The carrier turn-based engine
The turn-based engine is the carrier's own loop: it collects a sentence, posts it to Connect, Connect writes a reply, and the carrier reads that reply out. It needs no worker, no trunk and no fleet, which makes it the simplest way to answer a number. What it cannot do is let a caller interrupt — a turn is a whole sentence, by construction.
Gather, reply, redirect#
Connect answers a call by handing the carrier a document describing what to do: say this, then listen. The listening element is the gather, and when it has heard a sentence the carrier posts it to the turn URL, where Connect writes the next reply and hands back another document. The loop runs until somebody hangs up.
answer -> <Play greeting> <Gather> </Gather> <Redirect turn-url>
turn -> <Play reply> <Gather> </Gather> <Redirect turn-url>
silence -> <Play "sorry, I did not catch that"> <Gather> </Gather> <Redirect turn-url>The redirect after the gather is not decoration. Without it the document ends where the gather ends, and a carrier that heard nothing usable simply runs off the end and hangs up. That is not hypothetical: two real calls went greeting, fifteen seconds of listening, NORMAL_CLEARING, and the turn URL was never requested once. Empty speech now returns to the turn handler and gets an answer instead of a dial tone.
The voice it speaks in#
Until September 2026 every word a caller heard on this path was the carrier's own text-to-speech: two voices, sixteen European locales, and no Indian language at all. The sentence now goes to Google's Text-to-Speech API instead, comes back as a small 8 kHz MP3, is stored content-addressed and served sessionless, and the carrier is handed a play element rather than a speak element.
- Two model choices
gemini-tts, one voice across every language with a natural-language style instruction; orchirp3-hd, one voice per locale with a speaking rate.- Never silence
speak_urlreturns an empty string on any failure, and the carrier's own voice speaks the line. A failure downgrades the voice; it does not lose the sentence.- A refused key steps aside
- Ten minutes of cool-off rather than a retry storm. Saving a setting lifts the cool-off, so a corrected key takes effect at once.
- Both audiences
- The settings live on the Phone screen's Behaviour section for the Owner and for a customer, over one implementation.
When this is the right engine#
| If the line… | Turn-based | Realtime |
|---|---|---|
| Takes short, structured calls | Good fit — the loop is predictable | More machinery than the job needs |
| Needs the caller to interrupt | Not possible | Built for it |
| Must run without a worker fleet | Nothing to run | Needs workers checked in and capacity |
| Needs the fastest possible reply | Bounded by the carrier's own round trip | Bounded by the model — about 0.6 s to first audio |
| Is being set up in a hurry | Point the number at the answer URL | Trunk, dispatch rule and origination URI at the carrier |
There is a third consideration that is easy to miss: the turn-based path has no worker to lose. A workspace that cannot yet run or monitor a fleet gets a line that stays up on this engine, at the cost of a conversation that takes turns strictly.
Two failures that were configuration, not code#
- A host-less action URL.
_turn_urlemitted an action URL with no host whenpublic_urlwas unset. The greeting plays, the carrier has nowhere to post what it hears, and the call goes silent while the caller is still speaking. Nothing in Connect errors, because Connect is never asked anything. - One URL for two jobs.
/voice/{carrier}/statusserved as both the hangup URL and the status URL, and ended the call on *any* status — so aringingcallback hung up on a live caller. The lesson generalises: a handler that ends calls must be reached only by events that mean the call ended.
Both were invisible from inside the application and obvious from the carrier's call log. That log is the second source of truth for this engine, and comparing it against the calls list is the fastest audit available for the path.
Questions#
Can a caller interrupt the voice on this engine?
No. The carrier collects a whole sentence before Connect is asked anything, so there is no moment at which an interruption could be noticed. Interruption is one of the two things the realtime engine exists to provide, alongside speed.
What happens when the caller says nothing at all?
The gather ends with nothing usable, the redirect returns to the turn handler, and Connect answers with a short line to the effect that it did not catch that — then listens again. Before the redirect existed, that same silence ended the call.
Is the transcript on this path the carrier's or Connect's?
The carrier transcribes the caller's speech, which is what arrives at the turn URL. Connect's own words are known exactly, because Connect wrote them. That asymmetry is worth remembering when a caller's line reads oddly: it is the provider's reading of the audio, not Connect's.