Twilio SMS + Voice
One connected Twilio channel serves both texting and phone calls on your
Twilio numbers. SMS replies ride the webhook response (TwiML <Message>);
calls run a turn-based voice agent (<Gather input="speech"> + <Say>).
Channel keys reported to your flow: twilio_sms and twilio_voice
(conversation_context.channel); the dialled/texted number is
conversation_context.channel_account_id.
What you need
- A Twilio account with at least one phone number (SMS- and/or voice-capable). Trial accounts can only message/call verified numbers.
- The Account SID (
AC…) and Auth token from Twilio Console → Account Info. The auth token is stored in the Secret Manager and used to verify webhook signatures and to send messages. - A public HTTPS URL for Tools Anatomy (the console shows the exact webhook URLs to paste).
Official documentation
- Webhook security /
X-Twilio-Signature— https://www.twilio.com/docs/usage/webhooks/webhooks-security - Messaging webhook request parameters — https://www.twilio.com/docs/messaging/guides/webhook-request
- TwiML
<Message>(reply in the webhook response, < 1600 characters) — https://www.twilio.com/docs/messaging/twiml/message - TwiML
<Gather>speech input (SpeechResult,speechTimeout="auto",actionOnEmptyResult) — https://www.twilio.com/docs/voice/twiml/gather - TwiML
<Say>voices and languages (Polly., Google.) — https://www.twilio.com/docs/voice/twiml/say - Phone number configuration — https://www.twilio.com/docs/phone-numbers
Set up on Twilio
- Buy or pick a number: Console → Phone Numbers → Manage → Buy a number (tick SMS and Voice capabilities) or open an existing one under Active numbers.
- Copy credentials: Console home → Account Info → Account SID and Auth token (click Show). Consider a dedicated sub-account per business.
- Point the number at Tools Anatomy — either
- manually: on the number's page set Messaging → A message comes in to the SMS webhook URL (HTTP POST) and Voice → A call comes in to the Voice webhook URL (HTTP POST), then Save; or
- automatically: in the connect wizard's second step pick the number
from the Phone number list (loaded from your account) — Tools
Anatomy then sets
SmsUrl/VoiceUrl(HTTP POST) on that number for you.
- Trial accounts: verify the phone numbers you will text/call from (Console → Phone Numbers → Verified Caller IDs).
- Compliance: US A2P 10DLC / toll-free verification is required for application-to-person SMS in the US; complete it in Console → Messaging → Regulatory compliance before going live.
Connect in Tools Anatomy
/channels → Messaging channels → Twilio SMS + Voice → Connect. The
wizard has two steps:
Step 1 — credentials (validated against the Accounts API; the channel is created and the token stored in the Secret Manager):
| Field | Value |
|---|---|
| Account SID | AC… from Account Info |
| Auth token | the auth token (secret; never shown again) |
Step 2 — settings (lists are loaded live from your account, or curated from the Twilio docs where Twilio has no API):
| Field | Value |
|---|---|
| Phone number | pick one of the account's numbers (label shows voice/SMS capability) — its SMS and Voice webhooks are configured automatically; leave unset to paste the URLs yourself |
| Voice greeting | what the agent says when it answers (default "Hello! How can I help you today?") |
| Voice language | pick a language (en-US, en-GB, es-ES, fr-FR, ar-XA, ja-JP …); drives speech recognition and TTS |
| Text-to-speech voice | pick a <Say> voice for that language, grouped by provider/quality (Amazon Polly → Polly Neural → Polly Generative; Google Standard → Neural2 → Chirp3-HD). "Twilio default voice" leaves the attribute unset |
| Speech recognition model (advanced) | <Gather speechModel>: default, phone_call, Google STT v2 (googlev2_telephony …) or Deepgram (experimental_conversations, experimental_utterances, numbers_and_commands, deepgram_nova-2/3) |
| Enhanced recognition (advanced, deprecated) | <Gather enhanced>; only honoured with the phone_call model |
The voice and language lists are curated from the official Twilio
text-to-speech catalog (https://www.twilio.com/docs/voice/twiml/say/text-speech)
because Twilio offers no API to enumerate voices; any voice name from the
catalog can also be set through the API. The speech-model values come from
the <Gather> reference (https://www.twilio.com/docs/voice/twiml/gather).
Once a number is chosen, the channel shows an Open on Twilio link to that
number's configuration page in the Twilio Console
(https://console.twilio.com/us1/develop/phone-numbers/manage/incoming/<PN…>/configure).
Re-running Verify re-applies the webhook URLs and refreshes the number
list.
After connecting, the channel page lists the webhook URLs:
…/sms— Messaging → A message comes in…/voice— Voice → A call comes in…/voice/turn— internal (used by<Gather action>), nothing to configure…/status— optional status callback (accepted and ignored)
Verify shows every number on the account and whether it is routed here.
Identity we derive
| Canonical key | Source | Notes |
|---|---|---|
external_user_id |
From normalized to E.164 |
SIP/client callers keep the raw value |
channel |
twilio_sms (texts) / twilio_voice (calls) |
|
phone_number |
From (E.164), runtime_only |
only when it is a phone number |
display_name |
ProfileName (WhatsApp via Twilio) / CallerName (voice, if Caller ID lookup enabled) |
runtime_only, never a join key |
email |
— | not provided |
Context Vault identity channel: phone (shared with CallinAI/WhatsApp so
one number is one contact). channel_account_id = the To number.
Limits
- Twilio waits 15 seconds for a webhook response; the flow's reply must be produced within that window (the console's Playground timings are a good proxy). A slow flow gets the fallback message.
- SMS: one
<Message>body must be < 1600 characters; longer replies are split into several messages (each billed as multiple segments: 160 GSM-7 / 70 UCS-2 characters per segment). - Media (MMS) is not processed; the caller gets a text-only reply.
- Voice: each turn = speech recognition + flow + TTS.
speechTimeout="auto"ends listening on a natural pause; silence re-prompts once, then hangs up. - Voice recognition/TTS are billed by Twilio per minute; check https://www.twilio.com/en-us/voice/pricing.
Test it
- Text the number: you should get the flow's reply within seconds.
- Call the number: hear the greeting, say something, hear the reply.
- In
/channelsopen the channel → Threads: the SMS conversation and each call (thread =CallSid) with their transcripts. - Twilio Console → Monitor → Logs → Errors shows failed webhooks (11200 = HTTP retrieval failure: URL unreachable / non-2xx; 12100 = invalid TwiML).
Troubleshooting
- 401
invalid_signaturein the gateway log / 11200 in Twilio — the URL Twilio was configured with differs from the one the gateway builds (CHANNEL_GATEWAY_PUBLIC_BASE_URL). The signature covers the exact URL; fix the base URL or the number's webhook to match (both port variants are accepted). - Wrong auth token — Verify fails with platform rejected the credentials; rotate in Twilio and reconnect.
- Trial account — messages/calls only work with verified numbers and get a trial preamble.
- No voice reply, call hangs up immediately — the Voice webhook must be
the
…/voiceURL (not…/sms); check the number's Voice configuration.