Procedures run on cascade voice calls. An S2S agent skips them, with a
warning on its read; text conversations (chat, SMS, WhatsApp) do not run
them.
Why not just a prompt
A system prompt can say “ask the party size, then the date, then the time”. On a short call it mostly works. As the script grows, the order lives only in the model’s reading of a long prompt, and three things go wrong:- Steps get skipped. The model jumps to the read-back with the phone number never asked, and nothing notices.
- Nobody can tell where a call went. Did the caller drop out at the date or at the read-back? A transcript has to be read to know.
- Every rule is in every turn. The model sees the whole script on every reply, including the parts that do not apply yet.
The concepts
A small one, a restaurant booking:
How it sits beside the system prompt
The two are separate inputs, built at different times:
The procedure adds only two things to the prompt: the list of
on_request
procedures the agent can start (names and descriptions, never a step’s text),
and the move_to_step tool. A start: "call" procedure needs no mention at
all.
After a tool runs, the model replies without a fresh window, since the
conversation no longer ends on the caller’s turn. So a move’s result carries
what the window would: the new step’s text, its tool, and where it moves next
(Then move on: confirmed (when the calendar event was created); ...). That
is how a step whose tool answers still knows to move on. The step’s own tool
says it again when it answers, since a skill load or another call can come
between the move and the tool: if one of the step’s moves now applies,
report it; if none does, stay. And when the model calls the tool of the next
step without moving there first, its result names that move, so the record
still ends where the call did (never for an escalate step, whose move would
run its transfer again).
Which wins when they disagree
Neither, formally: both are text the model reads, and TurnCall enforces only which moves are allowed, never wording. In practice the window wins on what to do now (it is specific, recent and last) and the prompt on how to say it. Two versions of one rule drift, and the model follows whichever it read last, so give each rule one home:
A side question is the prompt’s job. When a caller asks “do you have sushi?”
at the read-back, no move fits, so the procedure stays put; the prompt (or a
skill) answers, and the next turn’s window brings the agent back to the
read-back. Once the procedure finishes, the window stops and the prompt alone
runs the rest of the call.
With skills and tools
- A step’s
toolnames the tool the model should call there; the window shows it, and the save checks it is one the agent has. It does not run anything by itself: the model calls it. - A skill from a step. A step’s text can say “load the nonna_calendar_rules skill, then add the event following it”. The skill’s instructions join the prompt for the rest of the call. Keep such a skill to that step’s job: a skill written as its own script for the whole task competes with the procedure.
- Skills are for capabilities the agent may need at any point (menu questions, identity checks); a procedure is for a task with an order. One agent can have both.
What it buys you
- Order is checked, not hoped for. A skipped step is a refused move, which the model is told about and corrects; the caller usually never notices.
- Every call has a path. The call read and
call.endedcarryprocedures: the steps reached,completed,escalated_at,refused_moves. Completion and drop-off rates are a query, not a transcript read. - Escalation is an action, not a hope. An
escalatestep runs its transfer or handoff when the call reaches it, briefing included. - A smaller prompt per turn. The model reads the step it is on, not the whole script.
- Testable. In an eval, a move is a tool call, so a scenario asserts the path, and an agent that skips a step fails.
- No added pause. A move reported beside what the model says costs no second model call.
- Versioned with the agent, and editable as a form in the Console rather than as prose.
What it costs
- The model still judges every condition. TurnCall checks that a move is
allowed, not that its
whenis true. “The caller confirmed the phone number” is the model’s reading of the call. - One step at a time. A caller who answers two steps at once (“tomorrow, seven thirty”) still passes through both. Write the later step to accept an answer already given (“If the caller already gave a time, do not ask again: move on”), or merge the two steps.
- A step with a tool costs replies. Moving, loading a skill and calling a tool are each a model reply, plus the tool’s own time. A step that loads a skill and calls a slow API can be the slowest turn of the call.
- Little of the graph is visible. The model sees
window_depthsteps ahead and nothing further, so a rule it needs throughout belongs in the prompt, not in a later step. - Cascade voice only. S2S agents and text conversations run the prompt alone.
When to use one
Use a procedure when the task has an order that matters, a point where it must hand over, or an outcome you want to count: bookings, diagnostics, identity verification, cancellations, intake forms. Keep to the prompt (or a skill) for open conversation, a single question, or knowledge the caller can ask about in any order.Writing a good one
- One step, one thing. A step’s text is what to do now. “Ask for a phone number, then read it back” is one thing; “ask the name and the phone” is two steps.
- Write
whenas something said on the call. “The caller confirmed the email you read back” works; “the email is valid” asks the model to know what it cannot. - Give every hard step a way out. A move to an
escalatestep (“the calendar tool failed twice”) keeps a call from going round in circles. - Tell the caller in the step’s text. The model says it in the same reply as the move: “Warmly explain that our host takes care of this booking, and that you are putting them through now.”
- Then read the calls.
refused_movesabove zero and paths that stop early show the steps to rewrite.