Skip to main content
An inbound agent answers a call somebody else placed. The channel has to declare it, and your carrier has to be able to reach whatever is running the agent. On this page:

Declare the channel

agent.yaml

Every key a phone channel takes

Both directions are written out, even when only one of them is true.
realtime_audio | telephony
required
telephony is a phone call. realtime_audio is the browser channel, and it takes none of the keys below.
true | false
required
Whether this agent answers calls. true is what makes the rest of this page apply.
true | false
required
Whether this agent places calls. false on a line people only ring in on, unless the agent does a warm transfer, because that dials the destination itself.
list of control names
What the route has to support: cold_transfer, warm_transfer, dtmf_send, dtmf_receive, hold, hangup, voicemail_detection, ivr_navigation. A route that cannot do one is refused when you validate, which is before you spend a console evening on it.
hangup | leave_message
What to do when the agent reaches a voicemail box. It needs outbound: true, so an inbound-only agent leaves it out.
A telephony channel also makes capacity.peak_starts_per_second required and positive. Phone calls has the capacity: keys. This page follows examples/salon-concierge, the shipped package with an inbound phone route. It declares inbound: true with outbound: false, and it carries a target for each platform, so the same package proves the wiring on whichever route you pick. Check the prompt, the tools, and the models in your browser before you touch a carrier at all:
That loop stops exactly where the phone leg starts. A phone call reaches an agent that is deployed, so the rest of this page is the real call, through your own number, once you deploy.

Pick the target your carrier can reach

The package declares two targets, one per platform, on the route each platform recommends for Twilio: Both deploy to a managed platform, so either one can take a real call once it is live. pipecat needs one console object, a . livekit needs a full Elastic SIP Trunk and more console steps, and in return gets cold transfer, warm transfer, and voicemail detection. The routes table lists what each transport can do.

What you need

  • A Twilio account with a voice capable phone number.
  • For livekit: LiveKit Cloud set up and the lk CLI installed, or a LiveKit Server of your own.
  • For pipecat: Pipecat Cloud set up, and uv on your PATH to install its CLI.
  • Model provider keys.
Put the values in examples/salon-concierge/.env:
The last four are the trunk settings the livekit target’s connection names. They are in this list because agent.yaml declares every name the package writes, and the generated agent checks that whole list before it takes a call. If you are only testing the pipecat target you can put any placeholder there. The connections reference shows where each group of names comes from, and Get your Twilio details says which console value fills which name.
Every environment variable name must be UPPER_SNAKE: an uppercase letter, then only uppercase letters, digits, and underscores. A name like 2factor_api_key fails both rules at once, so Unmute refuses it during validation, before it deploys anything.

Deploy, then point the number at it

Each route has its own page from here, because the carrier steps differ completely:
  • livekit: deploy with lk agent create, set up the Elastic SIP Trunk, then run the generated script that creates the two LiveKit records. All three are required. LiveKit over Twilio is that route end to end.
  • pipecat: set the secret set, deploy with a warm instance, then paste the generated markup into a TwiML Bin and point the number at it. Pipecat over Twilio is that route end to end.
Each generated build/<target>/README.md is the runbook of record: it names your region, your agent, and your secret set.

Call the number

Call it. The agent answers and greets you. Speak, and it replies. One number serves one route at a time: a number attached to a SIP trunk ignores its voice configuration, so it cannot also point at a TwiML Bin. If you want both routes live, give each one its own number.

If the call does not arrive

The number in TWILIO_PHONE_NUMBER is not on the account behind TWILIO_ACCOUNT_SID, or it is not voice capable. Check it in the Twilio console.
The reason is printed in Twilio’s own words: geographic permissions, or a trial account that can only reach verified numbers. Fix it in the console and run again.
Check lk agent status or pipecat cloud agent status <agent-name> first: a deploy that is not ready never picks up the call. Then check that every name in .env.example is actually in the secret set you deployed with.
Each route page has the failures that belong to that route alone: the LiveKit records and the trunk’s origination on LiveKit over Twilio, the organisation slug and the cold start on Pipecat over Twilio.

Where to go next

Get your Twilio details

Which console value fills which name.

LiveKit over Twilio

The sip route end to end.