Audience: QA and Product teams.Scope: Everything you can do (and cannot do) in the visual Flow Builder, written in plain language without code.How to use: Read top-to-bottom for orientation, or jump to a section when you need a specific behavior reference.Last reconciled against code: 14 August 2026, against
origin/v2/main (src/call_handler/flow_compiler/). Runtime and schema behavior in this guide was verified against the Pydantic models, the exported workflow schema, the validator, and the node builders. Claims about the Builder UI itself — auto-save to browser local storage, the 15-minute test-session expiry, canvas shortcuts, import rejection of old schemas — live in the front-end repo and were not verified in that pass; treat them as unconfirmed.Table of Contents
- Introduction & Mental Model
- The Workspace at a Glance
- Workflow-Level Settings
- The Ten Node Types
- Connections (Edges) Between Nodes
- Decision Logic & Operators
- The Variable System
- Speech, Language & Model Selection
- Fine-Tuning Examples
- Knowledge Bases
- The Test Agent (Voice Testing)
- Validation, Save, Import & Export
- Canvas Interactions & Shortcuts
- Cross-Cutting Rules
- QA Test Checklists by Area
- Best Practices Summary
- Glossary
1. Introduction & Mental Model
The Flow Builder is a visual no-code designer for creating voice AI agents that hold real phone conversations. A workflow author drags nodes onto a canvas, connects them with arrows, configures each node in the right-hand property panel, and ends up with a complete script for an AI agent. The agent speaks, listens, makes decisions, calls APIs, transfers calls, and ends calls — all driven by the workflow you design. A few mental anchors that are worth getting right before reading further:- A workflow is one complete agent. It has one entry point, an arbitrary internal structure, and one or more exits (typically End Call or Transfer).
- A node is a single step or action in the workflow. There are ten node types, each with its own purpose: Start, Conversation, Collection, Variable Extraction, Call API, Decision, Transfer, SMS, Press Digit, End Call. A workflow is built by combining nodes.
- An edge is an arrow connecting two nodes. It tells the agent “when this finishes, go to that.” Edges can be unconditional (always taken) or conditional (only taken when something is true).
- A variable is a named bucket of information that travels with the call (the caller’s name, an order number, an account status). Nodes write into variables; later nodes read from them. A variable can be flagged secret, which keeps its value out of every prompt while still letting it reach APIs and SMS destinations — see Section 7.9.
- The agent is the live AI persona that speaks to the caller. It is shaped by three layers of instructions: the global prompt (your brand voice), the prompt presets (tone and accuracy rules), and the node-level instructions (what to do at this specific step).
- The agent has access to three pluggable AI services: STT (speech-to-text, what it hears), LLM (the brain, how it reasons), and TTS (text-to-speech, how it sounds). Each can be set workflow-wide and overridden on individual nodes.
2. The Workspace at a Glance
The Flow Builder workspace has these regions:- Top toolbar — Workflow name, language picker, action buttons (Test Agent, Stop Test, Knowledge Base, Import, Export, settings panels).
- Canvas (center) — Where nodes are placed and connected. Supports zoom, pan, and a minimap.
- Node palette (left) — A list of node types. Drag onto the canvas to add a node.
- Property panel (right) — Appears when you select a node or edge. Shows every configurable field for that item.
- Validation feedback — Red error highlights on nodes/edges and a list of issues that block testing or export.
- Test panel (right side, on demand) — Appears when you start a test call. Shows live transcript and debug events.
3. Workflow-Level Settings
Workflow-level settings apply to the entire workflow, regardless of which node is running. They live in the right-side settings panels accessible from the top toolbar.3.1 Workflow Language
Three workflow languages are supported: English, Japanese, and Bangla. The default is English. What changing the language does:- Filters the STT and TTS provider dropdowns to providers that support the new language.
- Resets STT and TTS to sensible defaults for the new language if the current selection is incompatible.
- Does not change the LLM (LLMs are language-agnostic and handle all three).
- Does not translate prompts, instructions, or fine-tuning examples — you must rewrite them in the target language.
- Does not affect variable interpolation logic.
3.2 Global Prompt
A free-text field that gets prepended to every conversational agent in the workflow. Use it for persona-level guidance that should hold true everywhere: brand voice, who the agent represents, why the call is happening. Where it gets applied:- All Conversation nodes
- All Collection node steps
- End Call farewells when the farewell type is AI-generated
- Use
{{variable_name}}to interpolate any declared workflow variable. Values resolve at runtime. - Write multi-paragraph instructions if needed.
- Reference the brand, the speaker’s role, the call’s purpose, or hard rules that must always hold.
- Step-by-step conversation flow (that belongs on individual nodes).
- Tone/format rules that already exist as a prompt preset (use the preset instead — it is tested and known to compose well).
- Anything that only applies to one node (put it in that node).
3.3 Prompt Presets
A toggleable list of vetted instruction snippets, grouped by category. Presets are layered after the global prompt and before node-level instructions. They compose cleanly with each other; toggling several at once does not produce conflicts. Personality & Tone- Warm & Concise (on by default) — Friendly, unhurried tone; 2–3 sentences per turn; no repetition. Acknowledges the caller before answering.
- Filler Phrases — Adds natural “one moment,” “let me check,” “just a second” cues before tool lookups so the line never feels dead. Used sparingly.
- Emotional Awareness — Brief acknowledgment of frustration, worry, or confusion before getting to the answer. Useful for support and complaint flows.
- Read-Back Confirmation — Agent repeats critical details (names, phone numbers, emails, codes, dates, amounts) back before acting. Spells alphanumeric codes character-by-character. Useful for payments, account changes, regulated industries.
- Phonetic Spelling — When spelling letter-by-letter, agent uses NATO phonetic alphabet (“A as in Alpha”). Useful for noisy lines, accented speakers, or verification flows.
- Natural Speech Output — Converts symbols and digits to spoken form. Prices become “seven hundred fifty-eight dollars,” dates become “April eighteenth,” URLs become “verbex dot ai slash docs.” Phone numbers are spoken digit-by-digit. This preset is almost always worth turning on.
- Phonetic Tolerance — Accepts close-sounding name variants instead of treating minor mishears as mismatches. If multiple candidates are close, the agent asks the caller to confirm.
- Honest Identity (on by default) — If the caller asks “Are you human?” the agent answers truthfully and briefly. Never volunteers this unprompted; never claims to be human.
- Stay In Scope — The agent answers only from its prompt, attached knowledge base, and the current conversation. Admits unknowns plainly. Does not invent facts, prices, or policies.
- ✅ Toggle as many as you need; they are designed to compose.
- ✅ For a customer-service workflow, a strong default combination is Warm & Concise + Emotional Awareness + Read-Back Confirmation + Natural Speech Output + Honest Identity + Stay In Scope.
- ❌ Do not duplicate a preset’s rules in the global prompt or in node instructions. The preset already covers it; duplicating leads to bloated prompts and occasional conflicts.
3.4 Pronunciations
A workflow-wide replacement table that controls how the TTS engine speaks specific words or phrases. Each rule has a term (what is written in your prompts) and a replacement (what should come out of the speaker). Common uses:- Brand and product names that the TTS gets wrong
- Acronyms that should be spelled vs. read as a word
- Foreign or uncommon names
- Domain-specific jargon
- Leading and trailing whitespace on both fields is trimmed.
- Rules with an empty term are dropped silently.
- Terms are matched case-insensitively. If you add the same term twice (different cases), the last one added wins, but the rule keeps its position in the list.
- The TTS audio the caller hears.
- The LLM’s reasoning (the LLM still sees the original term).
- Transcripts and call logs (still show the original term).
- Variable values, decision logic, or any text comparison.
- The caller’s own speech (the STT transcribes whatever they actually said).
- Matching is literal text, not whole-word. A pronunciation for
APIwill also match inside the middle of another word that contains those letters. Be specific. - Empty pronunciations are silently dropped — if you save a rule with no term, expect to see it disappear from the list.
3.5 Workflow Variables (Declaration)
Variables are declared in the dedicated Variables panel. Detailed behavior — types, interpolation, naming rules — is covered in Section 7: The Variable System. High level only here:- Variables have a name, a type, an optional description, an optional secret flag, and (for declared variables) a default value.
- Types are: string, number, boolean, enum, date, list.
- Names must be lowercase letters, digits, and underscores; must start with a letter or underscore; cannot collide with reserved keywords or with the three reserved internal names (
_previous_node,_global_cooldown,_secret_vars). - Variables can also be created implicitly by Collection nodes, Variable Extraction nodes, Call API response mappings, or Conversation-node tool response mappings.
- A set of system dynamic variables (
{{from_number}},{{call_id}}, and others) is available without being declared — see Section 7.8.
3.6 Default STT, LLM, and TTS
These three dropdowns set the baseline AI services for the entire workflow. Individual nodes can override any of them. See Section 8: Speech, Language & Model Selection for the full list of providers, models, voices, and language compatibility.3.7 Workflow-Level Voice Behavior
Two settings on the entry node govern interruption tolerance for the whole call:- Minimum speech to interrupt (milliseconds) — How much continuous audio the caller must produce before they are allowed to interrupt the agent. A short noise (a cough, a quick “hmm”) under this threshold is ignored.
- Minimum words to interrupt — How many distinct words the caller must speak before interruption is allowed. Range 0–50.
minResponseDelayMs, maxResponseDelayMs, detectionDelayMs, and the interrupt threshold), each capped at 60,000.
Language note: Japanese interruption sensitivity was retuned repeatedly in August 2026 — the ja-JP VAD activation threshold moved 0.35 → 0.20 → 0.30 within four days, all VAD inference now runs at 8 kHz, and the ja-tuned VAD is passed into the flow’s Qwen STT adapter where it gates what reaches the model at all. Any Japanese interruption-tolerance test result from before 13 August 2026 is stale and should be re-run.
3.8 Workflow Identity
- Workflow name — Free-form, displayed in the toolbar and in any export filename.
- Workflow description — Optional, shown in workflow listings.
- Workflow ID — Auto-generated, stable across edits and exports. QA can use this to identify which workflow generated a given export file.
4. The Ten Node Types
The Flow Builder has exactly ten node types. Every workflow is built by combining them. Each section below covers purpose, configuration, runtime behavior, restrictions, and QA test ideas. The compiler recognizes:start, conversation, collection, variable-extraction, call-api, decision, transfer, sms, press-digit, end-call.
4.0 Is the caller heard while a node runs?
Worth knowing before reading the individual nodes, because it changed recently and it is the behavior most likely to surprise QA. On non-realtime sessions the microphone now stays open through long function nodes — Call API and SMS. Anything the caller says during the wait is committed to the transcript and carried into the next node’s chat context, and they hear an escalating, rate-limited hold acknowledgment (English, Bangla, or Japanese; a minimum of 8 seconds between acknowledgments) instead of dead air.- Realtime sessions keep the historical behavior: the caller is muted through function nodes.
- End Call, Transfer, and Press Digit nodes are muted.
- Decision and Variable Extraction remain muted (they are instantaneous anyway).
- System-spoken lines — retry fillers, hold acknowledgments, knowledge-base wait messages — are deliberately kept out of the LLM’s chat context, so the agent does not treat its own filler as conversation.
4.1 Start
Purpose. The single entry point of the workflow. Marks where every call begins and holds workflow-wide pacing settings (interruption sensitivity and tool-loop limits). Connections.- One outgoing connection (the first “real” node of the call).
- No incoming connections.
- Label — Internal name for this node. Callers never see it.
- User-away timeout (seconds) — How long the system waits in silence before treating the caller as “away.” Default is 30 seconds. Once flagged away, the workflow can react (e.g., end the call). Range 0–3600.
- Maximum tool steps per turn — A safety cap on how many tool calls the agent can chain in a single turn. Default 3. Prevents runaway loops where the agent keeps invoking the same tool. Range 0–100.
- Workflow-wide interruption sensitivity — Minimum-speech-to-interrupt and minimum-words-to-interrupt as described in Section 3.7.
- A workflow must have exactly one Start node.
- Nothing can connect into Start.
- Start has no model overrides, no instructions, no opening message, no knowledge base, and no tools.
- Verify the call begins on whatever node Start points to, with no greeting from Start itself.
- Set the away timeout to a small value, stay silent, confirm the agent reacts on schedule.
- Set minimum speech to interrupt to 800 ms; verify a 500 ms “mm” does not interrupt and a 1000 ms “please” does.
- Configure a workflow whose first agent loops on a tool; confirm the cap stops the loop.
4.2 Conversation
Purpose. The general-purpose dialogue node. The agent speaks, listens, reasons, optionally consults a knowledge base, optionally calls tools, and decides which outgoing edge to follow based on what the caller said. Connections.- One or more incoming.
- One or more outgoing. The agent picks among outgoing edges based on the caller’s intent (and any conditions on the edges).
-
Mode — How rigid the agent should be.
- Default — The agent has freedom to phrase its responses naturally, guided by your instructions. It’s similar to the previously available Agentic agent, but with better control.
- Prompt-only — The agent generates speech but follows a tightly written, step-by-step script you provide.
- Static-only — The agent speaks one exact line, word-for-word, then chooses an outgoing edge based on the caller’s reply.
- Label — Internal name.
-
Instructions — Free-text guidance for the agent. Visible in Full and Prompt-only modes. Supports
{{variable}}interpolation. - Exact opening line — Visible in Static-only mode. The single sentence the agent must say verbatim on entry.
- Opening message — Visible in Full mode. Choose between No greeting (wait for the caller), Static text (you write the exact greeting), or AI-generated (the agent improvises a greeting from a brief instruction).
- Knowledge base — Optional. Attaches a document library the agent can search during this conversation. See Section 10.
-
Voice settings — Per-node interruption tolerance and pause timing. Overrides the workflow defaults for this node only.
- Allow interruptions toggle.
- Minimum pause — wait time after the caller stops talking before the agent answers. Schema field
minResponseDelayMs, milliseconds, default 500, capped at 60,000. - Maximum pause — if the caller goes silent for longer than this, the agent prompts again. Schema field
maxResponseDelayMs, milliseconds, default 6000, capped at 60,000. - ⚠️ Unit caveat for QA: the runtime schema is unambiguously in milliseconds. If a Builder field is labelled “seconds,” the UI must be converting — confirm with the Builder team before trusting a value. Entering
6against a raw millisecond field yields 6 ms, not 6 seconds.
- Allow ending call — If on, the agent may hang up when the caller asks (“goodbye,” “end call”). If off, the agent politely refuses such requests and steers back to the workflow.
- Additional end-call guidance — Free-text rules the agent must satisfy before ending (e.g., “only after the booking is confirmed”).
- Fine-tuning examples — Optional. See Section 9.
-
Global node settings — Marks this Conversation as a globally available branch the agent can drop into from anywhere (e.g., an “escalate to human” handler that should be reachable mid-call regardless of where the caller is). This is not a bare on/off toggle — a global node carries three settings:
- Trigger condition — the natural-language rule describing when the global node fires.
- Cooldown steps — how many steps must pass before it can fire again. Range 0–1000.
- Return behavior — where control goes when the global node finishes. Default is return to previous node.
- Tools — Add API-backed actions the agent can invoke during this conversation (lookups, mutations, side-effects). Each tool exposes a name, a description, parameters, a timeout, a retry count, and an optional “wait message” the agent speaks while the tool runs.
- Tool response mapping — Each tool can also write values from its response into workflow variables, using JSON path → variable name with the same Auto / String / Number / Boolean coercion as Call API (see Section 7.4). A tool result is not limited to being spoken; it can be stored and used downstream in Decisions and interpolation.
- Tool request encoding — Webhook-style tools honor the configured Content-Type header: the body is encoded as JSON, form-urlencoded, or multipart. The tool header schema is the same as the Call API node’s.
- Retry and failure speech — Tools accept the same author-configurable spoken messages as Call API nodes (
retryMessage,errorFallbackMessage,errorTerminalMessage). See Section 4.5.
- STT, LLM, and TTS overrides for this node.
- Realtime model toggle — Use a single low-latency speech-in/speech-out model that combines STT, LLM, and TTS. When on, STT and LLM choices lock to the realtime provider; TTS can still be overridden separately for higher-fidelity voice output.
- ✅ Use Full mode for most cases. Prompt-only is for highly scripted flows; Static-only is for rare cases where the exact wording matters legally or compliance-wise.
- ✅ Use the knowledge base when the agent needs facts you do not want to hardcode in instructions (policies, prices, FAQs).
- ✅ Override the LLM when this conversation is significantly more or less complex than the rest of the workflow.
- ❌ Do not attach a knowledge base in Static-only mode. There is no LLM call to use it.
- ❌ Do not leave a Conversation node with zero outgoing edges — the call will dead-end.
- ❌ Do not reference a
{{variable}}that hasn’t been declared or populated yet — it will render as empty.
- Verify each opening message option (none / static / AI-generated) plays correctly.
- Toggle “allow interruptions” off and confirm the agent finishes its sentence even if the caller talks over it.
- With “allow ending call” off, ask to hang up; confirm the agent declines politely.
- Attach a knowledge base with known content and verify the agent cites it in its answer.
- Connect three outgoing edges with different conditions; verify the agent routes correctly across realistic caller utterances.
- Add a tool, trigger it during the call, and confirm the wait message is spoken while it runs.
4.3 Collection
Purpose. Walks the caller through a structured series of questions (steps) to gather one piece of information per step. The agent re-asks if the caller’s answer doesn’t match the expected type. Once all steps are filled, the workflow advances. Connections.- One or more incoming.
- One outgoing (the “next node when collection is done”).
- An optional early-exit path that bypasses remaining steps when an exit condition becomes true.
- Label — Internal name.
- Opening message — Optional plain text spoken once before the first step (e.g., “I just need a few quick details.”). Supports
{{variable}}. If blank, the first step starts immediately. - Steps (ordered list) — Each step collects exactly one variable.
- Description — A free-text explanation of what this step is for. Helps the agent understand context. Free-form, supports
{{variable}}(rendered into the agent’s instructions, not into anything spoken aloud). - Instructions — Optional detailed guidance for how the agent should ask and how to handle replies. Supports
{{variable}}. - Exact opening line — Optional single sentence spoken verbatim when the step begins. If blank, the agent improvises an opener using its instructions.
- Field name — The variable name where the collected value is stored. Must be lowercase letters, digits, and underscores; must start with a letter or underscore.
- Field type — String, number, boolean, or enum.
- Field description — A short explanation of what the value represents. Helps the agent extract correctly.
- Allowed values — For enum fields only. The exact strings the agent is allowed to extract into.
- Required / optional — Steps are required by default. Marking a step optional (
required: false) makes the compiler emit a siblingskip_<step>tool and append a skip clause to that step’s scope, so the agent can confirm with the caller and move on without a value. Do not assume every step is mandatory. - Secret — A step’s field can be flagged secret, which keeps the collected value out of prompts and redacts it from the
collection_completedebug event. See Section 7.9. - Per-step model overrides — STT, LLM, TTS overrides specific to this step.
- Voice settings (per step) — Interruption and pause timing overrides for this step (millisecond fields, as in Section 4.2).
- Use separate TTS — A latency optimization that splits TTS synthesis from speech recognition.
- Description — A free-text explanation of what this step is for. Helps the agent understand context. Free-form, supports
- Allow ending call and Additional end-call guidance — Same semantics as in Conversation.
- Early-exit condition — Optional logical check evaluated after each step. If it becomes true, the remaining steps are skipped and control jumps to the early-exit target.
- ✅ Use Collection when you have a known list of fields to gather. Use Variable Extraction (Section 4.4) when the user already mentioned the values earlier in the conversation.
- ✅ Use enum fields with allowed values when the answer must be one of a fixed set (e.g., shipping speed: standard / express / overnight). The agent will keep re-asking until it gets one.
- ✅ Set per-step exact opening lines when the wording is sensitive (compliance, legal, regulated industries).
- ❌ Do not put Collection where you actually want a Conversation. Collection is for structured slot-filling; if the caller is having a back-and-forth chat, use Conversation.
- ❌ Do not expect to attach a knowledge base or your own tools to a Collection node — neither is author-configurable here. (The compiler still injects its own escape tools, as described above.)
- ❌ Do not add fine-tuning examples to a Collection node or step — the schema has no examples field for either. If a step extracts badly, fix the field description, the step instructions, or the LLM override.
- ❌ Do not skip the field description. The LLM uses it to disambiguate; missing descriptions cause weak extractions.
- ❌ Do not put many unrelated fields in one Collection. Split into focused steps (each Collection node should feel like one logical task).
- Provide an answer of the wrong type (text for a number field, value not in the enum list); confirm the agent re-asks rather than crashing.
- Set an exact opening line on a step; confirm it is spoken verbatim.
- Configure an early-exit condition (e.g., caller says “agent”); confirm the workflow jumps when the condition fires.
- Verify each collected variable is available downstream via
{{variable}}interpolation. - Override the LLM on a single step and confirm only that step uses the new model.
- Mark a step optional; decline to answer it and confirm the agent confirms and moves on rather than looping.
- Mid-collection, say “get me a human” / “goodbye”; confirm the escape tools fire (global handoff, transfer, end call) instead of the agent re-asking the current step.
- Flag a step secret; confirm the value is usable downstream but redacted in the
collection_completedebug event.
4.4 Variable Extraction
Purpose. A silent, behind-the-scenes node that reads the conversation that has already happened and extracts one or more typed values into variables — without asking the caller anything. Useful when the caller has already volunteered information you care about. Connections.- One or more incoming.
- One outgoing.
- Label — Internal name.
- Fields (list) — Each field is one variable to extract.
- Name — The variable name to write into.
- Type — String, number, boolean, or enum.
- Description — Tells the LLM what to look for in the conversation. The clearer this is, the better the extraction.
- Allowed values — For enum fields, the exact set of legal values.
- Secret — An extracted field can be flagged secret. The value is redacted from every subsequent prompt but stays usable in API headers, URLs, bodies, and transfer/SMS destinations. See Section 7.9.
- Fine-tuning examples — Optional (response examples). Strongly recommended when extraction is tricky. See Section 9.
- Model configuration — LLM override only. STT and TTS are not used here.
"" for string/enum, null for number/boolean). The workflow immediately advances to the outgoing edge — there is no pause and no caller interaction.
Do’s and don’ts.
- ✅ Use it after a long Conversation node where the caller mentioned several pieces of information naturally; one Variable Extraction call can pull them all out at once.
- ✅ Pair it with a downstream Decision node that branches on whether the extraction succeeded.
- ❌ Do not use it to gather information from the caller — that is what Collection is for. Variable Extraction never speaks.
- ❌ Do not assume extraction always succeeds. Check for empty/null in subsequent Decision nodes.
- ❌ Do not pile dozens of fields into one extraction call — accuracy degrades when the LLM is asked to track too many things at once. Split into multiple Variable Extraction nodes when the field count grows large.
- Conduct a Conversation where the caller mentions an account ID, a city, and a preference; immediately follow with Variable Extraction and verify all three variables fill correctly.
- Provide a conversation where one field is genuinely absent; confirm that field comes out empty/null and downstream logic handles it.
- Add fine-tuning examples and verify extraction quality improves on tricky phrasings (“next Tuesday,” “sometime in March”).
4.5 Call API
Purpose. Makes an HTTP request to an external service while the call is in progress, optionally speaks a “please wait” line during the call, and stores values from the response into workflow variables. Connections.- One or more incoming.
- One outgoing for success.
- One outgoing for error / timeout (the “fallback” edge).
- Label — Internal name.
- HTTP method — GET, POST, PUT, PATCH, DELETE.
- URL — The full endpoint. Supports
{{variable}}interpolation. Variable values are automatically URL-encoded so spaces, ampersands, and equals signs cannot break the URL. - Headers — Key/value pairs (e.g., authentication tokens). Both keys and values support
{{variable}}. - Request body — Visible for POST/PUT/PATCH. The body is encoded according to the Content-Type header you configure: JSON, form-urlencoded, or multipart. For a JSON body, the template supports
{{variable}}, and when a placeholder is wrapped in quotes ("{{var}}") the system emits a JSON-typed literal — booleans and numbers drop their surrounding quotes automatically. Unquoted placeholders are inserted verbatim, which is risky for strings; prefer the quoted form. Form-urlencoded and multipart bodies do not follow the quoted-placeholder rule — they are encoded as fields, so test them separately. - Response mapping — Each entry pulls a value out of the JSON response and writes it into a variable.
- JSON path — A path expression like
$.data.account.statusthat points into the response. - Variable name — Where to write the extracted value.
- Value type — Choose from Auto, String, Number, Boolean. See Section 7.4 for what each does.
- JSON path — A path expression like
- Speak while waiting — Optional sentence the agent says before the request is sent (e.g., “Let me look that up for you”). Supports
{{variable}}. - Timeout (seconds) — How long to wait for the server to respond before triggering the fallback edge. Range 0–300.
- Retry count — How many times to retry on failure before giving up. Default 0 (no retries). Range 0–10. Retries reuse the same interpolated request; they do not re-evaluate variables.
- Retry message — Spoken before each retry attempt. Retries are no longer silent.
- Error fallback message — Spoken when the call fails and no error edge is wired, before the workflow falls through to the success edge.
- Error terminal message — Spoken just before shutdown when neither a success nor an error path exists.
- All three messages resolve
{{variables}}and are validated as static text. Left unset, they fall back to language-matched defaults, so a Bangla or Japanese workflow no longer hears English filler mid-call.
- HTTP redirects are followed.
- Header values are stripped of leading/trailing whitespace and control characters — this was silently corrupting bearer tokens.
- A malformed JSON body returned with a 2xx status no longer breaks the node.
- Request bodies now appear in call logs, and the debug timeline carries the API response payload (with secrets and sensitive plain text redacted).
- Template-formatting errors are raised inside the retry block, so they route to the error edge instead of crashing the node.
- On non-realtime sessions the caller is heard while this node runs and hears an escalating hold acknowledgment — see Section 4.0.
- ✅ Always wire up the error edge. APIs fail; your workflow should handle it gracefully.
- ✅ Set the value type explicitly (String / Number / Boolean) when the variable will be compared in a Decision node. Auto-mode keeps the JSON type, which can produce surprising mismatches (e.g., a JSON
truedoesn’t equal the string"true"). - ✅ Use a short, friendly waiting line (“one moment”) for any API call expected to take longer than a second. Otherwise the line goes dead.
- ✅ Set the retry and failure messages when the workflow is not in English, or when the default filler would sound wrong for the brand.
- ❌ Do not paste credentials in as plain text. Declare them as secret variables (Section 7.9) and reference them from headers — the value reaches the API but never enters a prompt.
- ❌ Do not chain many Call API nodes back-to-back and assume the line goes dead — it no longer does on non-realtime sessions (hold acknowledgments and retry messages fill the gap). Still keep the chain short; the caller is waiting either way.
- ❌ Do not assume retries fix wrong variables. Retries reuse the original request body. If your URL was malformed because a variable was empty, retrying does not help.
- Hit a known-good endpoint and verify the success edge fires and variables fill from the response.
- Hit an endpoint that returns an HTTP 500; verify the error edge fires.
- Set a 1-second timeout against a slow endpoint; verify the error edge fires after one second.
- Use
{{variable}}in URL, headers, and body; verify each is interpolated correctly. Confirm spaces in the URL are URL-encoded. - Use Auto value-type vs. explicit value-type and check that a downstream Decision behaves predictably with both.
- Send a form-urlencoded and a multipart body; verify the receiving endpoint sees the expected fields.
- Set a retry count of 2 against a failing endpoint; verify a retry message is spoken before each attempt.
- Remove the error edge, force a failure, and confirm the error-fallback message is spoken before the success edge is taken.
- Speak during a slow Call API node (non-realtime session); confirm your words land in the transcript, reach the next node’s context, and that a hold acknowledgment is played no more often than every 8 seconds.
- Check the debug timeline shows the API response payload, with any secret values masked.
4.6 Decision
Purpose. A silent router. Evaluates conditions and sends the call down one of several outgoing edges. The caller hears nothing during a Decision node. Connections.- One or more incoming.
- Multiple outgoing — one per condition, plus a default (else) edge.
- Label — Internal name.
- Decision method —
- Math expression — Deterministic. The system evaluates explicit variable comparisons. Predictable; identical inputs always produce identical outputs. See Section 6.1.
- LLM condition — Probabilistic. The agent reads the conversation context and your natural-language descriptions of each branch, then picks the best fit. Useful for vague intents (“caller seems frustrated”).
- Conditions (ordered list) — Each condition has:
- A label (visible to you, not to the caller).
- One or more clauses (in math mode) — each clause is a variable + operator + value, combined with AND/OR.
- A prompt description (in LLM mode) — natural language describing when this branch applies.
- A target edge — which outgoing edge fires when this condition matches.
- Fine-tuning examples — Optional transition examples, LLM mode only. Math-mode decisions ignore examples because the math is deterministic.
- No model override.
DecisionNodeDatahas no model-config field. An LLM-mode Decision runs on the workflow default LLM — there is nothing to override here.
- ✅ Order conditions from most specific to most general — otherwise the general one fires first and the specific never matches.
- ✅ Always have a default edge. The validator enforces this; pretend it didn’t and your call would dead-end.
- ✅ Use math-mode whenever you can. It is faster and predictable.
- ✅ Use LLM-mode for genuinely fuzzy decisions where you cannot phrase the rule as a clean comparison.
- ❌ Do not put
{{variable}}syntax inside condition clauses — clauses reference variables by name directly, not by interpolation. - ❌ Do not assume LLM-mode decisions will always pick perfectly. Add fine-tuning examples for the cases you have seen go wrong.
- ❌ Do not compare a boolean variable against the string
"true"(the comparison is type-aware but it is still a confusing pattern; either compare againsttruedirectly, or convert at the source).
- For math-mode: build a decision with three overlapping conditions and verify priority order matters.
- For LLM-mode: feed in five different caller utterances and verify each routes to the intended branch.
- Provide a condition referencing a variable that was never populated; confirm the default edge fires.
- Reorder conditions and confirm the routing changes accordingly.
4.7 Transfer
Purpose. Hands the caller off to a phone number, a queue, or another agent. Connections.- One or more incoming.
- One outgoing (the path the workflow takes if the transfer is unsuccessful or the caller returns).
- Label — Internal name.
- Transfer type —
- Cold — Immediate transfer. The caller is moved directly to the destination with no preamble. The agent does not speak with the destination first.
- Warm (non-agentic) — The caller is held. The system places a separate call to a human destination, optionally whispers context to that human, then bridges the two.
- Warm (agentic) — Same as warm non-agentic, but the destination is another AI agent. The system can pass consultation instructions describing how that downstream agent should behave.
- Destination — The phone number (in international format, e.g.,
+15555550123) or a SIP address. - Hold message (warm only) — What the caller hears while waiting.
- Whisper message (warm only) — What the destination hears as an introduction before being bridged.
- Consultation agent instructions (warm-agentic only) — Persona/behavior guidance for the downstream agent.
- Timeout (seconds) — How long to wait for the destination to answer before giving up.
- Ringing timeout (seconds) (warm only) — How long to ring the human destination before cancelling the leg and resuming with the caller.
- No-answer message (warm only) — What the caller hears when nobody picks up. It is validated in workflow preflight and localized per workflow language.
- ✅ Use cold transfers for simple call-center handoffs (“press 1 for billing”).
- ✅ Use warm transfers when context matters — “tell the agent the caller is asking about a refund and is upset.”
- ✅ Always set a sensible timeout. A 60-second wait on hold can sour a call.
- ❌ Do not use a Transfer node to send the caller to a number you do not control or have not tested. Failed transfers leave callers stranded.
- ❌ Do not put Transfer in the middle of a workflow expecting the caller to come back automatically. Once transferred, control of the call leaves the agent.
- Cold-transfer to a known-good number; verify it connects.
- Warm-transfer with a hold message and a whisper; verify both messages are spoken to the right party.
- Configure a short timeout and dial a number nobody answers; verify timeout behavior.
- Set a short ringing timeout against an unanswered number; verify the no-answer message is spoken in the workflow’s language and the caller returns to the agent.
4.8 SMS
Purpose. Sends a real text message to the caller (or any number) in the middle of the call — a booking confirmation, a payment link, a verification code — then continues the workflow. Connections.- One or more incoming.
- One outgoing for success.
- One outgoing for error (send failure).
- Label — Internal name.
- Provider — Currently Twilio.
- Account SID and Auth token — Provider credentials. Declare these as secret variables and reference them here; see Section 7.9.
- From number — Templated, so it supports
{{variable}}, and it is resolved at send time rather than at node entry. - Recipient — The destination number in E.164 format (e.g.,
+15555550123). Supports{{variable}}. - Body — Either:
- Static text — Exactly what you write, with
{{variable}}interpolation. A secret variable is allowed in a static SMS body. - LLM-generated — The agent composes the message from your instructions (e.g., “confirm the appointment date and time and thank them”).
- Static text — Exactly what you write, with
- Failure copy — The message spoken to the caller when the send fails.
- ✅ Wire the error edge. Carrier rejections and bad numbers are common.
- ✅ Use static text for anything regulated (codes, legal notices) and LLM-generated for conversational confirmations.
- ✅ Keep credentials in secret variables, never inline.
- ❌ Do not use a local-format number. E.164 or it fails validation.
- ❌ Do not assume the caller received it. Delivery is asynchronous at the carrier; the success edge means accepted for sending.
- Send to your own phone with a static body containing a variable; verify the received text and the success edge.
- Send to an invalid recipient; verify the error edge fires and the failure copy is spoken.
- Use an LLM-generated body and check it reflects what actually happened earlier in the call.
- Leave the auth token blank and confirm export is blocked by preflight.
- Put a secret variable in a static body; confirm it is sent correctly but masked in debug events.
4.9 Press Digit
Purpose. Navigates an external IVR by emitting DTMF tones — “press 2 for billing” menus on the far end of an outbound call. Connections.- One or more incoming.
- Exactly one outgoing direct edge.
- Label — Internal name.
- Instructions — Free text describing what to press and when.
- Detection delay (milliseconds) — How long to wait before emitting the tones, giving the far-end menu time to speak. Default 500, range 0–60,000.
- ✅ Tune the detection delay against the real IVR. Too short and the tones land before the menu is listening.
- ❌ Do not use this to collect digits from your caller — that is a Collection node.
- Dial a known IVR and verify the correct menu branch is reached.
- Shorten the detection delay until the tones are missed; confirm the failure mode is what you expect.
4.10 End Call
Purpose. Cleanly ends the call, optionally with a farewell message and an optional post-call webhook for logging or follow-up automation. Connections.- One or more incoming.
- No outgoing. The call ends here.
- Label — Internal name.
- Farewell type —
- No farewell — Hang up immediately.
- Static text — Say a fixed goodbye. Supports
{{variable}}. - AI-generated — Have the agent compose a farewell from your instructions (which can mention what happened during the call).
- Farewell text or instructions — Depending on type.
- Webhook URL (optional) — An HTTPS endpoint that is invoked when the call ends. Useful for logging outcomes to a CRM or starting a follow-up. Supports
{{variable}}in the URL. - Disposition tags (optional) — Free-form labels (e.g.,
resolved,transferred,callback_required) attached to the call record for analytics. - Delete room on end — Whether to clean up the underlying call session resource. On by default.
- No model override.
EndCallNodeDatahas no model-config field. An AI-generated farewell runs on the workflow default LLM and TTS.
- ✅ Always include at least one End Call node in any workflow. Calls that have no End Call may hang indefinitely.
- ✅ Use AI-generated farewells when you want the agent to recap what happened (“Thanks for confirming your appointment for Friday at 2 PM”).
- ✅ Use disposition tags consistently so analytics stay clean.
- ❌ Do not rely on the webhook for hard guarantees. It fires once, with no retry. Use it for best-effort logging.
- ❌ Do not put
{{variable}}references in the webhook URL that haven’t been populated by the time the workflow reaches End Call.
- Verify each farewell type plays correctly.
- Configure a webhook against a test endpoint; confirm it receives a POST after the call ends.
- Tag a call with
escalatedand confirm the tag is visible in analytics.
5. Connections (Edges) Between Nodes
An edge is the arrow connecting one node to another. Edges define the order of operations: when one node finishes, the workflow moves along an edge to the next node.5.1 Edge Types
The system uses the following edge categories. They are mostly automatic — the type is inferred from the source and target nodes — but you can change a Conversation node’s outgoing edge between three explicit modes.- Direct — Fires unconditionally as soon as the source node finishes. The default for most edges.
- Conditional (LLM) — Fires when the source node finishes and the agent decides, based on context, that the prompt condition matches. Available only from Conversation nodes.
- Conditional (math expression) — Fires when the source finishes and a deterministic variable check is true. Available only from Conversation nodes.
- On-reply — A special edge from a Conversation node that fires immediately after the caller’s first reply, without any further follow-up question. Constraint: if a Conversation has an on-reply edge, it cannot have any other outgoing edges.
- Session-start — The single edge from the Start node to the first “real” node.
- Logic-branch — An outgoing edge from a Decision node tied to a specific condition.
- Logic-default — The fallback edge from a Decision node, taken when no condition matches.
- Error-fallback — The error edge from a Call API node (and conceptually similar fallbacks elsewhere).
5.2 What You Can Configure on an Edge
- Label — Free-form text. Visible on the canvas next to the arrow. Helpful for documentation and for spotting branches at a glance. Labels are static text only —
{{variable}}placeholders in an edge label do not interpolate at runtime. - Edge type (Conversation sources only) — Direct vs. Conditional vs. On-reply.
- Condition method (Conditional edges only) — LLM (natural language) or Math expression (deterministic).
- Prompt condition (LLM-conditional edges only) — Natural-language description of when this edge applies. Supports
{{variable}}interpolation, since this text is part of a prompt sent to the LLM at runtime. - Equation clauses (math-conditional edges only) — Variable + operator + value triplets.
- Memory mode — Decide whether the next node receives the full conversation history (
full) or starts fresh (fresh). Use “fresh start” when the next node should not be biased by what was said earlier. Legacy note: a third value,summarized, is still accepted on import and is silently rewritten tofullwith no warning. If an older export used “summarized,” that edge now passes full history.
5.3 Source-and-Target Restrictions
- Start — Exactly one outgoing edge. No incoming.
- Conversation — Multiple outgoing allowed (Direct, Conditional, or On-reply with the constraint above).
- Collection — Exactly one outgoing edge after all steps complete. Plus the optional early-exit branch.
- Variable Extraction — Exactly one outgoing edge.
- Call API — Up to two outgoing edges: one success, one error.
- Decision — One edge per condition, plus exactly one default edge.
- Transfer — Typically one outgoing.
- SMS — Up to two outgoing edges: one success, one error.
- Press Digit — Exactly one outgoing direct edge.
- End Call — No outgoing edges. The call terminates here.
- Any node — Cannot connect into the Start node.
5.4 Important Edge Rules
- You cannot define dynamic variables on an edge. Variables are declared at the workflow level or produced by Collection / Variable Extraction / Call API nodes. An edge merely reads variables (in math conditions or LLM prompt conditions) — it never creates them.
- Edge labels do not interpolate. They are pure on-canvas text. The visualizer renders them literally;
{{var}}will appear as{{var}}on screen. - LLM prompt conditions on edges do interpolate. Because the text is sent to the LLM at runtime,
{{customer_status}}will resolve to the current value before the agent sees it. Use this judiciously — heavily personalized prompt conditions can hurt the LLM’s generalization. - Multiple conditional edges are allowed from a single Conversation node. They are evaluated in order; the first match wins.
- An on-reply edge forbids other outgoing edges from the same source. This is enforced by the validator.
- Fixed in August 2026: caller speech was being dropped around branch points. Two separate bugs — an on-reply edge short-circuiting the turn before the caller’s line was recorded, and the activity swap during node handoff losing the utterance — are both fixed. If QA has open bug reports about missing transcript lines near branches or handoffs, re-test them; they are likely closed.
- Self-loops are technically allowed. The validator does not reject a Conversation node whose edge points back at itself, but you almost certainly don’t want one — this is how you build infinite loops.
- Dangling edges are not allowed. When you delete a node, all its edges go with it. You cannot have an edge that points to nothing.
- A workflow needs at least one path from Start to an End Call (or a Transfer that ends the call externally). Workflows without an exit path can hang indefinitely.
5.5 Visual Cues on the Canvas
- Solid line, normal arrow — Direct or default edge.
- Long-dashed line — LLM-conditional edge (the agent decides at runtime).
- Short-dashed line — On-reply edge.
- Dotted line, often colored differently — Error-fallback edge.
- Edge icon (when applicable) — A small badge near the label indicating LLM-driven, math-driven, or on-reply behavior.
- Selected edge — Thicker stroke and color change when clicked, so you know which edge’s properties are open in the panel.
6. Decision Logic & Operators
Decisions can happen in two places: on a Decision node, and on a Conditional edge from a Conversation node. Both use the same operators when you choose math-expression mode.6.1 Math Expression Operators
A clause has the shapevariable operator value. Multiple clauses can be combined with AND or OR (single-level grouping; no nested parentheses).
Equality
==(equals, case-sensitive) — Strict text match."Active" == "active"is false. Use when case is meaningful (e.g., a token from an external system).!=(not equals, case-sensitive) — Inverse.equals_ci(equals, case-insensitive) — Case-insensitive text match."Active" equals_ci "active"is true. Use this for LLM-extracted values where the LLM may capitalize unpredictably.not_equals_ci— Inverse.
True == "true", True == "yes" both resolve to true, so a boolean variable filled by the LLM with a string token still compares correctly. Whitespace around clause values is trimmed automatically.
Numeric Comparison
>,<,>=,<=— Numeric compare when both sides are strict numbers; falls back to lexicographic compare otherwise. The validator warns when a non-numeric value is used against a numeric variable.
Date Comparison
>,<,>=,<=against an ISO-8601 date string — Real calendar comparison when both sides matchYYYY-MM-DD. Otherwise lexicographic. Important: non-ISO dates ("01/15/2024") silently fall back to text comparison and produce surprising results. Always use ISO format.
Containment
contains— For lists, tests element membership. For strings, tests substring presence. Case-sensitive. Combine withequals_cipatterns when case is uncertain.
Existence
exists— True only for genuine values. False for nulls, empty strings, and whitespace-only strings. The value field is ignored.not_exists— Inverse.
6.2 LLM Mode
Each condition becomes a natural-language description. The LLM reads them and the conversation context, then picks the best match. Order does not enforce strict priority (the LLM picks the best fit), but you can still rank conditions to help when descriptions are similar.6.3 Combining Clauses
- AND — All clauses must be true. Use to narrow.
- OR — At least one clause must be true. Use to broaden.
- AND and OR can be mixed, but only at one level — there are no nested groups. If you need nested logic, split into two Decision nodes.
6.4 Validation Rules for Decisions
- Every Decision node must have a default edge. The validator rejects Decisions without one.
- Conditions must reference variables that exist (declared, extracted, or mapped from an API). Typos are caught by the validator (older versions silently evaluated false; the current validator surfaces an error).
- Numeric operators against a non-number value, or boolean comparisons against unsupported tokens, are flagged.
- Enum variables compared against values not in their allowed list are flagged because they can never match.
- A secret variable referenced by an LLM-mode condition is rejected. Math-mode comparisons against secrets are allowed, with the value masked in telemetry.
6.5 Common Decision Pitfalls
- Using
==against an LLM-filled value and being surprised by capitalization differences. Switch toequals_ci. - Writing
is_member == "true"against a boolean variable. Compare against the boolean directly, or usevalueType: booleanon the upstream Call API mapping so the variable is a real boolean. - Comparing dates without ISO formatting. Always store dates as
YYYY-MM-DD. - Forgetting that
existsrejects empty strings. If the variable was set to"",existsis false. - Whitespace surprises in caller-typed values. The system trims clause values automatically; collected variable values are usually trimmed at extraction time too.
7. The Variable System
Variables are how data flows through a workflow. They are declared once and referenced anywhere with the{{variable_name}} placeholder.
7.1 Declaring Variables
The Variables panel is opened from the toolbar. You can:- Add a new variable with name, type, optional description, and optional default value.
- Edit existing variables.
- Remove unused variables.
- Lowercase letters, digits, and underscores only.
- Must start with a letter or underscore.
- Maximum 64 characters (the same 64-character ceiling applies to tool names and other identifiers).
- Reserved keywords are rejected with an explicit message.
- Three internal names are blocked in addition to the keyword list:
_previous_node,_global_cooldown,_secret_vars. These are internal flow-state fields; the validator rejects them and they cannot be written at runtime. A leading underscore is otherwise legal in your own variable names — this is a three-name blocklist, not an underscore ban. - Names are case-sensitive (
customer_nameandCustomer_Nameare different and the second one is invalid because of uppercase letters). - Names must be unique across the entire workflow, including names produced by Collection steps, Variable Extraction fields, and Call API response mappings.
7.2 Variable Types
- String / Text — Any text.
stringis the canonical name;textis accepted as an alias. - Number — Integer or decimal. Compared numerically in Decision nodes.
- Boolean —
trueorfalse. Renders as the lowercase word in interpolated text. - Enum — One of a fixed set of allowed values you define on the variable. Useful for constrained answers (e.g., shipping speed).
- Date — Calendar date in
YYYY-MM-DD. Compared chronologically in Decision nodes. - List — A sequence of values (limited support; primarily useful for
containschecks).
7.3 Variable Interpolation
Anywhere in the workflow that you can write text intended to be processed at runtime, you can use{{variable_name}}. The system substitutes the live value from the call’s state.
Interpolation is supported in:
- Conversation node instructions, opening messages, and exact opening lines.
- Collection node opening message, step instructions, step descriptions, and exact opening lines.
- Call API URL, headers, request body, and waiting line.
- Call API and tool retry, error-fallback, and error-terminal messages.
- SMS from-number, recipient, and static body (and the instructions for an LLM-generated body).
- Transfer hold, whisper, and no-answer messages.
- End Call farewell text and AI-generated farewell instructions.
- Webhook URL on End Call.
- Global prompt.
- Prompt presets do not contain interpolation themselves, but they coexist cleanly with interpolated text in the global prompt and node instructions.
- Fine-tuning example turn text.
- LLM-mode Decision condition prompts.
- LLM-mode Conversation conditional edge prompts.
- Edge labels (the static label text shown on the canvas).
- Variable names themselves (you cannot dynamically name a variable).
- Math expression clauses on edges or Decisions (clauses reference variables by name directly, not by interpolation).
7.4 Call API Response Coercion
When mapping a value out of an API response, the value type field controls how the value is stored:- Auto (default) — Stores the raw JSON value as-is. A JSON
truebecomes a booleantrue; a JSON number stays numeric; a string stays a string. Most flexible but prone to surprises in downstream comparisons. - String — Forces text.
123becomes"123". Always safe; pair with text comparison operators. - Number — Coerces text-that-looks-numeric (
"42") into a real number. Non-numeric text is left unchanged. - Boolean — Coerces common truthy tokens (
"yes","true","1",1) intotrueand falsy tokens ("no","false","0",0) intofalse. Use this when the variable will be compared in a Decision node.
7.5 Rendering Behavior
When{{variable_name}} is interpolated, the rendered output depends on the value:
- Boolean — Lowercase
trueorfalse. JSON-friendly and natural-sounding in speech. - Missing or null — Empty string. The agent says nothing for that placeholder rather than the literal word “none.”
- Numbers — The number as-is (e.g.,
42). - Strings, enums, dates — The value as stored.
- Lists — Comma-joined into a single readable string.
- Inside a URL — The value is URL-encoded so spaces, ampersands, and equals signs cannot break the URL.
- Inside a JSON body — Quoted placeholders (
"{{var}}") become JSON-typed literals; numbers and booleans drop their surrounding quotes automatically. Unquoted placeholders are inserted verbatim.
7.6 Misspelled Variable References
A{{misspelled_var}} that does not exist renders as an empty string at runtime. The system does not raise an error mid-call. The validator can flag undeclared references at design time, but if a typo slips through, expect silent empty output. Always test with realistic variable values.
7.7 Where Variables Get Populated
7.8 System Dynamic Variables
These are provided by the platform and can be interpolated without declaring them in the Variables panel:
Use
{{current_date_time_utc}} rather than asking the LLM what day it is, and {{sip_call_id}} when you need to correlate a call with carrier-side logs.
7.9 Secret Variables
Any workflow variable, Variable-Extraction field, Collection step field, or Call API / tool response mapping can be flagged secret. A secret value is redacted out of every prompt and scrubbed from webhook tool results — the LLM never sees it — while remaining fully usable in the places that need the real value. Where a secret value still works:- API request headers (this is the intended home for tokens and API keys).
- URL slots and request bodies.
- Transfer destinations.
- SMS destinations, credentials, and a static SMS body.
- Math-mode Decision and edge conditions (with the value masked in telemetry).
- Rejected in LLM-mode Decision conditions and anywhere else the value would have to enter a prompt.
- Masked in debug events, decision branch telemetry, API-response logs, and the
collection_completeevent.
- ✅ Declare every credential as a secret variable and reference it from a header. This replaces the older advice of “just use header-based authentication” — the redaction mechanism now exists and should be used.
- ✅ Use a static SMS body when the message must contain a secret (a one-time code). An LLM-generated body cannot see it.
- ❌ Do not expect to branch on a secret in LLM mode. Use math mode.
- ❌ Do not assume redaction covers a value you concatenated into a non-secret variable upstream. Flag the variable that actually holds the secret.
- Flag a variable secret, use it in a header, and confirm the API receives the real value while the debug timeline and logs show it masked.
- Reference a secret from an LLM-mode Decision condition; confirm validation rejects it.
- Reference the same secret from a math-mode condition; confirm routing works and telemetry is masked.
7.10 Common Variable Pitfalls
- Reading a variable before it was populated. Renders as empty. Order your nodes so the variable is populated upstream.
- Type mismatch in Decisions. A boolean stored as the string
"yes"will not equal the booleantrue. Set the source’s type explicitly, or use case-insensitive string comparison. - Whitespace. The system trims most extracted values, but external API responses may include trailing spaces. If a comparison fails unexpectedly, log the actual value in a test call and inspect.
- Two producers for one variable. If two nodes write to the same variable name, the later one overwrites. The validator warns; rename one or consolidate.
8. Speech, Language & Model Selection
Three pluggable services drive every voice interaction: Speech-to-Text (STT), Large Language Model (LLM), and Text-to-Speech (TTS). Each has a workflow-level default; nodes that run AI can override.8.1 Speech-to-Text Providers
The exact list and labels reflect the current state of the platform; consult the dropdowns for live availability. Common providers include:- Deepgram (Nova family) — High accuracy, low latency, supports all three languages. The default in many setups.
- OpenAI Whisper — Strong general-purpose accuracy. Supports all three languages.
- Google Cloud STT — Google-quality transcription. Supports all three languages.
- Groq Whisper — Whisper run on Groq accelerators for very low latency. Supports all three languages.
- Azure STT — Enterprise-friendly, supports all three languages.
- AssemblyAI — Good in noisy environments. Supports English only and is filtered out of the picker for Japanese and Bangla workflows because the underlying integration does not accept a language setting.
- Speechmatics — English and Japanese. No Bangla.
- AmiVoice — Japanese only.
8.2 Large Language Model Providers
LLMs are language-agnostic — they handle English, Japanese, and Bangla equally well. Choose by capability and cost rather than language. Typical lineups:- Anthropic Claude — Sonnet (high accuracy, strong instruction-following) and Haiku (fast, lightweight).
- OpenAI — GPT-4 family (most capable) and smaller variants for cost-sensitive flows.
- Google Gemini — Pro (capable) and Flash (lightweight, fast).
- Cerebras — Added to the flow LLM factory and the flow schema in mid-2026. Some
verbex-branded model names route through Cerebras. - Custom OpenAI-compatible endpoints — A base URL plus API key, for self-hosted or third-party models that speak the OpenAI API. Supported on the flow path, including parallel-tool-call handling.
- Realtime models — Special low-latency models that combine STT/LLM/TTS in one component for the most natural turn-taking.
- OpenAI calls request the priority service tier.
- Gemini “thinking” is minimised for latency (pinned to the provider minimum of 128 on 2.5-pro), so do not expect extended reasoning behavior from Gemini on this path.
parallelToolCallsis no longer sent to Google, which rejected it. Parallel tool calling is an OpenAI-family behavior here.
- For long, persona-heavy conversations or anything where adherence to detailed instructions matters: a high-accuracy model.
- For quick yes/no collection steps: a fast, cheap model is fine.
- For Variable Extraction with many fields and tricky phrasings: a high-accuracy model so extractions are reliable.
- For Decision nodes in math-mode: model choice does not affect logic. Choose based on the conversation around the decision, not the decision itself.
- For Call API nodes: LLM choice does not matter — these nodes do not invoke the LLM.
8.3 Text-to-Speech Providers
TTS provider availability depends on the workflow language. Typical providers include:- OpenAI — Several stock voices (Alloy, Echo, Fable, Onyx, Nova, Shimmer). English only.
- ElevenLabs — Multiple voice catalogs across model variants. Supports English and Japanese. The newest model also supports Bangla.
- Cartesia — Streaming-optimized voices, low latency, English (and Japanese in the streaming model).
- Deepgram Aura — Streaming English voices.
- Azure — Microsoft neural voices, English.
- Inworld — Available on the flow path. It takes no language parameter at all, so language filtering does not apply to it; audition it directly for your workflow’s language.
- Google TTS — Note for Bangla workflows: Google resolves Bangla to
bn-IN, notbn-BD. Google ships no Bangladesh Bangla voice. Use Verbex for bn-BD. - Verbex / PIA (in-house) — The native TTS for Bangla and Japanese, and now English as well (added July 2026; English routes through the same BD endpoint as Bangla, with the English speaker supplied by the workflow config). Eighteen named in-house speakers covering male and female voices.
8.3.1 Speech Speed
A per-call playback-speed factor is applied to every flow node agent. It is worth knowing precisely because it is not a Flow Builder field — it comes from the agent configuration, so an author looking for it on the canvas will not find it. If a workflow sounds faster or slower than expected and no TTS setting explains it, check the agent config with engineering. (The librosa/WSOLA time-stretch engines were removed from the pipeline after the initial integration.)8.4 Default Provider per Language
Out of the box, switching to a new language sets sensible defaults that the QA team can rely on as a baseline:
Exact model names visible in the picker may change over time; rely on the dropdowns for the live list.
8.5 Per-Node Overrides
Override at the node level when a single node has different needs from the rest of the workflow. The override surfaces in the model-configuration section of the property panel.
Only three places accept model overrides: Conversation nodes, Collection steps, and Variable Extraction nodes. Neither
DecisionNodeData nor EndCallNodeData has a model-config field, so an LLM-mode Decision and an AI-generated farewell both run on the workflow defaults — there is no per-node knob for either, despite both invoking an LLM.
When QA should specifically check overrides:
- An override on one Conversation node means that node will speak in a different voice than the rest of the workflow. Verify the change is audible.
- A Variable Extraction node with a higher-accuracy LLM override should produce more reliable extractions on tricky inputs.
- A Conversation in Static-only mode does not call the LLM at runtime — overriding the LLM there has no audible effect, only a slight metadata difference.
- If a Decision or a farewell is misbehaving, the fix is the workflow default LLM or the prompt, not a node override.
8.6 Voice Preview
Today, the Flow Builder does not have a one-click voice preview button next to the voice picker. The standard way to audition a voice is to start a Test Agent call (see Section 11) and listen to the voice on a real conversation. Test calls are short and inexpensive, so cycling through voices this way is practical for QA.8.7 Mixed-Language Workflows
A single workflow has one language. Truly bilingual workflows are not supported at the workflow level. Workarounds:- Override the TTS voice on individual nodes to give different segments different sound profiles within the same language.
- For genuine bilingual flows, build two separate workflows and route between them at the telephony layer.
9. Fine-Tuning Examples
Fine-tuning examples are short conversation snippets you provide to teach the LLM how to behave at a specific node. They are optional. Add them when testing reveals that a node is not behaving as expected.9.1 Where Fine-Tuning Examples Live
Different node types accept different categories of examples.- Response examples — Show the agent how to respond in a turn. Available on Conversation and Variable Extraction nodes.
- Transition examples — Show the agent which outgoing edge to pick from a given context. Available on Conversation, LLM-mode Decision, and Call API nodes. Math-mode Decisions do not use examples — the math is deterministic.
9.2 What an Example Looks Like
An example is a labeled list of conversation turns in order. Each turn is one of:- User turn — Caller speech.
- Agent turn — What the agent should say.
- Function-call turn — A tool the agent invokes, with arguments. (Available where tools are usable, primarily Conversation nodes.)
- Function-result turn — The output of the tool.
9.3 How to Add an Example
1
Open the property panel
Select a node that supports examples.
2
Open the Fine-Tuning Examples modal
Click the Fine-Tuning Examples button. A modal opens with tabs for Response and Transition (whichever apply).
3
Add an example
Click Add example.
4
Label it
Optionally label the example with a memorable name (“escalation when caller is angry”).
5
Add turns
Add turns one by one. Drag to reorder if needed.
6
Pick the target edge
For a transition example, select the target outgoing edge from the dropdown.
7
Save
Save the example.
9.4 When to Add Examples
- After testing reveals a recurring error. If the agent keeps misinterpreting
"free trial"as a refund request, write an example that disambiguates. - When the LLM consistently picks the wrong branch. A transition example for the troublesome path usually fixes it.
- When extraction is shaky. For Variable Extraction nodes, response-style examples that show how to format an answer raise extraction quality on tricky phrasings (informal dates, abbreviations, regional idioms). This applies to Variable Extraction only — Collection steps do not accept examples.
- When you write a new node that uses sophisticated phrasing. A few examples up front pre-empt early issues.
9.5 When Not to Add Examples
- The instructions alone produce correct behavior in tests. Adding unneeded examples is just noise.
- The task is simple — “ask for a name and store it” needs no examples.
- The example would be longer than the entire instruction. If the instruction is the issue, fix the instruction first.
9.6 Best Practices
- Start small. Two to five examples per node is usually enough.
- Cover the typical case first. A short, realistic exchange that mirrors how callers actually phrase things.
- Add edge-case examples second. Once the typical case works, write examples for the variants you have seen go wrong (slang, regional idioms, hesitations, off-topic detours that you want gracefully redirected).
- Use real call transcripts when possible. Manufactured examples tend to read unnaturally.
- Keep turns short. Long, monologue-style examples bloat the prompt.
- Use
{{variable}}inside example turn text when the example would only make sense with a specific value present. The interpolation resolves at runtime. - Iterate on tests. Add an example, run a test, see if behavior improved. If not, refine the example or rethink the instruction.
9.7 Validation Notes
- Response examples on a node type that does not support them (e.g., a math-mode Decision, or a Collection node) are flagged with a warning and ignored at runtime. Either move them to the right node or delete them.
- Transition examples must reference outgoing edges that actually exist. If an edge is deleted, examples pointing to it are flagged.
10. Knowledge Bases
A knowledge base is a searchable collection of documents that an agent can consult during a Conversation node. The agent generates a search query, the system returns the most relevant document chunks, and those chunks are made available to the LLM before it answers. This is how the agent answers questions about your policies, prices, FAQs, or product details without you hardcoding everything into instructions.10.1 Creating a Knowledge Base
The Knowledge Base manager is opened from the toolbar.1
Create it
Click New knowledge base.
2
Name it
Give it a descriptive name (e.g.,
Customer Service FAQ, Returns Policy).3
Confirm
Confirm the creation.
4
Upload documents
Inside the new knowledge base, upload documents.
10.2 Supported File Formats
Typical supported formats include PDF, plain text, Markdown, and Word documents. Images, video, spreadsheets, and ZIP archives are not supported. Refer to the upload dialog for the live accepted-format list.10.3 Indexing
After upload, the system processes the document in the background — extracting text, splitting it into chunks, and indexing the chunks for semantic search. While indexing, the document shows a processing indicator. When complete, you’ll see a chunk count next to the document name. You can close the manager during processing — indexing continues in the background.10.4 Attaching a Knowledge Base to a Node
Knowledge bases attach only to Conversation nodes.1
Select the node
Select the Conversation node.
2
Find the Knowledge Base field
In its property panel, find the Knowledge Base field.
3
Pick a knowledge base
Pick a knowledge base from the dropdown.
4
Set Top-K
Optionally set the Top-K results (default 3, range 0–50). Higher values give the LLM more context but slow responses.
10.5 What Happens at Runtime
When the agent is in the Conversation node:- The caller asks something.
- The LLM generates a search query for the knowledge base.
- The system returns the top-K chunks most similar to the query.
- The chunks are added to the LLM’s context.
- The LLM answers using the chunks plus the node’s instructions.
knowledge_base_search tool description was unified across nodes, and it now logs its query and its results, so you can see both in the debug timeline.
10.6 Validation
- A Conversation node referencing a deleted knowledge base produces a validation error. Either re-attach a different knowledge base or set the field back to None.
- An empty knowledge base is not an error; it just means search returns nothing.
10.7 Best Practices
- One focused knowledge base is usually better than many tiny ones. Search runs against the entire knowledge base; combining related material lets the LLM find the right chunk.
- Separate fundamentally different domains. “Legal terms” and “product specs” probably belong in different bases.
- Clean documents before upload. Strip headers, footers, page numbers, navigation boilerplate. Chunks need to be self-contained to be useful.
- Structure long documents. Break a 50-page manual into chapters before uploading. Chunk boundaries align better and recall improves.
- Test KB relevance. During a test call, watch the debug panel for search events. If the chunks returned aren’t the ones you’d expect, your documents may be unstructured or your queries may be off.
- Knowledge base vs. instructions. Use the knowledge base for facts that change or that you want to manage outside the workflow (policies, prices). Use instructions for rules of behavior (tone, scope, safety).
11. The Test Agent (Voice Testing)
The Test Agent button starts a real voice session against your current workflow so you can hold a conversation with the agent in your browser.11.1 Starting a Test
1
Click Test Agent
Click Test Agent in the toolbar.
2
Validation runs
The system runs validation. If errors exist, the test is blocked and the validation panel shows what to fix.
3
Session starts
The system spins up a fresh agent session in the background and connects your browser microphone.
4
Agent goes live
Within a few seconds, the test panel slides out and the agent is live.
11.2 Session Lifetime and Limits
- A test session auto-expires after 15 minutes. The panel closes automatically.
- You can stop a test early at any time with the Stop Test button.
- Only one test session can run at a time. The Test Agent button is disabled until the active session ends.
- Test calls consume real STT, LLM, and TTS quota at your providers, plus telephony resources. They are inexpensive but not free; do not leave them running idle.
11.3 Controls During a Test
- Mute / unmute your microphone.
- Stop test to end immediately.
- Audio levels indicate whether the agent and you are being heard.
- The agent can also end the call itself if its End Call node fires.
11.4 Live Debug Timeline
The right side of the test panel streams a transcript and debug events as they happen.- Transcripts — Both sides of the conversation, agent in one color and caller in another, updated in near real time.
- Tool calls — Every tool the agent invokes, with arguments and results. Failures are clearly marked.
- Variable updates — Whenever a Collection step or Variable Extraction node writes a value, the variable name and new value appear.
- HTTP requests — Each Call API node’s request, with method, URL, status code, and duration. The request body appears in call logs.
- API response payloads — The response body itself, with secret variables and sensitive plain text redacted.
- Knowledge base searches — The generated query and the returned results.
- Node transitions — A breadcrumb of which node the agent is currently in.
- Decision results — Which condition matched and why (showing the variable value, the operator, and the expected value for math-mode). Secret values are masked.
- Collection step markers — Step start and step completion lines. The
collection_completeevent redacts secret-flagged fields.
11.5 What to Watch For
- Wrong node activated. The canvas highlights tell you which node the agent is in. If it is the wrong one, the upstream edge or condition is misconfigured.
- Wrong variable value. The variable update event shows what got stored. If the value is wrong, the upstream Collection step’s instructions or the LLM’s extraction need work.
- Wrong API request. The HTTP event shows the actual URL and body sent. If it’s malformed, a
{{variable}}is empty or the template is wrong. - Wrong decision branch. The decision event shows the variable and the comparison. If it is wrong, the condition needs tightening or the upstream variable needs the right type.
- Tool call errors. Expand the failed tool to see the error. Some are transient (rate limits, network), some are configuration issues (bad URL, missing credential).
11.6 Common Failure Modes
- Validation blocks the test. Read the message, fix the highlighted node, retry.
- Agent never speaks. Usually the agent process failed to start (missing API key, malformed configuration). Check with engineering if this happens repeatedly.
- Tool failures. Often transient. Retry. If the same tool fails repeatedly, verify the configuration in the Conversation node.
- Decision misfires. Switch to math-mode if you can express the rule deterministically; otherwise add transition examples.
12. Validation, Save, Import & Export
12.1 Validation
The system validates the workflow continuously. Validation feedback shows up in three places:- Per-node red highlights when a specific node has problems.
- Per-edge red highlights for invalid connections.
- Validation panel listing every error and warning, grouped by severity.
- Disabled action buttons. Test Agent and Export refuse to run when blocking errors exist.
- Workflow has no Start node, or has more than one.
- A node is unreachable from Start.
- An edge points to a node that no longer exists.
- A Conversation has an on-reply edge alongside other outgoing edges.
- A Decision has no default branch.
- A condition references a variable that does not exist.
- A Collection step is missing a field name or description.
- A Variable Extraction field name is invalid (wrong characters or duplicate).
- A Call API URL or JSON body has a syntax error.
- A workflow variable is declared more than once.
- A variable uses a reserved internal name (
_previous_node,_global_cooldown,_secret_vars). - A secret variable is referenced from an LLM-mode Decision condition.
- An SMS node is missing credentials or a body (enforced in workflow preflight).
- A warm-transfer no-answer message fails validation.
- Any text field exceeds its length limit, or any numeric field falls outside its range (tables below).
Enforced numeric ranges. Every numeric field is range-validated. The minimum is 0, not 1:
Representative non-blocking warnings:
- A variable is declared but never used.
- A node has no outgoing edges (dead end) and is not an End Call.
- Two nodes write to the same variable name (last writer wins).
- A pronunciation rule has an empty term and will be ignored.
- Fine-tuning examples are configured on a node type that doesn’t support them.
12.2 Auto-Save
Every change is auto-saved to the browser’s local storage. Closing the tab and reopening it on the same browser/device restores your work. There is no Save button; saving is implicit.12.3 Export
Click Export to download the workflow as a JSON file. Exports are blocked while validation errors exist. The file contains everything needed to reconstruct the workflow: nodes, edges, variables, presets, global prompt, pronunciations, agent defaults, language, fine-tuning examples. Use Export for:- Sharing a workflow with a teammate.
- Backing up before a major change.
- Storing in version control.
12.4 Import
Click Import to load a previously exported JSON file. Importing replaces the current workflow — back up first if you want to keep the current state. Schema-mismatch behavior: the system intentionally rejects workflows exported from older schemas. Old files will fail to import with a clear error message rather than silently transforming into something unintended. The system does not migrate legacy shapes. If you have an old export that won’t import, rebuild the workflow from scratch in the current Builder.13. Canvas Interactions & Shortcuts
13.1 Adding and Removing Nodes
- Drag a node type from the left palette onto the canvas.
- Click a node to select it and open its property panel.
13.2 Connecting Nodes
- Click and drag from a node’s outgoing port to another node’s incoming port to create an edge.
- Edges that violate connection rules (e.g., trying to point into Start) are rejected with a brief warning.
13.3 Layout
- Drag nodes to reposition them. Position is purely visual — the workflow runs identically regardless.
- The Auto Layout button arranges all nodes hierarchically into a clean top-to-bottom flow. Useful after lots of edits.
- Zoom in/out with the canvas zoom controls or the mouse wheel.
- Pan with spacebar + drag, or middle-click drag.
- The minimap shows the entire workflow in miniature; click in it to jump to that area.
13.4 Selection
- Click a node or edge to select it.
- Click empty canvas to deselect.
- Multi-select, copy/paste, and built-in undo/redo are not available today. Use Export to preserve a known-good state before major changes.
13.5 Property Panel
- The right-side panel reflects whatever you have selected.
- Changes apply immediately (no save button).
- Some sections are collapsible (model configuration, voice settings, fine-tuning examples).
14. Cross-Cutting Rules
These hold across the entire Flow Builder:- A workflow has exactly one Start node. Nothing connects into it.
- Every node has a unique internal identifier.
- Deleting a node deletes its edges.
- All nodes (other than Start) should be reachable from Start; orphans are flagged.
- Every workflow needs at least one path from Start to a terminating node (End Call or Transfer).
- Variables must be declared at workflow level or produced by an upstream node before they are read.
- Variable names are unique across the entire workflow, including names produced by Collection steps, Variable Extraction fields, and Call API mappings.
- Workflow language sets a single language for the whole workflow; no built-in mixed-language support.
- LLMs are language-agnostic; STT and TTS are language-specific.
- There are ten node types: Start, Conversation, Collection, Variable Extraction, Call API, Decision, Transfer, SMS, Press Digit, End Call.
- Knowledge bases attach only to Conversation nodes.
- Author-configured tools attach only to Conversation nodes. The compiler additionally injects escape tools (global handoff, end call, transfer) into the Collection orchestrator.
- Model overrides exist on exactly three things: Conversation nodes, Collection steps, Variable Extraction nodes.
- Fine-tuning examples exist on exactly three things: Conversation (response + transition), Variable Extraction (response), Decision LLM-mode and Call API (transition). Collection accepts none.
- Secret-flagged values never enter a prompt; they still reach APIs, transfers, SMS, and math-mode conditions.
- All timing fields in the schema are milliseconds.
- On non-realtime sessions the caller is heard during Call API and SMS nodes; realtime sessions mute them. End Call, Transfer, Press Digit, Decision, and Variable Extraction are muted.
- System-spoken lines (retry fillers, hold acknowledgments, KB wait messages) are excluded from the LLM chat context.
- Every text field has a length limit and every numeric field a range; both are enforced by the validator (Section 12.1).
- Prompt-injection order is global prompt → prompt presets → node-level instructions, with fine-tuning examples layered in last as in-context demonstrations.
- Auto-save is local to the browser; truly portable workflows live in exported JSON files.
- Old exported workflows are rejected on import; the system does not migrate them.
- Test calls auto-expire after 15 minutes.
15. QA Test Checklists by Area
Use these as starting points; expand for your specific workflow.15.1 Workflow-Level Configuration
- Switching language updates STT and TTS dropdowns and resets incompatible selections.
- Switching language does not alter the LLM selection.
- The global prompt is reflected in the agent’s tone across multiple nodes.
- Toggling a prompt preset produces audible behavior change consistent with the preset description.
- Pronunciation rules affect the spoken output (not transcripts or LLM reasoning).
- Pronunciation rules with empty terms are ignored.
- Variables declared in the panel render correctly when interpolated.
- Default values for variables are present at call start.
- A global prompt over 20,000 characters is rejected by the validator.
- System dynamic variables interpolate without being declared;
{{sip_call_id}}is populated on inbound phone calls and empty on outbound and web calls. - Reserved internal names (
_previous_node,_global_cooldown,_secret_vars) are rejected. - Playback speed matches the agent config (this is not a Builder field).
15.2 Nodes
- Each node’s opening message option (none / static / AI-generated) plays as expected.
- Conversation nodes respect the “allow ending call” toggle.
- Conversation nodes with knowledge bases retrieve and use document content.
- Collection node steps re-ask on type mismatch and on values outside enum allowed-values.
- Collection early-exit fires when its condition becomes true.
- An optional Collection step can be skipped after the agent confirms with the caller.
- Escape routes work mid-collection: global handoff, end call, transfer.
- Global node fires on its trigger condition, honors cooldown steps, and returns per its return behavior.
- Variable Extraction fills variables from prior conversation history without asking the caller.
- Variable Extraction leaves missing fields empty/null without crashing.
- Call API success and error edges fire under correct conditions.
- Call API value-type coercion (Auto / String / Number / Boolean) behaves as expected.
- Decision math-mode evaluates conditions in order; first match wins.
- Decision LLM-mode picks the right branch on representative caller utterances.
- Call API retry, error-fallback, and error-terminal messages are spoken at the right moments, in the workflow’s language when left unset.
- Call API bodies encode correctly for JSON, form-urlencoded, and multipart Content-Types.
- Transfer cold mode connects directly; warm modes speak hold and whisper messages to the right parties.
- Warm transfer ringing timeout cancels the leg and plays the localized no-answer message.
- SMS sends with a static body and with an LLM-generated body; success and error edges fire correctly.
- SMS preflight blocks export when credentials or body are missing; non-E.164 recipients are rejected.
- Press Digit reaches the intended IVR branch; detection delay tuning changes the outcome as expected.
- End Call plays the configured farewell, fires the webhook, and ends the call cleanly.
- Conversation-node tool response mappings write into variables with correct type coercion.
15.2a Caller Audio During Function Nodes
- On a non-realtime session, speech during a Call API or SMS node lands in the transcript.
- That speech reaches the next node’s chat context (the agent acknowledges it).
- Hold acknowledgments escalate and are rate-limited to no more than one per 8 seconds, in en / bn / ja.
- On a realtime session, the caller is muted through function nodes (historical behavior).
- End Call, Transfer, and Press Digit nodes mute the caller.
- System-spoken filler does not appear in the LLM chat context (the agent never replies to its own hold line).
- Re-test previously reported transcript-loss bugs around on-reply edges and node handoffs — both were fixed in August 2026.
- Re-run all Japanese interruption-tolerance tests; the ja-JP VAD threshold and sample rate changed in August 2026.
15.3 Edges
- Edge labels appear on the canvas;
{{variable}}syntax in labels does not interpolate. - LLM-mode edge prompts do interpolate variables at runtime.
- On-reply edges cannot coexist with other outgoing edges from the same Conversation.
- Decision default edge fires when no condition matches.
- Error edges on Call API nodes fire on timeout or error response.
- An edge with the legacy
summarizedmemory mode behaves asfullafter import.
15.4 Variables
- Names with disallowed characters or starting with a digit are rejected.
- Reserved keywords are rejected with a clear message.
- Duplicate variable names across the workflow are rejected.
- Boolean and date interpolation render in the expected formats.
- Missing variables interpolate as empty strings, not the literal word “none.”
- URLs interpolate with proper encoding.
- A secret variable reaches an API header intact but is masked in debug events and logs.
- A secret variable is rejected in an LLM-mode Decision condition and accepted (masked) in math mode.
- A secret-flagged Collection field is redacted in the
collection_completeevent.
15.5 Test Agent
- Validation errors block the test.
- Test session expires automatically at 15 minutes.
- Stop Test ends the session immediately.
- Live transcript reflects the actual conversation.
- Variable update events appear when expected.
- Decision events show the matched condition, with secret values masked.
- HTTP events show actual URL, status, and duration, plus the response payload with secrets redacted.
- Knowledge base search events show the query and the returned results.
- Active node highlight on the canvas matches the agent’s current location.
15.6 Save / Import / Export
- Auto-save persists changes across page reloads on the same browser.
- Local storage does not sync across browsers/devices.
- Export is blocked when validation errors exist.
- Imported workflow replaces the current canvas state.
- Importing an old, incompatible export produces a clear rejection message.
15.7 Knowledge Base
- Documents process and produce a chunk count.
- Attaching a knowledge base produces relevant retrievals during a test call.
- Detaching the knowledge base prevents retrieval.
- Deleting a document removes its chunks from search results.
16. Best Practices Summary
A condensed checklist of guidance from the rest of the document. Workflow design- Keep each node focused on one job. Use Conversation for dialogue, Collection for slot-filling, Variable Extraction for parsing, Decision for branching.
- Always have an end. Every reachable path should lead to an End Call or a Transfer.
- Always wire the error edge on Call API nodes.
- Always have a default edge on Decision nodes (the validator enforces this).
- Use the global prompt for persona-level guidance. Use prompt presets for tone and accuracy rules. Use node-level instructions for what to do at this specific step.
- Don’t duplicate preset rules in instructions. Don’t put step-by-step flow logic in the global prompt.
- Use the Natural Speech Output preset on any workflow that speaks numbers, prices, dates, or URLs.
- Use Honest Identity and Stay In Scope for any production-facing workflow.
- Set explicit value-types on Call API response mappings whenever the variable will feed a Decision.
- Use enum types for fixed answer sets — the agent will keep re-asking until the answer is in your list.
- Use ISO date format (
YYYY-MM-DD) so date comparisons work correctly. - Use case-insensitive equality (
equals_ci) for LLM-extracted text comparisons. - Flag every credential as a secret variable and reference it from a request header. Branch on secrets in math mode only.
- Use the system dynamic variables (
{{current_date_time_utc}},{{from_number}},{{sip_call_id}}) instead of collecting or inferring what the platform already knows.
- Order math-mode conditions from most specific to most general.
- For LLM-mode decisions on tricky branches, add a few transition examples.
- Edge labels are documentation, not logic; logic lives in conditions.
- Default models are sensible. Override only when a node’s task is significantly more or less demanding than the rest of the workflow — and remember overrides exist only on Conversation, Collection steps, and Variable Extraction.
- LLM choice doesn’t affect Decision math-mode or Call API. An LLM-mode Decision and an AI-generated farewell always use the workflow default, so set that default with them in mind.
- For Bangla workflows, prefer Verbex TTS for natural speech. Google resolves Bangla to
bn-IN, so avoid it when you need bn-BD. - For Japanese workflows, ElevenLabs (multilingual) and Verbex are both strong choices.
- Verbex/PIA TTS now speaks English too (routed through the BD endpoint), so it is a valid option for English workflows as well.
- Set the retry / error-fallback messages on Call API nodes and tools in any non-English workflow, or accept the language-matched defaults — never leave them to English filler.
- Use one focused knowledge base per topic area.
- Clean documents before upload (remove headers, footers, navigation).
- Pair with Stay In Scope to prevent hallucinated answers.
- Add them after testing reveals a real failure mode, not preemptively.
- Two to five per node is usually enough; more is rarely better.
- They exist on Conversation, Variable Extraction, LLM-mode Decision, and Call API only — not on Collection.
- Use real call transcripts when possible; manufactured examples often read unnaturally.
- Run a Test Agent call after every significant change.
- Watch the debug timeline. The active node highlight, the variable updates, and the decision events tell you whether the agent did what you intended.
- Export before making sweeping changes — there is no built-in undo.
- Auto-save is local to the browser only. Export to back up.
- Old workflow exports do not import into newer Builder versions. Re-export when the schema changes.
16.1 Not Yet Shipped — Do Not Test Against This Guide
Two pieces of work exist on unmerged branches as of 14 August 2026 and are not inorigin/v2/main. They are listed only so QA does not chase behavior that isn’t deployed:
17. Glossary
- Agent — The live AI persona handling the call.
- Canvas — The main editor area where nodes and edges are arranged.
- Edge — An arrow between two nodes; defines transition.
- End Call — The terminal node that hangs up the call.
- Escape tool — A compiler-injected tool inside a Collection node that lets the caller leave slot-filling early (global handoff, end call, transfer).
- Fine-tuning example — A short conversation snippet provided to the LLM at a specific node to bias its behavior.
- Global node — A Conversation node reachable from anywhere in the workflow when its trigger condition fires; carries a trigger condition, cooldown steps, and a return behavior.
- Hold acknowledgment — A rate-limited, escalating system line spoken to the caller while a Call API or SMS node runs, so the line does not go dead.
- Global prompt — Workflow-wide persona/brand instruction prepended to every conversational agent.
- Interpolation — Replacement of
{{variable}}placeholders with current values at runtime. - Knowledge base — A document collection an agent can search during a Conversation node.
- LLM (Large Language Model) — The model that reasons and produces speech-text responses.
- Node — A single step or action in a workflow. Ten types exist.
- Press Digit — The node that emits DTMF tones to navigate an external IVR.
- Prompt preset — A vetted, toggleable instruction snippet applied across the workflow.
- Secret variable — A variable whose value is redacted from every prompt but still reaches APIs, transfers, and SMS.
- SMS node — The node that sends a text message mid-call via the configured provider.
- STT (Speech-to-Text) — The model that transcribes the caller’s voice.
- System dynamic variable — A platform-provided variable (
{{call_id}},{{from_number}}, …) usable without being declared. - TTS (Text-to-Speech) — The model that voices the agent’s replies.
- Transition example — A fine-tuning example that shows which outgoing edge to take from a given context.
- Variable — A named bucket of information that travels with the call.
- Workflow — One complete agent definition, comprising a Start node plus all connected nodes, edges, variables, and configuration.
End of guide. For questions about behavior not covered here, consult engineering — they can verify directly against the current build.

