cloud-websocket transport with the twilio carrier. Your number
points at a static piece of markup in the Twilio console, and that markup streams
the call straight to Pipecat Cloud, which starts your agent.
Your own
build/pipecat/README.md is the authority for your build, because it
was generated with your region and your agent name already filled in. This page
is the same route with the reasons attached, and it is the page to read before
the first call rather than after it.- Nothing of yours is hosted - why this route authenticates the way it does
- The values that have to agree - region, service host, markup, and the number
- The markup - what to paste into the TwiML Bin
- What the package declares - the connection file and the target, key by key
- Deploy with a warm instance - the setting that makes the call answerable
- Three different ways nothing happens - how to tell them apart in the logs
- Reading the agent’s log - the two commands, and the flag that hides the error
- Speakerphone makes the agent interrupt itself - and what protects the greeting
Nothing of yours is hosted, and that decides the security model
The generatedpcc-deploy.toml sets websocket_auth = "none". That is not a
shortcut. A TwiML Bin is static markup in a console, so it cannot fetch a token
before it opens the stream, which makes token authentication structurally
impossible on this route.
What limits who can start a session is knowing the AGENT.ORGANISATION string
your markup carries. Treat that string like a capability. It is not a secret in
the cryptographic sense, but anyone holding it can open sessions you pay for.
The values that have to agree
The route fails when any of these disagree, and the failures look nothing like each other.The stream address carries the region
deployment_region on the
target:
targets.yaml
An agent can only read a secret set from its own region. To move region, change
that one line, recompile, and paste the new address into the Bin. See Pipecat’s
regions guide for what
each region name covers.
The service host is your agent name and your organisation slug
_pipecatCloudServiceHost is AGENT_NAME.ORGANIZATION_NAME. The agent name is
filled in for you; the organisation is the one value the compiler cannot know:
The markup carries only the service host
A<Parameter> reaches this agent only if the emitted code reads one by that
name, and on an inbound call that name is _pipecatCloudServiceHost alone.
Adding the caller’s or the called number here is a common suggestion, and it
does nothing: no module in this package reads it.
The number must not be on a SIP trunk
A number attached to a trunk ignores its voice configuration, silently, so the Bin is never consulted. Read the state back rather than testing by ear:trunkSid is what you want. One number serves one target at a time, so
buy a second number if you
want both routes live.
The markup
Paste this from your ownbuild/pipecat/README.md, where the address and the
agent name are already correct. YOUR_ORGANIZATION is the only value you fill
in by hand.
<Say> line is a cold start cushion, not a requirement. Starting this agent
from cold takes a few seconds, and a caller who hears nothing hangs up. Drop the
line once you keep a warm instance.
What the package declares for this route
Two files carry this route: the connection that names it, and the target that names the connection. The connection is the short one.connections/twilio_voice.yaml
Every key a connection takes
sip | connector | cloud-websocket | daily-sip
required
The mechanism that carries the call.
cloud-websocket is this route, and it
is the one where Pipecat Cloud terminates the carrier’s stream itself.twilio
required
The carrier account behind the route. This route has no other carrier.
route key to environment variable name
Left out entirely on a package that only answers calls, which is what makes
the file above two lines long. A package that places a call, or hands one to
a person, needs
account_sid, auth_token and from_number here, and the
refusal says which behaviour asked for them.Every key a target takes
The target is the block under Deploy with a warm instance. These are its keys.livekit | pipecat | slng
required
pipecat on this route.exact x.y.z
required
The framework version pinned into the emitted project, written with all three
numbers.
targets.yaml names the one this release
supports.connection file stem
Which connection carries this target’s calls, named without the folder and
without the
.yaml. Required for a phone agent.platform region name
Where the platform deploys the agent. Pipecat takes exactly one, and it is
also the region in your stream address.
integer
How many instances the platform holds ready. On this route it is what makes
the call answerable: see below.
pins, sdk_language and per-target models: are the remaining target keys,
and targets.yaml covers all three.
Deploy with a warm instance
targets.yaml
warm_instances compiles to [scaling] min_agents in pcc-deploy.toml, so every
deploy of this build keeps the pool. It bills for that instance whether or not
anybody calls, which is why the compiler never adds it on its own.
Three different ways nothing happens
They look identical to the caller and they are easy to tell apart in the logs.
Only the first one is a wiring problem. The second is
warm_instances. The third is a secret that is
declared but not in the set you deployed with.
Reading the agent’s log
parse_telephony_websocket ... Parsed - Type: twilio, Data: {...}proves the Bin delivered, and shows the service host and the parameters it carried.Generating chat from context [...]dumps what the model actually saw. It is the fastest way to spot echo, fragmentation, or a polluted context.
Speakerphone makes the agent interrupt itself
A phone leg has no echo cancellation. A caller on speakerphone sends the agent’s own greeting back into the microphone, it is transcribed as caller speech, and the agent cuts itself off and carries the garbled turn in its context for the rest of the call. A Pipecat phone route protects the greeting by default for exactly this reason. Everything after the opening line stays interruptible, so tell testers to use the handset. Seeinterruption.protect to change what is
protected.
Where to go next
Human transfers
Cold and warm, and what each route can do.
Transfers on this route
Hand the caller to a person.