Channels
Channels are the communication methods that connect customers to your agent. TAC integrates with Twilio communication channels — including Voice, SMS, WhatsApp, RCS, and Chat — each with its own transport mechanism but sharing a unified callback interface.
All channels deliver messages to your message-ready callback, so you can handle messages from any channel with the same function. The ConversationSession object includes the channel field ("voice", "sms", "whatsapp", "rcs", or "chat") so you can customize responses per channel.
TAC registers the following endpoints on your server. All paths are defaults and can be customized in your server configuration.
| Endpoint | Method | Channel | Purpose |
|---|---|---|---|
/twiml | POST | Voice | Generates TwiML to connect incoming calls to Conversation Relay |
/ws | WebSocket | Voice | Streams real-time audio through Conversation Relay |
/conversation-relay-callback | POST | Voice | Handles call state changes and handoff data |
/webhook | POST | Messaging | Receives incoming messages from Twilio Conversations (SMS, WhatsApp, RCS, Chat) |
/ci-webhook | POST | — | Receives Conversation Intelligence events (optional) |
The Voice channel handles phone calls using Conversation Relay, which manages speech-to-text and text-to-speech over a WebSocket connection. Your agent works with text messages rather than audio streams.
- A caller dials your Twilio phone number.
- Twilio sends a webhook to your server's TwiML endpoint (
/twiml). - TAC responds with TwiML that connects the call to a Conversation Relay WebSocket.
- Conversation Relay transcribes the caller's speech and sends text to TAC over the WebSocket. TAC processes the message and delivers it to your
on_message_readycallback. - Your agent processes the text and sends a response through the Voice channel.
- Conversation Relay converts the text response to speech and plays it to the caller.
1from tac.channels.voice import VoiceChannel, VoiceChannelConfig23voice_channel = VoiceChannel(4tac,5config=VoiceChannelConfig(6memory_mode="always",7),8)
1async def handle_message_ready(2message: str,3context: ConversationSession,4memory: TACMemoryResponse | None,5) -> str | None:6llm_response = await generate_response(message)78await voice_channel.send_response(9conversation_id=context.conversation_id,10response=llm_response,11)
When a user interrupts the agent during a Voice conversation (for example, by speaking while the agent is still talking), TAC calls the on_interrupt callback. Use this to cancel in-progress LLM generation or other operations.
1async def handle_interrupt(2context: ConversationSession,3interrupt_data,4) -> None:5# Cancel any pending operations for this conversation6await cancel_pending_operations(context.conversation_id)78tac.on_interrupt(handle_interrupt)
The SMS channel handles text-based messaging through Twilio's Conversation Orchestrator webhooks. When a user sends an SMS to your Twilio phone number, Conversation Orchestrator routes the message to your webhook endpoint, and TAC processes it into your on_message_ready callback.
1from tac.channels.sms import SMSChannel, SMSChannelConfig23sms_channel = SMSChannel(4tac,5config=SMSChannelConfig(6memory_mode="always",7),8)910async def handle_message_ready(11message: str,12context: ConversationSession,13memory: TACMemoryResponse | None,14) -> str | None:15llm_response = await generate_response(message)1617await sms_channel.send_response(18conversation_id=context.conversation_id,19response=llm_response,20)
The WhatsApp channel handles messaging through Twilio's WhatsApp Business API. It uses the same webhook endpoint (/webhook) as SMS and follows the same messaging pattern.
Set the TWILIO_WHATSAPP_NUMBER environment variable to your WhatsApp-enabled number (format: whatsapp:+1234567890).
1from tac.channels.whatsapp import WhatsAppChannel, WhatsAppChannelConfig23whatsapp_channel = WhatsAppChannel(4tac,5config=WhatsAppChannelConfig(6memory_mode="always",7),8)
The RCS channel handles Rich Communication Services messaging. It uses the same webhook endpoint (/webhook) as SMS and WhatsApp.
Set the TWILIO_RCS_SENDER_ID environment variable to your RCS Sender ID.
1from tac.channels.rcs import RCSChannel, RCSChannelConfig23rcs_channel = RCSChannel(4tac,5config=RCSChannelConfig(6memory_mode="always",7),8)
All channels deliver messages to the same message-ready callback. Return the response string and TAC automatically routes it to the correct channel:
1async def handle_message_ready(2message: str,3context: ConversationSession,4memory: TACMemoryResponse | None,5) -> str | None:6llm_response = await generate_response(message)7return llm_response89tac.on_message_ready(handle_message_ready)
If you need per-channel behavior (for example, shorter responses for voice), check context.channel:
1async def handle_message_ready(2message: str,3context: ConversationSession,4memory: TACMemoryResponse | None,5) -> str | None:6if context.channel == "voice":7return await generate_response(message, max_tokens=100)8else:9return await generate_response(message)1011tac.on_message_ready(handle_message_ready)
Memory retrieval behavior is controlled by the memory_mode setting on each channel's config:
- Messaging channels (SMS, WhatsApp, RCS): Set
memory_modeto"always"to retrieve memory with each incoming message, or"once"to retrieve only on the first message in a conversation. - Voice: Set
memory_modeto"always"in theVoiceChannelConfigto retrieve memory for each utterance, or"once"for only the first utterance. Default is"never".
You can also retrieve memory on demand from within your callback:
1# Manual memory retrieval2memory = await tac.retrieve_memory(context, query="customer preferences")
Register a callback to handle conversation cleanup when a session ends:
1async def handle_conversation_ended(context: ConversationSession) -> None:2# Clean up resources for this conversation3conversation_history.pop(context.conversation_id, None)45tac.on_conversation_ended(handle_conversation_ended)
- Add TAC to your agent: Configure channels alongside tools, knowledge, and memory.
- Core concepts: Understand TAC's architecture and how channels fit into the system.
- Escalate to a human agent: Transfer conversations from your AI agent to a human agent.