Skip to content

Flow Builder Concepts

The agent builder lists every tab and field; this page explains the concepts — the four things people most often ask after building their first agent: when to use freeform vs a flow, what Say and Collect actually do, how branch conditions are evaluated, and when changes go live.

The first choice on the agent’s Overview tab is the conversation mode:

FreeformFlow
How it worksThe AI improvises every reply from your greeting + persona promptThe agent walks the visual graph step by step
Setup effortMinutes — write a promptMore — build and connect nodes
Wording controlThe AI phrases everythingFixed lines are spoken word-for-word; AI lines only where you ask
Caller answersLive in the conversation only (post-call extraction can still pull fields from the transcript)Captured into variables ({{vars.name}}) you can branch on, speak back, or send to APIs
Routing the callThe AI ends or transfers when its prompt says to ([hangup] / [transfer])Explicit Transfer / Hang up nodes at exact points in the graph
Mid-call integrationsNoneTool call / HTTP action / Send message / Webhook nodes
PredictabilityConversational, less predictableDeterministic steps; fully deterministic in Strict routing mode

Use freeform when the call is conversational and the outcome is simple — reception and after-hours intake (“take a name and a message”), FAQ answering, lead screening that ends in a transfer. It’s the fastest way to a working agent, and a strong persona prompt plus Scope & refusals keeps it on the rails.

Use a flow when you need structure — specific answers captured into variables, guaranteed wording at specific moments (disclosures, menus), branching (“sales or support?”), or mid-call API calls and notifications.

Switching modes is non-destructive: a freeform agent keeps its saved flow dormant, and switching back to Flow mode resumes it.

These two nodes are the core of every flow, and they divide cleanly:

  • Say speaks. Collect listens. A Say node says its line and immediately moves to the next node — it never waits for the caller. If the agent should hear the caller, the flow needs a Collect node there.

A Say node has two source modes:

  • Fixed text — spoken exactly as written. Supports {{variables}}:

    Thank you for calling {{company_name}}. This call may be recorded.

    Use fixed text whenever the wording matters — greetings, disclosures, menu prompts.

  • AI-generated — you write a prompt, and the AI writes the actual line at call time in the persona’s voice:

    Warmly acknowledge the reason the caller gave ({{vars.reason}}) and
    reassure them someone will follow up today.

    The spoken line varies call to call. Use it for natural acknowledgements and summaries — never for lines that must be word-for-word. An AI line can’t promise an action the flow doesn’t actually perform.

Each Say node also has a Caller can interrupt toggle — when the agent’s Barge-in setting is on, callers can talk over interruptible lines; mark a line non-interruptible to always play it in full (e.g. a legal disclosure).

A Collect node optionally speaks a prompt (fixed text, supports {{variables}}), then waits for the caller and stores what they said in a variable:

  • Variable name → reference it anywhere downstream as {{vars.name}} — in Say text, branch conditions, API URLs and bodies.
  • Caller input can be Speech (the default — the answer is transcribed) or Keypad (DTMF) — digits the caller presses are stored in the variable instead, for classic “press 1 for sales” menus (branch on vars.choice equals 1).
  • The silence timeout on the node controls how long the agent waits after the caller stops before considering the answer complete.

A Branch node holds no logic itself — its outgoing edges do. Select an edge in the builder to set its condition.

1. Compare a variable — a deterministic check against a collected variable or call metadata:

ComparatorMatches when…
equals / does not equalexact string match (numbers compared as text)
containsthe value appears anywhere, case-insensitive
matches regexthe pattern matches, case-insensitive (an invalid pattern simply never matches)
greater/less than, at least, at mostnumeric comparison
is set / is emptythe variable has / doesn’t have a value

The variable is a path: vars.reason (a Collect result), caller.number, caller.name, call.id. Deterministic checks are exact, instant, and cost nothing.

2. Caller intent (AI) — you write a yes/no question and the AI judges the caller’s most recent reply against it:

Question: does the caller want to speak to sales? Take this path when intent is: yes

Use AI intent when the same meaning arrives phrased a hundred ways (“gimme sales”, “I’d like to buy something”, “who do I talk to about pricing?”). Each intent edge is its own independent yes/no check.

3. Combinators — All of (AND) / Any of (OR) / Not — nest the above into one condition, e.g. all of [caller intent is “support”, vars.tier equals pro].

When the call reaches a branch, the edges are checked in order, and:

  1. The first edge whose condition matches is taken.
  2. If no condition matches, the edge marked “else” / fallback is taken.
  3. With no else edge either, an unconditional edge (one with no condition) is used if present.

A branch with no matching edge at all is a dead end: the caller is routed to the agent’s Fallback destination (Behavior tab), or the call ends if none is set. Always give a branch an else edge.

The agent’s Routing mode (Behavior tab) has two settings:

  • Flexible (default) — AI-generated Say lines and AI-intent conditions are allowed.
  • Strict — deterministic only. Every Say must be fixed text and every condition explicit (compare/regex); saving a strict agent whose flow still contains an AI Say node or an AI-intent edge is rejected with the offending node/edge named. At call time, anything ambiguous falls to the else edge instead of the AI guessing.

Strict mode is for flows where predictability beats flexibility — compliance scripts, DTMF menus, regulated disclosures. Strict agents show a Strict badge on the agents list.

A small front-desk flow that greets, captures a name, and routes by intent:

Start
└─ Say (fixed): "Thank you for calling {{company_name}}."
└─ Collect → variable: name
prompt: "May I have your name?"
└─ Collect → variable: reason
prompt: "Thanks {{vars.name}} — are you calling about
sales, or do you need support?"
└─ Branch
├─ edge: Caller intent (AI)
│ question: "does the caller want sales?" → Transfer 7001 (sales)
├─ edge: Compare — vars.reason contains "support" → Transfer 7002 (support)
└─ else edge → Say (fixed): "Let me take a message."
└─ Collect → variable: message
└─ Say (AI): "Confirm you noted
{{vars.message}} and say goodbye."
└─ Hang up

Things to notice:

  • {{vars.name}} collected in the second node is spoken back in the third node’s prompt.
  • The branch mixes an AI-intent edge (sales can be phrased any way) with a deterministic edge (contains "support") and ends with an else edge, so no caller hits a dead end.
  • The closing Say is AI-generated — a natural goodbye — while the greeting is fixed text.

Pair this with the agent’s Data & Recording tab to extract name / reason / message into structured fields after the call and deliver them to email, Slack, Teams, or a webhook.

When changes go live: Save vs Apply Changes

Section titled “When changes go live: Save vs Apply Changes”

Two different systems are involved in getting a call to your agent, and they update at different times:

  • Agent config — live on Save. The platform reads the agent’s saved configuration fresh at the start of every call. Greeting, persona prompt, voice, flow graph, timing knobs, fallback: click Save changes and the very next call uses them. There is no Apply step for the agent itself.
  • Routing — staged until Apply. Which phone number rings which destination is PBX configuration. Pointing an inbound route at your agent (or away from it) is staged when you save the route and pushed to your phone system only when you press Apply Changes — the banner shown on Nova pages. Until then, calls keep following the previous routing.

Symptom-to-cause:

SymptomCause
”I reworded the greeting but callers hear the old one”Agent not saved — wording is live on the next call after Save changes
”I pointed a number at the agent but calls still go to the old destination”Routing staged but not applied — press Apply Changes on a Nova page
”I saved the agent and now Nova shows an unapplied-changes banner”Normal — the agent’s conversation behavior is already live; Apply pushes the PBX-level sync