- Give each route its own number - why one number cannot serve two routes
- Which values you need depends on the route - the two credential groups, and every connection key
- First, a voice-capable number - the one requirement on the number itself
- The account trio - for
cloud-websocketand the LiveKit connector - The four SIP values - for the LiveKit
siproute - 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
- Then declare the names -
secrets:, and where the values live
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.
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, and the last step of the trunk
setup below covers that. Two numbers is less work after the first day.
Which values you need depends on the route
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.First, 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, and
voice capability is the whole requirement on it.
The account trio: Pipecat cloud-websocket and the LiveKit connector
These two routes talk to Twilio’s REST API in your name, so they need the account credentials.connections/twilio_voice.yaml
.env drives all of them.
Pointing the number at the agent
This part differs by route, and it is the part to get right:cloud-websocket: the number points at a static piece of TwiML in the console, which streams the call to Pipecat Cloud. 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. That address comes from the region in yourtargets.yaml. Pipecat over Twilio walks the whole route, including the organisation slug that is the most common thing to get wrong. -connector: the number’s voice webhook points atPOST /telephony/inboundon the public URL of the service you deploy.
The four SIP values: the LiveKit sip route
The LiveKitsip route reads four values from an Elastic SIP Trunk: the
termination domain, the credential’s username and password, and the attached
number. Setting the trunk up is a console walkthrough of its own, and it lives
on LiveKit over Twilio,
together with the LiveKit records the call needs afterwards.
Two settings on that trunk decide whether a transfer works: Call Transfer
(SIP REFER) with Enable PSTN Transfer, and the caller ID below.
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.
Then declare the names
Two files, and neither holds a value:agent.yaml
secrets: too, which is what puts it in
the generated .env.example and 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.
Where to go next
LiveKit over Twilio
The
sip route end to end: trunk, records, and what a rename breaks.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.