What a variable is
A variable is a named piece of data that persists for the duration of one call. Anything an Ask node collects becomes a variable. Anything an Action node returns becomes a variable. Anything on the audience row for the contact being called is available as a variable from the moment the call starts.
You reference a variable with double curly braces. The brace expression is replaced with the value at the moment the node runs.
Got it, {{contact.name}}. I've booked you for {{state.appointment_time}}.
Variables are scoped to the call. They do not carry from one call to the next, and one call cannot read another call's state.
The two namespaces
| Prefix | Source | Set when |
|---|---|---|
contact. | The audience row this call is for | Before the call starts |
state. | Ask nodes and Action node results | During the call, as nodes run |
contact.name, contact.phone_number, and contact.country_code exist on every audience row because the CSV import requires those headers. Any extra column in your CSV becomes a custom field on the same row. See Audiences for the import format.
state. names are the ones you choose. When you configure an Ask node, the "where to save the answer" field is the variable name. Save to severity and you read it back as {{state.severity}}.
Where you can use them
You can drop a variable reference into any of these:
- The text of a Say node
- The question text of an Ask node
- The parameters of an Action node (calendar event title, SMS body, webhook payload, CRM field value)
- The condition of a Decision node
A Decision node compares against the value, not the brace text. {{state.severity}} >= 8 evaluates the number the Ask node saved.
A worked flow
The urgent-care intake example from Workflow nodes threads three variables through it.
- Ask node: "What's your date of birth?" — save to
dob. - Ask node: "How severe are your symptoms, one to ten?" — expected answer type number, save to
severity. - Decision node:
{{state.severity}} >= 8branches to a Transfer Call action. - Book Calendar action on the lower-severity branches returns the booked slot, saved as
appointment_time. - Say node: "Thanks {{contact.name}}, you're booked for {{state.appointment_time}}."
The Say node at step 5 only works on branches that actually ran step 4. On the transfer branch, state.appointment_time was never set.
What goes wrong
The transcript shows the literal {{state.x}}. The name in the reference does not match the name the Ask node saved to. A Say node reading {{state.severity}} against an Ask node that saved to severity_score renders the braces verbatim, and the caller hears them read aloud. Names are matched exactly, including case and underscores.
A variable is empty because its branch never ran. Every state. variable is set by one specific node. If the flow took a branch that skipped that node, the variable does not exist. Trace the paths that reach a node before you reference a variable in it, and prefer references set on the same path.
A custom field is missing on some contacts. Optional CSV columns are per-row. If half your rows have account_tier and half do not, {{contact.account_tier}} is empty for half your calls. Handle the empty case in a Decision node or write the Say node so it reads acceptably without the value.
An empty cell became a literal string. A CSV cell containing null or n/a imports as the text "null" or "n/a", not as empty. The Finn will say it. Leave the cell blank instead.
The type does not match the comparison. A Decision node doing a numeric comparison needs a number. If the Ask node was configured for free text, the caller saying "about an eight" saves a string. Set the expected answer type on the Ask node to match how you plan to compare it.
Free-form mode uses a shorter form
Outside the workflow editor, in a Finn's plain instruction text, audience custom fields are referenced without the contact. prefix:
If
{{account_tier}}is "Enterprise", mention that they have priority support.
This is the free-form syntax described in Agent variables. Inside a workflow, use the prefixed form.
Checking your work
Test on Chat shows each node's inputs and outputs in real time, so you can see the value a variable held when a node ran and where a branch read the wrong one. Do this before Test on Call. Details in Workflow testing.