> ## Documentation Index
> Fetch the complete documentation index at: https://unmute.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Unmute compiles to exactly three targets. Pipecat and LiveKit are code targets: compile writes a Python project you run. SLNG is a hosted target: compile writes a deployment body and SLNG runs the agent, so it has no `unmute dev`. Those three are the only values `provider` accepts in `targets.yaml`. Deepgram and ElevenLabs appear in these docs as model vendors, which is not the same thing as a target, and `slng` is both.
> The Go structs in `internal/spec` and `internal/ir` are the schema truth. Check a field against them, or run `unmute validate`, rather than against what you remember.

# Inbound calls

> Take a real call from your own phone number, once your agent is deployed.

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](#declare-the-channel) - `channels:`, key by key, for an agent that answers
* [Pick the target your carrier can reach](#pick-the-target-your-carrier-can-reach) - two routes, two amounts of console work
* [What you need](#what-you-need) - the accounts, the CLIs, and the names in `.env`
* [Deploy, then point the number at it](#deploy-then-point-the-number-at-it) - compile, deploy, then your route's carrier step
* [Call the number](#call-the-number) - the real call, and why one number serves one route
* [If the call does not arrive](#if-the-call-does-not-arrive) - the failures that belong to no route in particular

## Declare the channel

```yaml agent.yaml theme={null}
channels:
  phone:
    kind: telephony
    inbound: true
    outbound: false
```

### Every key a phone channel takes

Both directions are written out, even when only one of them is `true`.

<ParamField path="kind" type="realtime_audio | telephony" required>
  `telephony` is a phone call. `realtime_audio` is the browser channel, and it
  takes none of the keys below.
</ParamField>

<ParamField path="inbound" type="true | false" required>
  Whether this agent answers calls. `true` is what makes the rest of this page
  apply.
</ParamField>

<ParamField path="outbound" type="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.
</ParamField>

<ParamField path="required_controls" type="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.
</ParamField>

<ParamField path="on_voicemail" type="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.
</ParamField>

A telephony channel also makes `capacity.peak_starts_per_second` required and
positive. [Phone calls](/telephony/overview#every-key-capacity-takes) 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:

```sh theme={null}
unmute dev examples/salon-concierge --target pipecat
```

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:

| Target    | Transport         | How the call arrives                                                         |
| --------- | ----------------- | ---------------------------------------------------------------------------- |
| `livekit` | `sip`             | your number is attached to a Twilio Elastic SIP Trunk pointed at LiveKit SIP |
| `pipecat` | `cloud-websocket` | your number points at a static TwiML Bin whose stream goes to Pipecat Cloud  |

Both deploy to a managed platform, so either one can take a real call once it
is live. `pipecat` needs one console object, a <Tooltip tip="A small piece of markup you paste into Twilio that tells it where to send the call.">TwiML Bin</Tooltip>. `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](/telephony/overview#the-routes) lists what each transport can do.

## What you need

* A Twilio account with a voice capable phone number.
* For `livekit`: [LiveKit Cloud](/deploy/livekit-cloud) set up and the `lk`
  CLI installed, or a LiveKit Server of your own.
* For `pipecat`: [Pipecat Cloud](/deploy/pipecat-cloud) set up, and `uv` on
  your PATH to install its CLI.
* Model provider keys.

Put the values in `examples/salon-concierge/.env`:

```bash theme={null}
OPENAI_API_KEY=sk-...
SLNG_API_KEY=...
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_PHONE_NUMBER=your_number_in_e164
SIP_TRUNK_HOSTNAME=your-trunk.pstn.twilio.com
SIP_AUTH_USERNAME=your_trunk_username
SIP_AUTH_PASSWORD=your_trunk_password
SIP_FROM_NUMBER=your_number_in_e164
```

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](/reference/connections-yaml) shows where each group of
names comes from, and [Get your Twilio details](/telephony/twilio) says which
console value fills which name.

<Warning>
  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.
</Warning>

## Deploy, then point the number at it

```sh theme={null}
unmute compile examples/salon-concierge
```

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](/telephony/livekit-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](/telephony/pipecat-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](/telephony/twilio#give-each-route-its-own-number).

## If the call does not arrive

<AccordionGroup>
  <Accordion title="phone number was not found on this Twilio account">
    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.
  </Accordion>

  <Accordion title="Twilio refuses the call">
    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.
  </Accordion>

  <Accordion title="the deployed agent never answers">
    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.
  </Accordion>
</AccordionGroup>

Each route page has the failures that belong to that route alone: the LiveKit
records and the trunk's origination on
[LiveKit over Twilio](/telephony/livekit-twilio#if-the-call-does-not-arrive),
the organisation slug and the cold start on
[Pipecat over Twilio](/telephony/pipecat-twilio#three-different-ways-nothing-happens).

## Where to go next

<Columns cols={2}>
  <Card title="Get your Twilio details" icon="key" href="/telephony/twilio">
    Which console value fills which name.
  </Card>

  <Card title="LiveKit over Twilio" icon="phone" href="/telephony/livekit-twilio">
    The `sip` route end to end.
  </Card>
</Columns>
