Post

Building Voice AI Agents with Telnyx and Ruby on Rails

Building Voice AI Agents with Telnyx and Ruby on Rails

Introduction

As AI continues to evolve, the integration of Large Language Models (LLMs) with global telecommunications infrastructure is unlocking incredible possibilities. Imagine a customer calling your business and speaking naturally with an AI agent that understands context, can look up order statuses in real-time, and responds with lifelike voice synthesis.

This is where platforms like Telnyx come into play. By providing Voice AI Agents with built-in global telco infrastructure, Telnyx bridges the gap between advanced AI models and traditional telephony. In this post, we’ll explore how to orchestrate these agents using a Ruby on Rails backend.

The Architecture of a Voice AI Agent

A Voice AI Agent handles several complex tasks in milliseconds:

  1. Telephony: Answering the incoming SIP or PSTN call.
  2. Speech-to-Text (STT): Converting the caller’s spoken words into text.
  3. Inference: Passing the text to an LLM (like OpenAI’s GPT-4 or Anthropic’s Claude) alongside custom system prompts and tools.
  4. Text-to-Speech (TTS): Synthesizing the AI’s response back into a natural-sounding voice.

Telnyx abstracts this pipeline via their Mission Control Portal. Your Ruby on Rails (or Python) application simply acts as the orchestrator, receiving webhooks when events occur and optionally providing real-time data through “Tools” or “Skills” that the AI can trigger during the conversation.

Code Example: Handling Telnyx Webhooks in Rails

When a call comes in, Telnyx sends a webhook to your server. Here’s how you can respond and connect the call to your configured Voice AI Assistant.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# app/controllers/telnyx_webhooks_controller.rb
class TelnyxWebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def create
    event = params.fetch(:data, {})
    event_type = event.fetch(:event_type, '')
    payload = event.fetch(:payload, {})

    case event_type
    when 'call.initiated'
      # Answer the call
      call_control_id = payload[:call_control_id]
      Telnyx::Call.answer(call_control_id)
      
    when 'call.answered'
      # Connect the call to our AI Agent configured in Telnyx Mission Control
      call_control_id = payload[:call_control_id]
      assistant_id = ENV['TELNYX_AI_ASSISTANT_ID']
      
      # Use the Telnyx gem to bridge the call to the AI Assistant
      Telnyx::Call.bridge(
        call_control_id,
        assistant_id: assistant_id
      )
    end

    head :ok
  rescue => e
    Rails.logger.error "Telnyx Webhook Error: #{e.message}"
    head :unprocessable_entity
  end
end

Explanation

  • skip_before_action :verify_authenticity_token: We bypass CSRF protection because this endpoint receives automated POST requests from Telnyx.
  • call.initiated & call.answered: We listen for the call lifecycle events. Once answered, we bridge the call to our pre-configured AI Assistant using its unique ID.
  • Telnyx::Call: We utilize the telnyx Ruby gem to issue commands back to the telephony platform.
  • Scalability: By handling this via webhooks, your Rails app remains stateless and highly scalable, while Telnyx handles the heavy lifting of audio streaming and AI inference.

Conclusion

Building next-generation voice applications doesn’t mean you have to invent your own telephony stack or stitch together disparate STT/TTS services. By leveraging Telnyx’s robust infrastructure and combining it with the rapid development capabilities of Ruby on Rails (or Python), you can deploy intelligent, conversational AI agents capable of transforming your customer interactions.

Suggested Reading

This post is licensed under CC BY 4.0 by the author.