Connect by JBRH Open Connect

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.

Status
Available What this means
Audience
both
Channels
phone
In the app
#/calls
Last verified
Product version
6.3.2

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; or chirp3-hd, one voice per locale with a speaking rate.
Never silence
speak_url returns 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-basedRealtime
Takes short, structured callsGood fit — the loop is predictableMore machinery than the job needs
Needs the caller to interruptNot possibleBuilt for it
Must run without a worker fleetNothing to runNeeds workers checked in and capacity
Needs the fastest possible replyBounded by the carrier's own round tripBounded by the model — about 0.6 s to first audio
Is being set up in a hurryPoint the number at the answer URLTrunk, 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#

  1. A host-less action URL. _turn_url emitted an action URL with no host when public_url was 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.
  2. One URL for two jobs. /voice/{carrier}/status served as both the hangup URL and the status URL, and ended the call on *any* status — so a ringing callback 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.