Workflows
A workflow is an agent built as a graph of steps. Use it when the conversation has to follow a path - qualify, then branch, then act - rather than being left to the model.
If a single prompt can describe the whole job, use a prompt agent instead. Workflows earn their complexity when there are real branches.
The dashboard offers the workflow builder for voice agents. A chat agent created in the dashboard is a prompt agent; the API accepts a chat agent in workflow mode.
Nodes
A workflow is nodes connected by edges. The node types:
| Node | What it does |
|---|---|
| Start | Where the conversation begins; can speak an opening message. |
| Conversation | The agent talks, with its own prompt for this step. |
| Say | Speaks a fixed line and moves on. |
| DTMF | Collects keypad digits on a call and stores them in a variable. |
| Wait | Speaks an optional message, then continues along its edges. If its edges are conditional, it holds until the caller's next reply picks one. |
| Tool | Calls a tool and stores the result, without the model deciding. |
| Transfer | On a call, hands the caller to another number. In chat it ends the session. |
| End | Ends the conversation, optionally with a farewell. |
Each conversation node has its own prompt for that step. A workflow-level global prompt is prepended to every one of them, which is where shared rules belong ("never quote a price") rather than repeating them per node.
Edges and routing
An edge connects one node to the next, and its condition decides when it is taken. After each caller turn, the outgoing edges are checked in this order:
- Global edges first. An edge marked
global: truecan be taken from any node, which makes it an escape hatch ("the caller asks for a human"). A satisfied global condition wins over the current node's own edges. - Deterministic conditions - free and predictable, so prefer these:
keyword- the caller's message contains the text, ignoring case.- on a variable:
equals,not_equals,contains,exists,not_empty,regex, and the numericgt,gte,lt,lte.
- AI intent - a description of what the caller means, e.g. "the caller wants to reschedule". Only runs if nothing deterministic matched and the node (or a global edge) has intent edges. One model call picks the best-matching description, or none. It uses the node's own model, falling back to the workflow's first conversation model and then the platform default.
always- an unconditional edge, taken last, so it never pre-empts an intent edge on the same node.
Because the router chooses between intent edges by their descriptions alone, give each intent edge on a node a clearly different description.
Intent routing fails safe: if the model call fails or no description matches, no
intent edge is taken. The conversation then follows the node's always edge if it
has one, and otherwise stays on the current step rather than jumping somewhere
wrong. Each edge taken by intent routing is recorded, with the description that
matched, in the session's Routing tab.
Routing runs before the reply is written, so the reply comes from whichever node the turn ends on.
Extraction
Any conversation node can capture values from what the caller says - a name, a date, an order number. See Variables and extraction.
Testing a workflow
The Playground shows which node a text conversation is on as it happens, and the session's Routing tab shows each edge intent routing took and why. When a workflow goes somewhere unexpected, that tab is the answer.