- Start with the route - the values you need depend on it, and so does everything else
- 1. Get a voice-capable number - the one requirement on the number itself
- Give each route its own number - why one number cannot serve two routes
- 2. Get the values your route needs - the two credential groups, side by side
- 3. Point the number at your agent - which console object, per route
- 4. Declare the names in your package -
secrets:, and where the values live - Caller ID for a transfer target - the trunk setting that decides whether a transfer connects
- If your trunk is in a Twilio Region - what a region changes, and what it does not
- Where to go next
Unmute never buys a number, creates a trunk, or changes anything on your carrier
account, at compile time or afterward. Every value below is one you set yourself,
in the Twilio Console.
Start with the route
Twilio reaches an agent three ways, and they need different values. Find your row first, then read only the parts this page marks for it.
The two groups are different credentials, not two names for one thing. The
account trio identifies your account to Twilio’s REST API. The four SIP values
are one trunk’s own dial-out settings, and they live in a different part of the
console.
Every key a connection takes
Three keys. The first two pick the route, and the third names the variables that hold its values.sip | connector | cloud-websocket | daily-sip
required
The mechanism that carries the call. It decides which
environment keys the
file accepts, so changing it changes the group of values you need.twilio | telnyx | plivo
required
The carrier account behind the route.
twilio on every route on this page.route key to environment variable name
Which variable holds each value. The keys on the left are fixed by the route:
account_sid, auth_token and from_number for the account trio,
sip_address, sip_username, sip_password and from_number for the SIP
route. A key from another route is refused, and the refusal lists the set
this route accepts.1. Get a voice-capable number
Phone Numbers, Manage, Buy a number, with the Voice capability. Skip this if you already own the number you want the agent to use. Whatever you buy or already own is the value offrom_number, or
SIP_FROM_NUMBER on the SIP route. It is also the caller identity the person you
dial sees. Voice capability is the whole requirement on it.
Write it in E.164 form: a plus, the country code, then the rest, no spaces.
Give each route its own number
A number attached to a SIP trunk ignores its voice configuration completely, and does so silently. So one number cannot serve a TwiML Bin and a SIP trunk at the same time. If you want both routes live, buy a second number:
You can also swap a single number back and forth. Two numbers is less work after
the first day.
2. Get the values your route needs
Read the half your row in Start with the route points at, and skip the other one.The account trio
For Pipecatcloud-websocket and the LiveKit connector. Both talk to Twilio’s
REST API in your name, so they need the account credentials.
connections/twilio_voice.yaml
.env drives all of them.
The four SIP values
For the LiveKitsip route. All four come off one Elastic SIP Trunk.
connections/twilio_sip.yaml
3. Point the number at your agent
Having the values is not the same as routing the calls. Each route points the number at something different, and this is the part to get right.
The SIP row is the one people miss, because you attach the number from inside
the trunk and not from the number’s own page.
Attach the number to the trunk
has the console path.
On
cloud-websocket there is no URL of yours to configure, because nothing of
yours is hosted. Your build’s generated README dictates the exact markup,
including the regional stream address, which comes from the region in your
targets.yaml. Pipecat over Twilio
walks it, including the organisation slug that is the most common thing to get
wrong.
4. Declare the names in your package
Two files, and neither holds a value:agent.yaml
secrets: too. That is what puts it
in the generated .env.example and in the startup check. The values go in .env
locally, and in your platform’s secret store for a deployment.
Your build’s build/<target>/README.md is the authority for your own route. It
was generated from your package, so it already names your region and your
number.
Caller ID for a transfer target
A cold transfer is a SIP REFER: Twilio receives it and places a new call to the destination. The trunk decides what caller ID that new call presents, and the two choices behave very differently.
Transferee is the nicer behaviour, because the person receiving the transfer sees
the customer rather than your own line. It only works where the receiving carrier
tolerates a caller ID that belongs to nobody on your account. Present a Spanish
mobile number from a UK trunk to a Spanish carrier and it is rejected on the spot.
How that failure looks, so you recognise it rather than debugging your agent:
- The agent logs
cold transfer failed after 0s: SIP call failed: 486 Busy Here. - Twilio’s call log shows a child call under the original call, with the
original caller’s number in
From, status Busy, duration 0 sec, cost blank, and no PCAP.
If your trunk is in a Twilio Region
Twilio can hold resources in a region such as Ireland (IE1) rather than in the default one. If you set a number’s Active Region and create the trunk there, three things change:- The trunk gets a SID that the default API cannot see. A lookup returns
404 not foundeven though the console shows the trunk. - Regional endpoints such as
api.dublin.ie1.twilio.comneed regional API credentials. Your account SID and auth token get401 Authenticatethere. - The number’s Active Region and its trunk must be in the same region, and the console only shows you the configuration for the region you are viewing.
Where to go next
LiveKit over Twilio
The
sip route end to end: the trunk, the two records, and the failures.Pipecat over Twilio
The
cloud-websocket route end to end.connections/<name>.yaml
The file these values fill.
Transfers on LiveKit
Hand the caller to a person.