Skip to main content

Transitions, Variables & the Director

A Voice Workflow is a state machine: the caller is always sitting on exactly one node, and after each thing they say the engine decides where to go next. This page explains the machinery behind that decision — the variables the flow tracks, the edge conditions that wire nodes together, the resolution order the engine follows every turn, and the Director (a fast LLM) that extracts data and picks ambiguous routes. For the nodes these transitions connect, see Node Types. To build and arrange the graph, see The Workflow Builder.

Variables

Variables are the workflow’s memory. You declare them in the Variables panel (the right sidebar in the builder), reference them anywhere as {{name}}, and the flow uses them for two things:
  • Collection — a Conversation or Collector node extracts declared variables from what the caller says, and requires certain ones before the flow may move on.
  • Branching — edge conditions and Condition nodes read variables to decide the next node.
Each variable is typed, and may optionally be constrained to an enum (a fixed list of allowed values, useful for keeping the agent on a known set of options).
TypeHoldsExample valueNotes
stringFree text"Mumbai"Use an enum to restrict to known options
integerWhole numbers42Compare with >, <, >=, <= in equations
numberDecimals19.99For amounts, durations, scores
booleantrue / falsetrueIdeal for branch flags (e.g. {{slot_available}})
Give variables clear, lowercase names you can read inside {{ }} — for example {{caller_name}}, {{preferred_date}}, {{slot_available}}. The same name is reused when an API Request maps a response field back into a variable, so consistency pays off.

Edge conditions

Edges are top-down: each edge leaves the bottom of one node and connects to the top of another, and the canvas prints each edge’s condition as a label so you can read the routing at a glance. You set an edge’s condition in the edge condition editor (select an edge; the Inspector tab switches to the editor). It has a single mode toggle with three options:

Unconditional

The “else” path. No test — taken when no other edge from this node matches.

Prompt

A natural-language condition the Director judges (a textarea), e.g. “caller agreed to continue”.

Equation

A deterministic expression evaluated in code, e.g. {{age}} > 18. A guided builder (variable / operator / value) plus a raw-expression option.

Prompt conditions

A prompt condition is plain English describing when this edge should fire. The Director reads the caller’s latest turn and decides whether the condition is met. Use prompt conditions when intent is fuzzy and only a model can judge it:
  • caller agreed to continue
  • caller wants to speak to a human
  • caller raised a pricing objection

Equation conditions

An equation is a deterministic expression over variables, numbers, quoted strings, and booleans. Because equations run in code — not through the model — they always resolve the same way for the same inputs.
OperatorMeaningExample
existsThe variable has been captured{{email}} exists
==Equal to{{slot_available}} == true
!=Not equal to{{plan}} != "free"
>Greater than{{age}} > 18
<Less than{{quantity}} < 5
>=Greater than or equal{{score}} >= 0.8
<=Less than or equal{{wait_minutes}} <= 10
CONTAINSSubstring / membership{{city}} CONTAINS "Mumbai"
ANDBoth sides true{{age}} >= 18 AND {{consent}} == true
OREither side true{{plan}} == "pro" OR {{plan}} == "enterprise"
Operands may be {{variable}} references, bare numbers, "quoted strings", or true / false.

Resolution order

This is the most important rule on the page. After each caller turn, the engine decides the next node by checking, in this exact order:
1

Equation edges first (deterministic)

Every equation edge leaving the current node is evaluated in code, top to bottom. The first one that is true wins — the flow takes that edge immediately. No model is involved, so this step is fully predictable.
2

The Director's prompt-edge pick

If no equation edge matched, the Director’s chosen prompt-condition edge is taken — but only if the node’s require[] variables are all satisfied. If a required variable is still missing, the flow does not leave (see Staying on a node).
3

Global enter-conditions

If neither of the above produced a transition, the engine checks whether any global node’s enter-condition matches. If one does, the flow jumps to that global node, handles the situation, then returns.
4

Otherwise, stay

If nothing matched, the caller stays on the current node and it speaks again.
Why equation-first matters. Equations are checked deterministically before the model ever sees the routing decision. That makes critical branches — eligibility gates, “did we get a yes”, “is a slot available” — debuggable and reproducible: the same variables always take the same edge, every call. Reserve prompt conditions for the genuinely fuzzy cases the model is good at.

The Director

The Director is a fast LLM that runs each caller turn to do two jobs:
  1. Extract the current node’s declared variables from what the caller just said (filling in {{name}}, {{preferred_date}}, and so on).
  2. Pick which prompt-condition edge is met, when routing requires judgement.
Equation conditions and global enter-conditions are evaluated alongside this (equations in code, as above) — the Director only owns the prompt-based part of the decision. The Director is gated: it only runs when routing is genuinely ambiguous, so it does not add latency to turns that an equation already resolves. You choose the Director model and temperature in the builder’s Settings tab. The default is a fast model; see Publishing & Going Live for guidance on choosing it.
A slow Director model adds latency on every turn that needs routing — the caller waits longer before the agent replies. Keep the Director on a fast model and push deterministic branches into equation edges; only reach for a heavier model if extraction quality genuinely demands it.

require[] and staying on a node

A Conversation or Collector node can mark some of its variables as require[] — the flow may not leave until those variables are captured. If the caller hasn’t yet given a required value, the engine stays on the node and re-asks, turn after turn, until it has what it needs. This is how you guarantee data before moving on: a booking node that requires {{preferred_date}}, or a collector that requires a verified {{email}}, will keep the caller on that phase until the value is in hand. Only then does Step 2 of the resolution order (the Director’s prompt-edge pick) become eligible. Equation edges are still checked first regardless — so a require gate governs prompt-edge transitions, not hard equation branches you’ve wired for edge cases like an early exit.

Global nodes and interruptions

A global node is a Conversation node marked Global with an enter-condition (a prompt or an equation). It is reachable from any interruptible node — when its enter-condition matches, the flow jumps to the global node no matter where the caller currently is. This is how you handle situations that can come up anywhere in the call: the caller raises a pricing objection, asks for a human, or goes off-script. The global node handles the situation, then returns the caller to the node they were on so the main flow resumes where it left off.
  • Enter-condition — a prompt (e.g. “caller asks to speak to a human”) or an equation, evaluated as part of the resolution order’s globals step.
  • Interruptible toggle — each Conversation node controls whether globals may interrupt it. A node with interrupts off is shielded from globals during its turn.
  • Cooldown — measured in turns, this prevents a global from re-triggering immediately after it just ran, so the caller isn’t bounced back into it on the very next turn.
Globals fire only after equation edges and the Director’s prompt-edge pick have had their chance (step 3 of the resolution order). A clean, in-script transition always wins over a global interruption.

Putting it together

A typical turn looks like this: the caller speaks → the Director extracts the current node’s variables → equation edges are checked in code (first-true-wins) → if none match and require[] is satisfied, the Director’s prompt-edge is taken → otherwise a global may interrupt → otherwise the caller stays. The destination node then produces the reply. For the worked end-to-end example — an API call that maps a response field into a boolean a Condition then branches on — see the API Request Node. To start from a ready-made graph, see Workflow Templates.