# Flow Builder Source: https://docs.verbex.ai/agents/conversation-flow-builder ## Table of Contents 1. [Introduction & Mental Model](#1-introduction--mental-model) 2. [The Workspace at a Glance](#2-the-workspace-at-a-glance) 3. [Workflow-Level Settings](#3-workflow-level-settings) 4. [The Ten Node Types](#4-the-ten-node-types) 5. [Connections (Edges) Between Nodes](#5-connections-edges-between-nodes) 6. [Decision Logic & Operators](#6-decision-logic--operators) 7. [The Variable System](#7-the-variable-system) 8. [Speech, Language & Model Selection](#8-speech-language--model-selection) 9. [Fine-Tuning Examples](#9-fine-tuning-examples) 10. [Knowledge Bases](#10-knowledge-bases) 11. [The Test Agent (Voice Testing)](#11-the-test-agent-voice-testing) 12. [Validation, Save, Import & Export](#12-validation-save-import--export) 13. [Canvas Interactions & Shortcuts](#13-canvas-interactions--shortcuts) 14. [Cross-Cutting Rules](#14-cross-cutting-rules) 15. [Best Practices Summary](#15-best-practices-summary) 16. [Glossary](#16-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](#79-secret-variables). * 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. Everything else in this document expands on these concepts. *** ## 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. When the workspace looks crowded, you can collapse panels you're not using. Auto-save is always on; closing the browser does not lose your work as long as you reopen on the same browser/device (see [Validation, Save, Import & Export](#12-validation-save-import--export)). *** ## 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. **A workflow has exactly one language.** You cannot mix languages at the workflow level. You can override the TTS voice on individual Conversation or Collection nodes, so a single English workflow could speak one segment in a British voice and another in an American voice — but the workflow language itself stays one of the three. ### 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 **What you can do here:** * 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. **What you should not put here:** * 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). **Length guidance:** There **is** a hard limit — the validator rejects a global prompt over **20,000 characters**. (The ceiling has been raised three times; see [Section 12.1](#121-validation) for the full table of enforced length limits.) Practically, 1–4 sentences is best. Long global prompts inflate token usage on every turn. ### 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. **Accuracy & Format** * **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. **Trust & Safety** * **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. **Do's and don'ts:** * ✅ 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 **Normalization rules applied automatically:** * 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. **What it affects:** * The TTS audio the caller hears. **What it does not affect:** * 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). **Gotchas:** * Matching is **literal text**, not whole-word. A pronunciation for `API` will 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](#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](#78-system-dynamic-variables). ### 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](#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. Both can be tightened on a per-node basis when a Conversation or Collection step needs different tolerance. **All timing fields in the underlying schema are milliseconds** (`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 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. **What you configure here.** * **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](#37-workflow-level-voice-behavior). **Runtime behavior.** When the call connects, the system applies workflow language defaults, sets up interruption rules, and immediately hands off to the next connected node. The Start node never speaks; it is purely structural. **Restrictions.** * 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. **Test ideas.** * 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). **What you configure here.** *Behavior tab* * **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](#10-knowledge-bases). * **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 `6` against 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](#9-fine-tuning-examples). * **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*. Several bugs in this area were fixed in July–August 2026 (a same-turn race in handoff, chat-context passing into the global node, cooldown being consumed after a completed Collection step on the realtime path), so these settings are now load-bearing and worth testing directly. *Tools tab* * **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](#74-call-api-response-coercion)). 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](#45-call-api). *Model configuration* * 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. **Runtime behavior.** On entry, the agent optionally speaks an opening message, then listens. It interprets caller speech, retrieves from the knowledge base if attached, calls tools as needed, and produces a response. After speaking, it evaluates the outgoing edges to choose where to go next. If multiple edges match, it picks the best fit; if none match clearly, it takes the default edge if one exists. **Do's and don'ts.** * ✅ 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. **Test ideas.** * 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. **What you configure here.** * **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 sibling `skip_` 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_complete` debug event. See [Section 7.9](#79-secret-variables). * **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](#42-conversation)). * **Use separate TTS** — A latency optimization that splits TTS synthesis from speech recognition. * **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. **Runtime behavior.** The opening message is spoken once. Then each step runs in sequence: the agent uses the step's opening line (or improvises) to ask, listens, attempts to extract a value matching the type, and re-asks politely if extraction fails. Successful extraction stores the value into the step's variable. After every step, the early-exit condition (if defined) is evaluated; if true, the early-exit edge fires. Once all steps complete, the single outgoing edge is taken. **Escaping a collection block mid-slot-filling.** The Collection orchestrator now carries **escape tools**, so a caller can leave the block partway through: global-node handoff, end call, and transfer all work from inside a collection. This is why "get me a human" halfway through slot-filling now works instead of being ignored until the last step. These are compiler-injected — you do not configure them, and you cannot add your own tools here. **Do's and don'ts.** * ✅ 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). **Test ideas.** * 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_complete` debug 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. **What you configure here.** * **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](#79-secret-variables). * **Fine-tuning examples** — Optional (response examples). Strongly recommended when extraction is tricky. See [Section 9](#9-fine-tuning-examples). * **Model configuration** — LLM override only. STT and TTS are not used here. **Runtime behavior.** When the node is entered, a single LLM call is fired against the existing conversation history. Each field is filled if the LLM can find a match; otherwise it is left empty (`""` 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. **Test ideas.** * 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). **What you configure here.** * **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.status` that points into the response. * **Variable name** — Where to write the extracted value. * **Value type** — Choose from *Auto*, *String*, *Number*, *Boolean*. See [Section 7.4](#74-call-api-response-coercion) for what each does. * **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. **Runtime behavior.** Variables are interpolated, the request is sent, the optional waiting line is spoken, the response is parsed, mapped values are written into variables, and the success edge fires. On timeout, network failure, or non-OK HTTP status, the error edge fires instead. If no error edge is wired up, the workflow may dead-end on failure — always wire one. **Reliability behavior QA should know about** (all current as of August 2026): * 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](#40-is-the-caller-heard-while-a-node-runs). **Do's and don'ts.** * ✅ 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 `true` doesn'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](#79-secret-variables)) 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. **Test ideas.** * 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. **What you configure here.** * **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](#61-math-expression-operators). * **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.** `DecisionNodeData` has no model-config field. An LLM-mode Decision runs on the **workflow default LLM** — there is nothing to override here. **Runtime behavior.** Conditions are evaluated **in order, top to bottom**. The first match wins. If no condition matches, the default edge fires. **Secret variables in decisions.** A secret-flagged variable is **rejected** in an LLM-mode condition (the value would have to enter a prompt). It is **allowed** in math-mode routing, and the branch telemetry masks the value. If you need to branch on a secret, use math mode. **Do's and don'ts.** * ✅ 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 against `true` directly, or convert at the source). **Test ideas.** * 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). **What you configure here.** * **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. **Runtime behavior.** Cold transfers happen instantly via call signaling. Warm transfers put the caller on hold, dial the destination, optionally whisper context, and bridge once both legs are ready. If the ringing timeout expires first, the leg is cancelled, the no-answer message is spoken, and the caller resumes with the agent. The caller is muted during a Transfer node. **Do's and don'ts.** * ✅ 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. **Test ideas.** * 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). **What you configure here.** * **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](#79-secret-variables). * **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"). * **Failure copy** — The message spoken to the caller when the send fails. **Runtime behavior.** Variables are interpolated, the message is sent through the provider, and the success or error edge fires accordingly. On non-realtime sessions the caller is **heard** during the send and hears a hold acknowledgment rather than dead air (see [Section 4.0](#40-is-the-caller-heard-while-a-node-runs)). **Restrictions and validation.** Credentials and the body are enforced in workflow preflight — a half-configured SMS node **blocks export**. The recipient must be valid E.164. **Do's and don'ts.** * ✅ 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*. **Test ideas.** * 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. **What you configure here.** * **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. **Runtime behavior.** The node waits out the detection delay, emits the DTMF tones, and takes its single outgoing edge. The caller is **muted** for the duration. **Do's and don'ts.** * ✅ 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. **Test ideas.** * 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. **What you configure 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.** `EndCallNodeData` has no model-config field. An AI-generated farewell runs on the **workflow default** LLM and TTS. **Runtime behavior.** The optional farewell is spoken; then the call is hung up; then the optional webhook fires; then resources are cleaned up. The caller is muted for the shutdown itself. **Do's and don'ts.** * ✅ 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. **Test ideas.** * 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 `escalated` and 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 to `full`** with 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 shape `variable 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. Equality is **type-aware for booleans**: `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 match `YYYY-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 with `equals_ci` patterns 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 to `equals_ci`. * Writing `is_member == "true"` against a boolean variable. Compare against the boolean directly, or use `valueType: boolean` on 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 `exists` rejects empty strings. If the variable was set to `""`, `exists` is **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. **Naming rules.** * 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_name` and `Customer_Name` are 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. `string` is the canonical name; `text` is accepted as an alias. * **Number** — Integer or decimal. Compared numerically in Decision nodes. * **Boolean** — `true` or `false`. 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 `contains` checks). ### 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. **Interpolation is NOT supported in:** * 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 `true` becomes a boolean `true`; a JSON number stays numeric; a string stays a string. Most flexible but prone to surprises in downstream comparisons. * **String** — Forces text. `123` becomes `"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`) into `true` and falsy tokens (`"no"`, `"false"`, `"0"`, `0`) into `false`. Use this when the variable will be compared in a Decision node. **Rule of thumb:** Set value-type explicitly whenever the variable will be used in a Decision. Auto-mode is fine for variables that only get interpolated into text. ### 7.5 Rendering Behavior When `{{variable_name}}` is interpolated, the rendered output depends on the value: * **Boolean** — Lowercase `true` or `false`. 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 | Source | Behavior | | :- | :- | | **Variables panel default** | Pre-populated at call start. | | **Collection node step** | Populated when the step extracts the value from the caller's reply. | | **Variable Extraction node** | Populated silently from chat history when the node runs. Missing fields end up empty/null. | | **Conversation-node tool response mapping** | Populated when the tool returns, using the JSON path you configured (same coercion rules as Call API). | | **Call API response mapping** | Populated when the API call succeeds, using the JSON path you configured. | | **System / call-time** | A fixed set of platform-provided values, always available — see [Section 7.8](#78-system-dynamic-variables). | ### 7.8 System Dynamic Variables These are provided by the platform and can be interpolated **without declaring them** in the Variables panel: | Variable | Value | | :- | :- | | `{{from_number}}` | The originating number. | | `{{to_number}}` | The dialed number. | | `{{call_id}}` | The platform's call identifier. | | `{{call_direction}}` | Inbound or outbound. | | `{{current_date_time_utc}}` | Current UTC date and time at the moment of interpolation. | | `{{sip_call_id}}` | The carrier's SIP Call-ID. **Inbound phone calls only** — it resolves to an empty string on outbound calls and on web calls. | 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). **Where a secret is blocked or masked:** * **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_complete` event. **Do's and don'ts.** * ✅ 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. **Test ideas.** * 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 boolean `true`. 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. When you change the workflow language, an STT selection that does not support the new language is automatically reset to a sensible default for that language. ### 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. **Provider-specific runtime details worth knowing:** * 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. * `parallelToolCalls` is no longer sent to Google, which rejected it. Parallel tool calling is an OpenAI-family behavior here. **When to choose which model:** * 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`**, not `bn-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. Among the in-house Verbex speakers are voices like Maria, Rashida, Hena, Niloy, Rafiq, and others. Each is selectable from the voice dropdown when Verbex TTS is active. The Verbex roster is the recommended choice for any Bangla workflow, the most natural-sounding option for Japanese, and now a viable English option too. #### 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: | Language | STT default | LLM default | TTS default | | :- | :- | :- | :- | | English | Deepgram (latest Nova) | High-tier general model | Stock English voice | | Japanese | Deepgram (latest Nova) | High-tier general model | ElevenLabs multilingual / Verbex | | Bangla | Deepgram | High-tier general model | Verbex (Maria) | 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. | Node type | STT | LLM | TTS | | :- | :- | :- | :- | | Conversation | ✅ | ✅ | ✅ | | Collection (per step) | ✅ | ✅ | ✅ | | Variable Extraction | ❌ | ✅ | ❌ | | Decision (LLM mode) | ❌ | ❌ | ❌ | | Call API | ❌ | ❌ | ❌ | | End Call | ❌ | ❌ | ❌ | | SMS / Press Digit | ❌ | ❌ | ❌ | | Transfer / Start | ❌ | ❌ | ❌ | **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](#11-the-test-agent-voice-testing)) 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. A node can have both kinds when applicable. **Correction:** Collection nodes take **no** fine-tuning examples — neither the node nor the individual step has an examples field in the schema. To improve a shaky Collection step, work on the field description, the step instructions, or the step's LLM override. ### 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. Transition examples additionally specify which outgoing edge the agent should take after the example's final turn. ### 9.3 How to Add an Example Select a node that supports examples. Click the **Fine-Tuning Examples** button. A modal opens with tabs for *Response* and *Transition* (whichever apply). Click *Add example*. Optionally label the example with a memorable name ("escalation when caller is angry"). Add turns one by one. Drag to reorder if needed. For a transition example, select the target outgoing edge from the dropdown. 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. Click **New knowledge base**. Give it a descriptive name (e.g., `Customer Service FAQ`, `Returns Policy`). Confirm the creation. 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**. Select the Conversation node. In its property panel, find the Knowledge Base field. Pick a knowledge base from the dropdown. Optionally set the Top-K results (default 3, range **0–50**). Higher values give the LLM more context but slow responses. Detach by setting the field back to *None*. ### 10.5 What Happens at Runtime When the agent is in the Conversation node: 1. The caller asks something. 2. The LLM generates a search query for the knowledge base. 3. The system returns the top-K chunks most similar to the query. 4. The chunks are added to the LLM's context. 5. The LLM answers using the chunks plus the node's instructions. If no relevant chunks are found, the agent answers without them, falling back to its general knowledge and your instructions. Pair this with the **Stay In Scope** preset if you want the agent to refuse to invent answers. **A wait message is spoken while retrieval runs.** The agent says a short language-aware filler ("one moment, let me check") in English, Bangla, or Japanese, so the line does not go dead during lookup. Like other system-spoken lines, it is kept out of the LLM's chat context. **Retrieval now goes through Cortex.** The legacy KB v1 dependency was removed entirely — all lookups take the Cortex path. The `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 Click **Test Agent** in the toolbar. The system runs validation. If errors exist, the test is blocked and the validation panel shows what to fix. The system spins up a fresh agent session in the background and connects your browser microphone. 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_complete` event redacts secret-flagged fields. The canvas highlights the currently active node, and edges briefly highlight when the agent traverses them. This is the single most powerful QA tool for understanding what the agent actually did vs. what you intended. ### 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. Errors block testing and export; warnings do not but should be addressed. **Representative blocking errors:** * 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 length limits.** These are hard limits in the validator, and they were raised three times between June and August 2026 — the current ceilings are: | Field | Limit (characters) | | :- | :- | | Global prompt | 20,000 | | Node prompt / instructions | 16,000 | | Static text and descriptions | 7,000 | | JSON request body | 32,768 | | URL | 2,048 | | Identifiers and tool names | 64 | | Node labels | 80 | **Enforced numeric ranges.** Every numeric field is range-validated. The minimum is **0**, not 1: | Field | Range | | :- | :- | | Timeout | 0–300 s | | Retry count | 0–10 | | Knowledge base top-K | 0–50 | | User-away timeout | 0–3600 s | | Maximum tool steps per turn | 0–100 | | Minimum words to interrupt | 0–50 | | Global node cooldown steps | 0–1000 | | DTMF detection delay | 0–60,000 ms | | Response delay (min/max pause) | 0–60,000 ms | **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. **Important caveat:** local storage is per-browser, per-device. The workflow does **not** sync across devices, browsers, or users. To move a workflow elsewhere, use Export / Import. ### 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](#121-validation)). * 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. 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). **Prompts and instructions** * 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. **Variables** * 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. **Edges and decisions** * 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. **Models** * 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. **Knowledge bases** * 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. **Fine-tuning examples** * 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. **Testing** * 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. **Operations** * 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. 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.* # Create an AI Agent Using a Template Source: https://docs.verbex.ai/agents/create-ai-agent-from-template Discover how to effortlessly create an AI agent with a pre-defined template in Verbex **What you'll learn** * How to create an AI agent using a template * How to configure the agent with a pre-defined template Starting from scratch when creating an AI agent can be overwhelming and confusing. Using a pre-defined template is a more efficient approach, providing a clearer understanding of the process. In Verbex, you have the option to create an AI agent using a pre-defined template. You can choose from templates available in both Simple and Agentic modes. ## Steps to Create an AI Agent from a Template 1. Navigate to the AI agent page. Create AI Agent from Template 2. Click the "Create AI Agent" button. 3. Choose the mode: Simple or Agentic. 4. For Simple agents, you will see the following templates: Create AI Agent from Template 5. For Agentic agents, you will see the following templates: Create AI Agent from Template 6. After selecting your desired template, you can modify prompts, tools, and other configurations. Create AI Agent from Template More templates will be added in the future to expand your options. Select a template that closely matches your requirements for a more tailored experience. Adjust the prompts, tools, and configurations to better suit your specific needs. Ensure the agent functions as expected by conducting comprehensive tests. # Creating Simple AI Agent Source: https://docs.verbex.ai/agents/create-simple-agent Verbex offers two types of AI Agents: **1. Simple AI Agent** * Basic conversational capabilities * Perfect for straightforward tasks like answering FAQs or booking appointments * Easier to set up and manage * Ideal for most customer service scenarios **2. Agentic AI Agent** * Advanced reasoning and decision-making abilities * Can handle complex, multi-step tasks * More autonomous in problem-solving * Suitable for sophisticated business processes ## Step 1: Access the Dashboard ### Start from the Dashboard The Dashboard is your central control center, providing an overview of your system's activity. Here you'll find everything needed to create and manage your AI Agents. ### Navigate to Agents Section 1. Find the Agents section in the left-hand menu 2. Click to access the Agent management area Agent section in navigation ### Create New Agent Click the green "Create New Agent" button to begin the creation process. You'll be prompted to choose between creating a Simple AI Agent or an Agentic AI Agent. Choose Simple AI Agent if you're new to the platform or need basic conversational capabilities. Select Agentic AI Agent when you need more advanced reasoning and autonomous decision-making abilities. ## Step 2: Choose Your Starting Point You have two options to begin creating your AI Agent: ### 1. Use a Template * Pre-built AI Agents for common use cases * Quick setup for standard scenarios like: * Appointment booking * Customer support * Complaint resolution * Lead generation ### 2. Start from Blank * Build a fully custom AI Agent * Complete control over all settings * Perfect for unique use cases Templates save time for common scenarios, while starting from blank gives you maximum customization options. Templates are available for both Simple and Agentic AI Agents. ## Step 3: Configure Agent Prompt ### Set Behavior and Personality Define how your AI Agent will interact with users through the behavior prompt. The configuration options will vary depending on whether you're creating a Simple or Agentic AI Agent. #### Example Behavior Prompts: For Simple AI Agent: ```text theme={null} You are a professional and friendly AI Agent for [Company Name]. Your role is to provide helpful, accurate information while maintaining a warm and supportive tone. Always prioritize customer satisfaction and clear communication. ``` ### Create Welcome Message Set up the first message users will hear when interacting with your AI Agent. #### Example Welcome Messages: For Simple AI Agent: ```text theme={null} "Hi! I'm [Name], your AI Agent at [Company Name]. How can I assist you today?" ``` Remember to make your welcome message: * Brief and friendly * Clear about who/what the AI Agent is * Inviting for user interaction * Appropriate for the type of AI Agent (Simple or Agentic) ## Step 4: Test Your Agent * On right panel click **Test Call** and then click "Connect\*\* * You conversation will start showing live in the web test call. # Writing Effective Prompts Source: https://docs.verbex.ai/agents/creating-effective-prompts-guide Learn how to write clear instructions for your AI Agent's behavior and interactions * Your prompt is the foundation of your AI Agent's personality and capabilities. It defines how the Agent will interact, make decisions, and utilize available tools. * The **main prompt language will always be English**, but examples can be **language-specific** to accommodate different user bases. * Ensure prompts indicate **cultural nuances** if applicable. ## Core Components ### 1. Identity and Role Define who your AI Agent is and its primary purpose. This sets the foundation for all interactions. **Context Consideration:** * Clearly state the AI’s purpose and domain. * Define whether the AI is task-oriented or conversational. * Specify the expected level of autonomy in decision-making. * Specify the AI agent response language. You can specify the language proficiency also if you want. The response language always be monolingual. We don't support multilingual AI agents yet that can respond or speak in different languages. ```text Simple AI Agent theme={null} You are an AI Agent for Bright Smile Dental, named Emily. Your role is to handle appointment scheduling and basic patient inquiries with a friendly, professional approach. You always respond in English. ``` ### 2. Available Resources Clearly specify the tools and knowledge available to your AI Agent. You don't need to write exact name of the tools. You can write the name of the tool in a general way. ```text theme={null} You have access to: 1. Check calendar tool for viewing appointment availability 2. Book appointment tool for scheduling appointments 3. Knowledge base containing service information and policies ``` ### 3. Behavioral Guidelines Define how your AI Agent should: * Communicate with users * Handle different situations * Make decisions * Maintain professional standards ## Writing Tool Instructions ### Proper Tool Reference Format Always specify tools in general way to ensure clear recognition: ```text Correct ✓ theme={null} Use check calendar availability tool to verify available appointment slots ``` ```text Incorrect ✗ theme={null} Check the calendar to verify available slots ``` ### Tool Usage Flow Provide clear steps for using tools: ```text theme={null} When scheduling appointments: 1. Use check calendar availability tool to find available slots 2. Present options to the patient 3. Once confirmed, use book appointment tool 4. Send confirmation using send email tool ``` ## Knowledge Base Integration Clear instructions about knowledge base usage help maintain accuracy and consistency in responses. ### Reference Guidelines ```text theme={null} When answering questions: 1. First check the knowledge base 2. If information exists, provide exact details from the knowledge base 3. If not found, provide general guidance based on context 4. Always indicate when information comes from outside the knowledge base ``` ## Response Structure ### Communication Standards Define clear expectations for responses: * **Length:** Keep responses concise (2-3 sentences) * **Tone:** Professional yet friendly * **Format:** Clear and structured * **Follow-up:** End with relevant questions ### Conversation Flow ```text theme={null} Maintain natural conversation flow by: - Acknowledging user inputs - Providing relevant responses - Guiding the conversation purposefully - Transitioning smoothly between topics ``` ### Ending Interactions ```text theme={null} Guidelines for concluding conversations: 1. Summarize actions taken or information provided 2. Confirm all questions were answered 3. Provide next steps if applicable 4. End with a professional closing ``` Key elements of good responses: * Clear and concise * Relevant to the query * Professional tone * Appropriate follow-up * Proper conversation closure ## Example Prompts ### Simple AI Agent Example ```text theme={null} You are Emily, an AI Agent for Bright Smile Dental. Your primary role is to assist patients by scheduling appointments, answering inquiries, and providing general guidance about dental services. You always respond in English with a professional, friendly, and helpful tone. TOOLS AVAILABLE: - Check calendar tool: View available appointment slots. - Book appointment tool: Schedule confirmed appointments. - Send email tool: Send confirmation emails. - Insurance check tool: Verify patient insurance details. - Knowledge base: Retrieve accurate information about dental services, procedures, and policies. INSTRUCTIONS: 1. Always greet patients warmly and professionally. 2. For appointment scheduling: - Use check calendar availability tool to find available slots. - Confirm patient preferences before booking. - Use book appointment tool to finalize. - Send a confirmation email using send email tool. 3. For insurance verification: - Use insurance check tool to check coverage. - Provide clear explanations based on results. 4. For general inquiries: - Reference the knowledge base for accurate information. - If the answer is unavailable, provide a general response and suggest contacting the clinic. 5. Maintain a conversational, empathetic, and professional tone. 6. Always end interactions with a relevant follow-up question or next steps. 7. If caller ask non-related questions, politely inform them that you are an AI agent for Bright Smile Dental and you can only help with appointment scheduling, insurance verification, and general inquiries. TONE: Friendly, professional, and informative. ``` ## Best Practices Use specific names and roles Clearly specify when and how to use tools Define when to reference documentation Set clear communication standards Avoid vague instructions that could lead to inconsistent behavior. Always be specific about: * Tool usage conditions * Response requirements * Decision-making criteria * Language expectations and multilingual support where applicable. ## Additional Considerations * Regularly review and refine prompts based on AI performance. * Test AI behavior in different scenarios to ensure consistency in responses. * Consider potential ethical implications and bias in AI-generated content. * Update prompts as tools and knowledge bases evolve to maintain accuracy. * Prepare questionare and evaluate your prompt (Comming Soon in Verbex AI) For further improvements, iterate on prompts through testing and user feedback to achieve optimal AI interactions. More in [Prompting Guideline for Simple Agents](https://docs.verbex.ai/documentation/resources/prompting-guide-simple-agent) # Automatic Prompt Generation for Simple Agent Source: https://docs.verbex.ai/agents/prompt-generation-simple-agent Learn how to automatically generate prompts for simple agents to streamline your workflow and improve agent performance **What you'll learn:** * When to use automatic prompt generation * How to automatically generate prompts for simple agents * How to customize and optimize generated prompts * Best practices for implementing automatic prompt generation ## When to use automatic prompt generation Automatic prompt generation is valuable in these scenarios: * **Limited prompt engineering experience** * Helps users without technical expertise create effective agents * Removes barriers to entry for non-technical users * Enables anyone to create functional agents regardless of skill level * **Standardized workflows** * Ensures consistency across multiple similar agents * Maintains quality and predictability in responses * Particularly beneficial in business and team environments * **Time-saving and complexity reduction** * Provides ready-to-use templates following best practices * Eliminates need to understand prompt engineering nuances * Enables quick updates and iterations to agent capabilities * **Rapid prototyping and testing** * Facilitates quick creation and modification during experimentation * Speeds up testing of new features and capabilities * Reduces time investment during development phases * **Easier agent maintenance** * Simplifies updating agents as needs evolve * Makes maintenance more efficient with parameter adjustments * Reduces errors compared to manually edited prompts ## Creating a New Prompt * Click the **Generate** button from the right side of the prompt editor * Write a description of the prompt you want to generate * Click the **Create** button It will take a few seconds to generate the prompt and display it on the prompt editor. ## Update an Existing Prompt * Click the **Generate** button from the right side of the prompt editor * Write instructions about what you want to update in the prompt * Click the **Update** button. It will take a few seconds to update the prompt and display it on the prompt editor. ## Best Practices When describing what you want to generate, be as specific as possible about the agent's purpose and capabilities. Provide examples of expected interactions to help the generator create more accurate prompts. Use the update feature to refine your prompt gradually rather than trying to get it perfect in one go. Describe the desired outcomes and results rather than just the features you want. Always review and test the generated prompt with sample queries before deploying. # Create AI Agent Source: https://docs.verbex.ai/api-reference/ai-agents-v2/create-ai-agent /api-reference/openapi.json post /v2/ai-agents/ Create a new AI agent with the provided configuration. # Delete AI Agent Source: https://docs.verbex.ai/api-reference/ai-agents-v2/delete-ai-agent /api-reference/openapi.json delete /v2/ai-agents/{agent_id} Delete an AI agent. # Get AI Agent Source: https://docs.verbex.ai/api-reference/ai-agents-v2/get-ai-agent /api-reference/openapi.json get /v2/ai-agents/{agent_id} Retrieve details of a specific AI agent. # List AI Agents Source: https://docs.verbex.ai/api-reference/ai-agents-v2/list-ai-agents /api-reference/openapi.json get /v2/ai-agents/ List AI agents with pagination. # Update AI Agent Source: https://docs.verbex.ai/api-reference/ai-agents-v2/update-ai-agent /api-reference/openapi.json put /v2/ai-agents/{agent_id} Update an existing AI agent. # Create API Key Source: https://docs.verbex.ai/api-reference/api-keys/create-api-key /api-reference/openapi.json post /v1/api-keys/ Create a new API key # Get API Key Source: https://docs.verbex.ai/api-reference/api-keys/get-api-key /api-reference/openapi.json get /v1/api-keys/{key_id} Get API key details # List API Keys Source: https://docs.verbex.ai/api-reference/api-keys/list-api-keys /api-reference/openapi.json get /v1/api-keys/ List all API keys for the user # Revoke API Key Source: https://docs.verbex.ai/api-reference/api-keys/revoke-api-key /api-reference/openapi.json post /v1/api-keys/{key_id}/revoke Revoke an API key # Create built-in tool Source: https://docs.verbex.ai/api-reference/built-in-tools/create-built-in-tool /api-reference/openapi.json post /v2/ai-agents/{ai_agent_id}/builtin-tools/ Create a new built-in tool with the provided configuration. # Delete built-in tool Source: https://docs.verbex.ai/api-reference/built-in-tools/delete-built-in-tool /api-reference/openapi.json delete /v2/ai-agents/{ai_agent_id}/builtin-tools/{tool_id} Delete a built-in tool. # Get built-in tool Source: https://docs.verbex.ai/api-reference/built-in-tools/get-built-in-tool /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/builtin-tools/{tool_id} Retrieve details of a specific built-in tool. # List built-in tools Source: https://docs.verbex.ai/api-reference/built-in-tools/list-built-in-tools /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/builtin-tools/ List built-in tools with pagination. # Update built-in tool Source: https://docs.verbex.ai/api-reference/built-in-tools/update-built-in-tool /api-reference/openapi.json put /v2/ai-agents/{ai_agent_id}/builtin-tools/{tool_id} Update an existing built-in tool. # Download Call Recording Source: https://docs.verbex.ai/api-reference/call-recording/download-call-recording /api-reference/openapi.json post /v1/call-recording/download Download the recording file for a specific call. This endpoint returns the call recording as a binary file (audio). Use this to directly download the recording to your system for storage or processing. # Get Signed URL for Call Recording Source: https://docs.verbex.ai/api-reference/call-recording/get-signed-url-for-call-recording /api-reference/openapi.json post /v1/call-recording/signed-url Get a pre-signed URL to access the recording of a specific call. This endpoint generates a temporary signed URL that can be used to stream or download the call recording. The signed URL expires after a limited time for security purposes. # Create Web Call Source: https://docs.verbex.ai/api-reference/calls/create-web-call /api-reference/openapi.json post /v1/calls/create-web-call Create a new web-based call session with an AI agent. This endpoint initializes a new web call session that allows direct browser-based communication between a user and an AI agent. Use this for implementing click-to-call or embedded chat interfaces in web applications. # Create Web Call (Public Shared) Source: https://docs.verbex.ai/api-reference/calls/create-web-call-public-shared /api-reference/openapi.json get /v1/calls/public/create-web-call Create a web call session using a public shared link. This endpoint enables creating web calls without user authentication, using a shared key instead. Ideal for public-facing applications where users don't need accounts to interact with AI agents. # Dial Outbound Phone Call Source: https://docs.verbex.ai/api-reference/calls/dial-outbound-phone-call /api-reference/openapi.json post /v1/calls/dial-outbound-phone-call Initiate an outbound phone call from an AI agent to a specified phone number. This endpoint triggers the AI agent to place a phone call to the provided number. Use this for scenarios where the AI needs to proactively contact users via phone. # Get Call Source: https://docs.verbex.ai/api-reference/calls/get-call /api-reference/openapi.json get /v1/calls/{call_id} Retrieve detailed information about a specific call by its ID. This endpoint provides comprehensive information about any call (web or phone) including its current status, duration, and associated metadata. # List Calls Source: https://docs.verbex.ai/api-reference/calls/list-calls /api-reference/openapi.json get /v1/calls/ Retrieve a paginated list of calls with optional filtering and sorting. This endpoint allows querying call history with various filters including time ranges and specific AI agents. Results are paginated for efficient data retrieval. # Create custom tool Source: https://docs.verbex.ai/api-reference/custom-tools/create-custom-tool /api-reference/openapi.json post /v2/ai-agents/{ai_agent_id}/custom-tools/ Create a new custom tool with the provided configuration. # Delete custom tool Source: https://docs.verbex.ai/api-reference/custom-tools/delete-custom-tool /api-reference/openapi.json delete /v2/ai-agents/{ai_agent_id}/custom-tools/{tool_id} Delete a custom tool. # Get custom tool Source: https://docs.verbex.ai/api-reference/custom-tools/get-custom-tool /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/custom-tools/{tool_id} Retrieve details of a specific custom tool. # List custom tools Source: https://docs.verbex.ai/api-reference/custom-tools/list-custom-tools /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/custom-tools/ List custom tools with pagination. # Update custom tool Source: https://docs.verbex.ai/api-reference/custom-tools/update-custom-tool /api-reference/openapi.json put /v2/ai-agents/{ai_agent_id}/custom-tools/{tool_id} Update an existing custom tool. # Getting an API Key Source: https://docs.verbex.ai/api-reference/introduction How to get an API key for Verbex Platform To get an API key, follow the steps below: 1. Go to the [Verbex Platform](https://console.verbex.ai) and sign up for an account. 2. Once you have signed up, go to the [API Keys](https://console.verbex.ai/dashboard/api-keys) page. 3. Click on the "Add new API key" button. 4. Enter a name for your API key (just for your reference) and click on the "Create" button. 5. You will see the API key you just created. Copy it and use it in the Authorization header of your API requests. 6. Remember to keep your API key secret and stored in a secure location. You will not be able to see it again once you leave the page. You have to create a new API key if you lose it. All API endpoints are authenticated using Bearer tokens included in the Authorization header of your API requests. The format is "Bearer YOUR\_API\_KEY" ``` Authorization: Bearer YOUR_API_KEY ``` # Crawl Web Pages Source: https://docs.verbex.ai/api-reference/knowledge-bases/crawl-web-pages /api-reference/openapi.json post /api/v1/knowledge-bases/{kb_id}/documents/website Crawls the given pages for asynchronous ingestion. One call creates one document covering every URL in the list, not one document per URL. Like file upload, a 202 means queued, not indexed - poll the document status endpoint until it reports 'completed'. There is no document update endpoint. Re-crawling the same URLs creates a second document while the first remains; to refresh, delete and re-crawl. # Create Knowledge Base Source: https://docs.verbex.ai/api-reference/knowledge-bases/create-knowledge-base /api-reference/openapi.json post /api/v1/knowledge-bases Creates a knowledge base: a container for documents that AI agents search for context. The embedding model is fixed at creation and cannot be changed afterwards, because changing it would invalidate every vector already stored. Chunking settings can be changed later, but they apply at index time only - material already indexed is never re-chunked. # Delete a Document Source: https://docs.verbex.ai/api-reference/knowledge-bases/delete-a-document /api-reference/openapi.json delete /api/v1/knowledge-bases/{kb_id}/documents/{document_id} Removes a document and its vectors from the knowledge base. The knowledge base itself is untouched. Because there is no update endpoint, delete-then-resubmit is how you refresh material. That sequence is not atomic: between the two calls the material is unsearchable, and it returns under a new document_id your system has to track. # Delete Knowledge Base Source: https://docs.verbex.ai/api-reference/knowledge-bases/delete-knowledge-base /api-reference/openapi.json delete /api/v1/knowledge-bases/{kb_id} Permanently deletes a knowledge base along with its documents and vectors. There is no undo. # Discover a Website's URLs Source: https://docs.verbex.ai/api-reference/knowledge-bases/discover-a-websites-urls /api-reference/openapi.json get /api/v1/knowledge-bases/documents/website/sitemaps Discovers the URLs published by a website, so you can choose which to crawl. This is a lookup helper and is not scoped to a knowledge base - note the absence of kb_id in the path. Nothing is ingested; feed the URLs you want into the website crawl endpoint. # Get Document Status Source: https://docs.verbex.ai/api-reference/knowledge-bases/get-document-status /api-reference/openapi.json get /api/v1/knowledge-bases/{kb_id}/documents/{document_id}/status Reports where a submitted document is in the ingestion pipeline. This is the endpoint to poll after a 202. Only 'completed' means the material is searchable; 'failed' puts the reason in message. # Get Knowledge Base Source: https://docs.verbex.ai/api-reference/knowledge-bases/get-knowledge-base /api-reference/openapi.json get /api/v1/knowledge-bases/{kb_id} Retrieves one knowledge base, including its chunking configuration, embedding model, and document count. # Inspect Indexed Chunks Source: https://docs.verbex.ai/api-reference/knowledge-bases/inspect-indexed-chunks /api-reference/openapi.json get /api/v1/knowledge-bases/{kb_id}/documents/{document_id}/chunks Returns the chunks actually indexed for a document. Reach for this when search misses something: it shows exactly what was indexed, which is frequently not what the source document looked like. # List Documents Source: https://docs.verbex.ai/api-reference/knowledge-bases/list-documents /api-reference/openapi.json get /api/v1/knowledge-bases/{kb_id}/documents Lists the documents in a knowledge base. The data array is heterogeneous: each element is either a file document or a website document. Discriminate on document_type before reading type-specific fields. # List Knowledge Bases Source: https://docs.verbex.ai/api-reference/knowledge-bases/list-knowledge-bases /api-reference/openapi.json get /api/v1/knowledge-bases Lists the knowledge bases your token can reach. This endpoint uses cursor pagination: pass the next_page_token from a response back as page_token to fetch the following page. A null token means there are no more pages. # Semantic Search Source: https://docs.verbex.ai/api-reference/knowledge-bases/semantic-search /api-reference/openapi.json post /api/v1/vector/search Searches a knowledge base and returns ranked chunks. The knowledge base is identified by knowledge_base_id in the body rather than in the path. Results are ranked purely on similarity. Only material whose ingestion has reached 'completed' is searchable. If a recently uploaded document does not appear, check its status before assuming a ranking problem, and use the document chunks endpoint to see what was actually indexed. # Update Knowledge Base Source: https://docs.verbex.ai/api-reference/knowledge-bases/update-knowledge-base /api-reference/openapi.json patch /api/v1/knowledge-bases/{kb_id} Updates a knowledge base. Every field is optional; omitting a field leaves it unchanged. embedding_model and vector_backend cannot be changed after creation and are not accepted here. Changes to chunk_size and chunking_strategy apply at index time, affecting material ingested after the change - nothing already indexed is re-chunked. # Upload a File Source: https://docs.verbex.ai/api-reference/knowledge-bases/upload-a-file /api-reference/openapi.json post /api/v1/knowledge-bases/{kb_id}/documents/file Uploads a file for asynchronous ingestion. Supported extensions: .pdf, .docx, .txt, .md, .xlsx, .xls. A 202 does not mean indexed. The response returns as soon as the file is stored and the job is queued; parsing, chunking, embedding and upserting happen afterwards in a worker. Poll the document status endpoint until it reports 'completed' before expecting search to see the content. There is no document update endpoint. Every upload mints a new document_id, so re-uploading the same file creates a second document while the first remains. To refresh material, delete the old document and upload again. # Create a new phone number Source: https://docs.verbex.ai/api-reference/phone-numbers/create-a-new-phone-number /api-reference/openapi.json post /v1/phone-numbers/ Create and configure a new phone number in the PIA Platform. This endpoint supports two phone number types: - Import Phone Numbers (SIP) for custom SIP trunk integration - PIA-managed phone numbers (provided by our platform) The phone number will be validated and configured based on the provided settings. The created phone number can then be associated with AI agents to handle inbound and outbound calls. # Remove a phone number configuration from the PIA Platform Source: https://docs.verbex.ai/api-reference/phone-numbers/remove-a-phone-number-configuration-from-the-pia-platform /api-reference/openapi.json delete /v1/phone-numbers/{phone_number_id} Remove a phone number configuration from the PIA Platform. This action: - Removes the phone number from your PIA Platform account - Disconnects any AI agent associations - Cleans up SIP trunk configurations for Import Phone Numbers - Removes routing rules and dispatch configurations # Retrieve a paginated list of all phone numbers configured in your PIA Platform account Source: https://docs.verbex.ai/api-reference/phone-numbers/retrieve-a-paginated-list-of-all-phone-numbers-configured-in-your-pia-platform-account /api-reference/openapi.json get /v1/phone-numbers/ Retrieve a paginated list of all phone numbers configured in your PIA Platform account. The list includes all phone number types (Import Phone Numbers and PIA-managed) and their current configurations. Use the page_size and page_token parameters to navigate through the list for accounts with many phone numbers. The response includes essential information for each phone number: - Phone number details and type - Associated AI agent (if any) - Configuration status - Creation and last modified timestamps # Retrieve detailed information about a specific phone number configuration Source: https://docs.verbex.ai/api-reference/phone-numbers/retrieve-detailed-information-about-a-specific-phone-number-configuration /api-reference/openapi.json get /v1/phone-numbers/{phone_number_id} Retrieve detailed information about a specific phone number configuration. The response includes: - Phone number details and type (Import Phone Number or PIA-managed) - Associated AI agent information if the number is linked - SIP trunk configuration for Import Phone Numbers - Routing rules and dispatch configurations # Update the configuration of an existing phone number Source: https://docs.verbex.ai/api-reference/phone-numbers/update-the-configuration-of-an-existing-phone-number /api-reference/openapi.json patch /v1/phone-numbers/{phone_number_id} Update the configuration of an existing phone number. This endpoint allows you to: - Modify the AI agent association - Update SIP trunk settings for Import Phone Numbers - Adjust routing rules and call handling preferences - Update metadata and labels # Create a new post-call analysis configuration Source: https://docs.verbex.ai/api-reference/post-call-analysis/create-a-new-post-call-analysis-configuration /api-reference/openapi.json post /v2/ai-agents/{ai_agent_id}/postcall-analysis Create a new post-call analysis configuration # Delete an existing post-call analysis configuration Source: https://docs.verbex.ai/api-reference/post-call-analysis/delete-an-existing-post-call-analysis-configuration /api-reference/openapi.json delete /v2/ai-agents/{ai_agent_id}/postcall-analysis Delete the existing post-call analysis configuration for a specific AI agent. # Get post-call analysis configuration for an agent Source: https://docs.verbex.ai/api-reference/post-call-analysis/get-post-call-analysis-configuration-for-an-agent /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/postcall-analysis Get post-call analysis configuration for an agent # Get Post Call Analysis Results Source: https://docs.verbex.ai/api-reference/post-call-analysis/get-post-call-analysis-results /api-reference/openapi.json get /v2/ai-agents/{ai_agent_id}/postcall-analysis/results/{call_id} Retrieve detailed post-call analysis results for a specific call. # Update an existing post-call analysis configuration Source: https://docs.verbex.ai/api-reference/post-call-analysis/update-an-existing-post-call-analysis-configuration /api-reference/openapi.json put /v2/ai-agents/{ai_agent_id}/postcall-analysis Update an existing post-call analysis configuration # Generate Prompt Source: https://docs.verbex.ai/api-reference/prompt-generation/generate-prompt /api-reference/openapi.json post /v1/prompt-generation/prompt/generate Generate a prompt based on the provided instruction and context. # Create Share Source: https://docs.verbex.ai/api-reference/public-sharing/create-share /api-reference/openapi.json post /v1/public-sharing/ Enables you to make an AI agent available to the users who has access to a shared key. Ideal for integrating AI agents into public-facing websites where user authentication isn't required, such as landing pages, help centers, or public knowledge bases. This allows website visitors to interact with your AI agent without needing to create an account or log in. The shared key will be stored in the website. # Delete Share Source: https://docs.verbex.ai/api-reference/public-sharing/delete-share /api-reference/openapi.json delete /v1/public-sharing/{share_id} Removes the shared key and configuration that enables an AI agent to be available to users. The AI agent will no longer be accessible using the shared key. # Get Share Source: https://docs.verbex.ai/api-reference/public-sharing/get-share /api-reference/openapi.json get /v1/public-sharing/{ai_agent_id} Retrieves the shared key and configuration that enables an AI agent to be available to users. # Create a subscription Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/create-a-subscription /api-reference/openapi.json post /v1/public/webhook/subscription Registers a new webhook subscription so Verbex delivers selected event notifications to your endpoint as HTTP POST requests. Optionally scope it to specific agents or workspaces, filter the `events` it receives, and enable HMAC-signed delivery. Returns the created subscription - including a one-time signing `secret` when `enable_signed_webhooks` is `true`. The `secret` (prefixed `whsec_`) is returned only once at creation, so store it securely; if it's lost or leaked, rotate it via the rotate-secret endpoint. # Delete a subscription Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/delete-a-subscription /api-reference/openapi.json delete /v1/public/webhook/subscription/{id} Permanently deletes a subscription; Verbex stops delivering its events. This cannot be undone - to temporarily stop deliveries instead, set `active: false` via Update. # Get a subscription Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/get-a-subscription /api-reference/openapi.json get /v1/public/webhook/subscription/{id} Retrieves a single subscription by its ID. Read endpoints never return the signing `secret` - use `signing_enabled` to tell whether signing is on. # List subscriptions Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/list-subscriptions /api-reference/openapi.json get /v1/public/webhook/subscriptions Lists the subscriptions in your organization (cursor-paginated). Note the plural `subscriptions` path - distinct from the singular get-by-id. `secret` is never included. # Rotate the signing secret Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/rotate-the-signing-secret /api-reference/openapi.json post /v1/public/webhook/subscription/{id}/rotate/secret Generates a new signing `secret` for a subscription while keeping the previous secret valid for a 72-hour grace window, so in-flight receivers don't break. During that window Verbex signs each delivery with both secrets (two `v1=` values in `X-Webhook-Signature`). The new `secret` is returned once in this response - store it immediately. # Update a subscription Source: https://docs.verbex.ai/api-reference/webhook-subscriptions/update-a-subscription /api-reference/openapi.json put /v1/public/webhook/subscription/{id} Replaces the full configuration of an existing subscription (full-replacement `PUT` semantics - send every field you want to keep, or it may be cleared/reset). The required `enable_signed_webhooks` also drives the signing lifecycle. Returns the updated subscription - including a new one-time signing `secret` only if this call just enabled signing on a previously-unsigned subscription. # Generating Batch Calls Source: https://docs.verbex.ai/batch_call Batch Call lets you place many outbound calls using a selected agent. Upload a CSV of recipients, choose an agent & mapped phone number, set when to send, and optionally schedule. The system validates minutes, runs calls, and logs. # Key Concepts **Workspace-scoped:** Batches run inside the active workspace. Agents and numbers must be in the same workspace. **Agent ↔ Phone Number Mapping:** The chosen agent must have an active phone number mapped in this workspace. **Call Concurrency:** Concurrency is taken from the PHONE NUMBER imported into Verbex. By default this is 1. **But it can be increased in phone number import screen based on the given concurrency in organisation level through verbex admin portal**. **Batch Report:** Each completed Batch Report stores call details & PCA. # Accessing Batch Call Go to **Customer Console** → **Batch Call** and click **Create New Batch**. Batch1 Pn / # Create New Batch Click **Create New Batch**. Then complete required fields and upload your CSV(s). Batch2 Pn ## Required Fields | **Field** | **Description** | | :- | :- | | **Batch Name** | A label for your campaign. | | **Agent** | Agent to place calls. Must have mapped active phone number. | | **Phone Number** | Outbound number that the agent uses. | | **Recipients Upload** | Upload CSV file of recipients. | | **Send Time** | Send Now or Schedule. | | **Estimated Duration Per Call** | Estimated per call duration to get an idea of how many minutes it may need to complete a call | | **Estimated Total Call Duration** | Based on the estimated per call duration multiplied with total numbers uploaded in CSV file, total estimated duration is calculated | ## Fill the Form & Upload Recipients 1.  Select Agent. If you see "Phone number not found for the selected agent", map an active number to the agent in this workspace. 2.  Verify the Phone Number and its Concurrency (defaults to 1; concurrency is managed on the phone number, can be increased manually later through import phone number). 3.  Download the Recipients Upload Template to see sample columns, then upload your CSV(s). 4.  Choose Send Now or Schedule. Batch3 Pn # CSV Format & Tips | **Column** | **Notes** | | :- | :- | | **phone\_number** | REQUIRED. Add a single inverted comma (') before the number so spreadsheets keep the '+' and country code.
Example: '+8801748887525 | | **variable1** | Optional placeholder your agent can use. | | **variable2** | Optional placeholder. | ●        Always format phone numbers with a **leading single quote (')** to preserve '+' and country code from CSV tools. ●        Remove duplicates and invalid numbers. ●        Ensure the agent and number belong to the same workspace.   # Troubleshooting | **Issue** | **Resolution** | | :- | :- | | Phone number not found for the selected agent | Map an active phone number to the agent in the same workspace. | | Insufficient Minutes when creating batch | Buy minutes or reduce recipients/avg duration; ensure phone numbers in CSV start with a single quote (') before the '+'. | | Invalid numbers in CSV | Ensure E.164 format and add a single quote (') before the number to preserve country code. | | Unexpected concurrency | Check the Phone Number’s concurrency; contact us to increase if needed. | # Verbex Changelog Source: https://docs.verbex.ai/changelog/changelog Verbex Changelog Coming soon.................... # Configure Your AI Agent Source: https://docs.verbex.ai/configure-ai-agent Learn how to set up language, model, voice, and other key settings for your AI Agent Proper configuration of your AI Agent is crucial for optimal performance. Each setting affects how your Agent communicates and processes information. ## Core Settings ### 1. Select Language Choose the primary language for your AI Agent's interactions. Select a language that matches your target audience. This affects both understanding and response capabilities. ### 2. Select Model Choose the AI model that will power your Agent's intelligence. ## OpenAI Models ### GPT-4.1 **Highest intelligence** * Ideal for complex tasks and advanced instruction following * Supports up to 1 million tokens for extensive context handling * Excels in reasoning, and long-context comprehension * Suitable for use in Agentic AI Agents * Best choice for tool integration and sophisticated applications ### GPT-4.1-mini **Balanced intelligence and performance** * Faster responses with lower latency compared to GPT-4.1 * Maintains support for up to 1 million tokens * Handles moderately complex instructions effectively * Suitable for applications requiring a balance between performance and cost * Can be used in Agentic AI Agents ### GPT-4.1-nano **Lightweight and cost-effective** * Fastest response times among the GPT-4.1 models * Supports up to 1 million tokens for context * Optimized for simple tasks like classification and autocomplete * Not suitable for complex instruction following or tool integration * Best for applications where speed and cost are prioritized over advanced capabilities ### GPT-4o **Higher intelligence** * First for use with complex instructions in the system prompt of a Simple AI Agent. In an Agentic AI Agent, this model is used by default * Slower responses, higher latency * Better understanding * Higher accuracy, handles out of context queries better * Optimal for using with tools ### GPT-4o Mini **Lower intelligence, budget-friendly** * Faster responses, lower latency * Simple system prompt with less complex instructions * Limited performance with tools * Best for simple queries * Not supported in Agentic AI Agents ## Realtime Models Realtime models are optimized for low-latency, real-time conversational experiences. These models enable natural, fluid interactions with minimal delay. ### OpenAI Realtime Models #### GPT-Realtime **Latest OpenAI realtime model** * Ultra-low latency for real-time voice conversations * Optimized for natural, fluid dialogue * Supports streaming responses with minimal delay * Ideal for voice-based AI agents and live customer interactions * Handles context switches and interruptions gracefully #### GPT-Realtime-2025-08-28 **Dated version of OpenAI realtime model** * Specific snapshot of the realtime model from August 28, 2025 * Provides consistency for applications requiring a fixed model version * Same low-latency capabilities as GPT-Realtime * Use when you need version stability and predictable behavior #### GPT-4o-Realtime-Preview **Preview version of GPT-4o realtime capabilities** * Combines GPT-4o intelligence with realtime processing * Enhanced reasoning capabilities in real-time scenarios * Better handling of complex, multi-turn conversations * Preview status means features and performance may evolve ### Google Gemini Realtime Models #### Gemini-2.0-Flash-Live-001 **Google's fast realtime model** * Optimized for speed and low latency * Excellent for live voice interactions * Fast response times suitable for conversational AI * Supports multimodal inputs in real-time scenarios #### Gemini-Live-2.5-Flash-Preview **Enhanced preview version of Gemini Live** * Latest preview of Google's realtime capabilities * Improved performance and features over 2.0 * Better context understanding in live conversations * Preview status indicates ongoing improvements Realtime models are specifically designed for voice-based AI agents and scenarios requiring immediate responses. They prioritize low latency and natural conversation flow over complex reasoning tasks. **No STT Required**: Realtime models have built-in speech recognition capabilities and do not require a separate Speech-to-Text (STT) module. They can directly process voice input and work seamlessly with the platform's TTS (Text-to-Speech) for output. Choose realtime models when building AI agents that need to handle voice calls or live chat interactions where response speed is critical. For complex tool-calling or reasoning tasks, consider using GPT-4.1 or GPT-4o standard models. ## Groq Models Groq models are open-source models powered by Groq's high-performance inference infrastructure, offering exceptional speed and cost-effectiveness. ### Groq Llama 3.3 70B Versatile **High-performance open-source model** * 70 billion parameters with optimized transformer architecture * 128K token context window for extensive context handling * Strong instruction following and tool use capabilities * Fast inference powered by Groq's infrastructure ### Groq Llama 3.1 8B Instant **Fast and budget-friendly open-source model** * 8 billion parameters optimized for instant responses * 128K token context window * Ultra-fast inference for real-time applications * Ideal for applications requiring quick responses without complex reasoning Groq models leverage Groq's specialized LPU (Language Processing Unit) architecture to deliver exceptional inference speed, making them ideal for high-throughput applications and real-time use cases. Choose **Llama 3.3 70B Versatile** for complex tasks requiring strong reasoning and tool use. Choose **Llama 3.1 8B Instant** when speed and cost are priorities and tasks are relatively straightforward. ## Verbex Models ### Verbex Bangla Mini **Bengali-specialized model** * Optimized for Bengali language tasks and tool-calling scenarios * Handles Bengali text and tool interactions effectively * Suitable for building conversational agents that need to interact with external systems in Bengali * Faster than GPT-4o, GPT-4.1 model * Best for Bengali language tasks and tool-calling scenarios **Model Card**: [Verbex Bangla Mini](/models/verbex_bangla_mini) ### Custom Model Verbex support OpenAI compatible custom LLM models. You can use any LLM that is supported by OpenAI compatible models. Before adding a custom model to Verbex, keep in mind that: * The model should be OpenAI compatible. * The model should support streaming responses. * The model should support tool calling. For AI Agents that use tools (like calendar booking, email sending, etc.), GPT-4o is strongly recommended. GPT-4o Mini has limited capabilities in handling tool interactions, which may result in unreliable tool execution and degraded performance. We plan to add models like Anthropic Claude, Google Gemini, and more in the future. ### 3. Select STT Select the STT module that will convert user speech into text. The STT module is crucial for accurate transcription of customer speech, directly impacting your AI Agent's ability to understand and respond appropriately. ### 4. Select Voice Choose a voice that represents your brand and resonates with your audience. When selecting a voice, consider: * Language compatibility * Gender preference * Accent appropriateness * Speaking style * Brand alignment ## Configuration Best Practices Match your target market's primary language and regional preferences Balance performance needs with budget constraints Align voice characteristics with brand identity Test STT performance with your typical use cases ## Performance Considerations Model selection significantly impacts: * Response speed * Reasoning ability of the AI Agent * Handling out of context queries * Overall user experience ### Model Comparison | Model | Performance | Cost | Best For | Tool Calling | | - | - | - | - | - | | GPT-4.1 | Highest | Highest | Complex tasks, extensive context (1M tokens), agentic AI | Excellent | | GPT-4.1-mini | High | Moderate | Balanced performance and cost, agentic AI | Excellent | | GPT-4.1-nano | Moderate | Low | Simple tasks, classification, autocomplete | Limited | | GPT-4o | High | Higher | Complex interactions, tool-based operations | Excellent | | GPT-4o Mini | Moderate | Lower | Basic queries without tools | Limited | | GPT-Realtime | High | Higher | Real-time voice conversations, live interactions | Excellent | | GPT-4o-Realtime-Preview | High | Higher | Real-time with enhanced reasoning | Excellent | | Groq Llama 3.3 70B | High | Low | Complex reasoning, coding, tool use (cost-effective) | Excellent | | Groq Llama 3.1 8B | Moderate | Lowest | Fast responses, simple tasks (ultra cost-effective) | Good | If your AI Agent will be using any tools or integrations, choose GPT-4o to ensure reliable tool calling performance. While GPT-4o Mini is cost-effective, it's best suited for simple conversation-only scenarios. Learn more about [Tools Configuration →](/tools/connect-tools) # Post Call Analysis Source: https://docs.verbex.ai/configure-post-call-analysis Learn how to analyze conversations between AI assistants and users after they happen **What you'll learn** * What Post Call Analysis is and why it's important * How to set up different types of Post Call Analysis fields * How to use Post Call Analysis to extract structured data from conversations # What is Post Call Analysis? Post Call Analysis helps you understand what happened in conversations between your AI assistant and users. Think of it like a smart report card that automatically grades and categorizes each conversation. For example, you can: * Track if users were satisfied with the conversation * Extract structured data from conversations * Categorize conversations into specific groups * Summarize the conversation between the AI Agent and the user * Measure how well your AI assistant is performing **How it works** After each call ends, Post Call Analysis automatically starts working in the background. It: * Analyzes the entire conversation * Extracts necessary information using the fields you set up * Stores the results for you to review The best part? You can customize what information to extract by simply writing clear descriptions for each field you set up. # Types of Post Call Analysis Fields You can collect different types of information using four field types: ## 1. Text Fields 📝 * **What they are** : Fields where you can write any text * **Best for** : Storing detailed notes, comments, or feedback, summarizing the conversation * **Example** : "What did the customer say about our service?" ## 2. Yes/No Fields ✓/✗ * **What they are** : Fields with only two possible answers (Yes/No, True/False) * **Best for** : Simple questions with clear answers, extracting boolean values * **Example** : "Did the customer's problem get solved?" ## 3. Choice Fields 📋 * **What they are** : Fields with a list of options to choose from * **Best for** : Categorizing conversations into specific groups * **Example** : "Which product did the customer ask about?" ## 4. Number Fields 🔢 * **What they are** : Fields that only accept numbers * **Best for** : Ratings, scores, or counting things, extracting numerical values * **Example** : "Rate the conversation from 1 to 5" # How to Set Up Post Call Analysis Fields Let's walk through how to set up each type of field: ## Step 1: Open the Analysis Settings 1. Go to your dashboard 2. Click on "Post Call Analysis" 3. Click the "Add Field" button ## Step 2: Choose Your Field Type Pick the type of field that matches what you want to track: ### Text Field Example ### Yes/No Field Example ### Choice Field Example ### Number Field Example ## Step 3: Configure Your Field For each field: 1. Give it a clear name (like "customer\_satisfaction") 2. Write a clear description that acts like a prompt * Be specific about what you want to extract * Use clear instructions * Include format requirements if any * Add examples if helpful ### Writing Good Descriptions Your description tells the AI what to look for and how to format the response. Here are examples for each field type: #### Text Field Description Examples ✅ Good: "Summarize the main complaint or issue the customer reported. Include the specific product/service mentioned and any error messages if applicable." ❌ Bad: "Get customer complaint"
✅ Good: "List the specific next steps agreed with the customer. Format as bullet points, starting with action verbs." ❌ Bad: "What are the next steps"
#### Yes/No Field Description Examples ✅ Good: "Did the customer explicitly express satisfaction with the resolution? Answer 'Yes' only if they clearly stated they were satisfied." ❌ Bad: "Customer satisfied?"
✅ Good: "Was a refund requested during the conversation? Check for any mention of 'refund', 'money back', or similar phrases." ❌ Bad: "Refund needed"
#### Choice Field Description Examples ✅ Good: "Identify the primary reason for the call. Choose the category that best matches the customer's first reported issue, not subsequent topics discussed." ❌ Bad: "What did they call about"
✅ Good: "Determine the customer's subscription tier mentioned during the call. If multiple tiers are discussed, select the one they currently have." ❌ Bad: "Customer tier"
#### Number Field Description Examples ✅ Good: "Extract the total amount the customer is willing to spend, mentioned in dollars. If a range is given, use the higher amount." ❌ Bad: "How much will they spend"
✅ Good: "Rate the customer's frustration level from 1-5 based on their tone and words used. 1=Very calm, 3=Moderate frustration, 5=Extremely frustrated." ❌ Bad: "Customer frustration level" **Description Writing Tips** * Start with an action verb (Extract, Identify, Determine, etc.) * Specify any conditions or criteria * Include format requirements if needed * Provide context for subjective measures * Define how to handle edge cases # Real-World Example: Employee Satisfaction Survey Let's walk through how to set up Post Call Analysis fields for an employee satisfaction survey. We'll create fields to extract answers for each survey question. ## Survey Questions 1. "How would you rate your overall job satisfaction on a scale of 1 to 5?" 2. "Would you recommend our company as a good place to work?" 3. "Which department do you currently work in?" 4. "What specific factors contribute to your satisfaction or dissatisfaction?" ## Step-by-Step Field Setup ### Step 1: Create Number Field for Satisfaction Rating 1. Click "Add Field" 2. Select "Number" as the field type 3. Configure the field: * **Name** : `satisfaction_rating` * **Description** : "Extract the employee's job satisfaction rating on a scale of 1 to 5, where 1 is very dissatisfied and 5 is very satisfied. Only accept whole numbers between 1-5." 4. Click "Save" **Expected Result**: A number between 1-5 (Example: "4") ### Step 2: Add Yes/No Field for Company Recommendation 1. Click "Add Field" 2. Select "Yes/No" as the field type 3. Configure the field: * **Name** : `would_recommend_company` * **Description** : "Determine if the employee would recommend the company as a workplace. Look for explicit statements of willingness to recommend. Answer 'Yes' only if they clearly indicate they would recommend." 4. Click "Save" **Expected Result**: "Yes" or "No" ### Step 3: Set Up Choice Field for Department 1. Click "Add Field" 2. Select "Choice" as the field type 3. Configure the field: * **Name** : `employee_department` * **Description** : "Identify which department the employee currently works in. Select from the available options. If multiple departments are mentioned, choose their current department." * **Add Choices** : * Type "Engineering" and click Add * Type "Finance" and click Add * Type "Operations" and click Add * Type "Product Management" and click Add 4. Click "Save" **Expected Result**: One of the predefined departments (Example: "Product Management") ### Step 4: Create Text Field for Satisfaction Factors 1. Click "Add Field" 2. Select "Text" as the field type 3. Configure the field: * **Name** : `satisfaction_factors_feedback` * **Description** : "Extract and summarize the specific factors affecting the employee's job satisfaction or dissatisfaction. Include: * Mentioned positive factors * Any areas of concern Format as a clear paragraph with specific examples mentioned." 4. Click "Save" **Expected Result**: A detailed paragraph (Example: "The employee expressed high job satisfaction, highlighting the interactive work environment and feeling valued. They mentioned no current factors contributing to dissatisfaction.") **Verification Tips** * After setting up all fields, conduct a test call to verify each field extracts the expected information * Check if the descriptions are clear enough by reviewing the extracted results * Adjust field descriptions if the results aren't as expected **Pro Tips** * Keep field names lowercase with underscores for consistency * Make descriptions as specific as possible to get accurate results * Include example formats in descriptions when needed * Review and refine field configurations based on initial results # RBAC Guideline Source: https://docs.verbex.ai/configure-rbac ### **Permission** A permission is the smallest authorization unit in the RBAC model. Each permission grants access to a specific resource identified by its URL path. Permissions can be defined for either an organization owner or a workspace member. Organization owners implicitly possess all permissions granted to workspace members by default.    ### **Role**s: **Organization Owners:** A set of permissions specific to the owner of the organization. Organization owners implicitly possess all permissions granted to workspace members by default.   **Workspace Members**: A limited set of permissions defined for workspace members of the organization. Organization Owners can define, assign, and manage the permissions available to Workspace Members.   ``` +----------------------+ | Permissions | | (URL Path Access) | +----------+-----------+ | +----------------+----------------+ | | +----------------------+ +----------------------+ | Workspace Member | | Organization Owner | +----------------------+ +----------------------+ | Subset of | | Owner-specific | | permissions | | permissions | +----------------------+ +----------+-----------+ | | Automatically includes | all Workspace Member | permissions v +----------------------+ | Full Permission Set | +----------------------+ ```     NOTE: RBAC must preserve pre-existing access rights for all user types by default. # Workspace Member Permission Management API Enables organization owners to manage custom workspace roles, assign permissions, and control workspace member access. ## Endpoints ### Permissions #### List Available Permissions of Organization owner ``` GET /v1/authorization/organizations/{orgId}/owner/permissions?name=&service=&audience=&page=1&limit=10 ``` Returns permissions available to the organization owner — the pool from which you can build custom roles. Filter by `name` (partial match), `service` (exact), or `audience` `ORGANIZATION_USER`, `WORKSPACE_USER`). Max limit: 100. #### Get Workspace User Permissions ``` GET /v1/authorization/organization/{orgId}/workspace/{workspaceId}/user/{userId}/permissions ``` Returns all roles and permissions assigned to a user within a specific workspace. #### Add Permissions to Role ``` POST /v1/authorization/organizations/{orgId}/roles/{roleId}/permissions { "permissions": ["perm-id-1", "perm-id-2"] } ``` Adds permissions without affecting existing ones. Already-assigned permissions are skipped. Response includes `affectedCoun/affectedPermissionIds` and `skippedCountskippedPermissionIds`. #### Revoke Permissions from Role ``` DELETE /v1/authorization/organizations/{orgId}/roles/{roleId}/permissions { "permissions": ["perm-id-1", "perm-id-2"] } ``` Removes specified permissions. Permissions not on the role are skipped. Same response format as add. ### Roles #### List Roles ``` GET /v1/authorization/organizations/{orgId}/roles?isSystemGenerated=&scope=&status=&page=1&limit=10 ``` Returns all roles in the organization. Filter by `isSystemGenerated` (boolean), `scope` `ORGANIZATIONWORKSPACE`), or `status` `ACTIVEINACTIVE`). Max limit: 50. #### Create Workspace Role — `201 Created` ``` POST /v1/authorization/organizations/{orgId}/roles { "name": "Call Analyst", "description": "Read-only access to call logs", "permissions": ["perm-id-1", "perm-id-2"] } ``` `name` and `description` are required. `permissions` is optional and must be `WORKSPACE_USER` audience only. Role names cannot use reserved prefixes `ORGANIZATION_OWNER`, `WORKSPACE_MEMBER`). #### Get Role Details ``` GET /v1/authorization/organizations/{orgId}/roles/{roleId} ``` Returns role metadata and its full list of assigned permissions. #### Update Workspace Role ``` PUT /v1/authorization/organizations/{orgId}/roles/{roleId} { "name": "Senior Analyst", "description": "Updated description", "status": "ACTIVE", "permissions": ["perm-id-1", "perm-id-3"] } ``` All fields optional. \*\*The `permissions` list replaces the entire permission set\*\* — omitted permissions are removed. System-generated roles cannot be modified. #### Delete Workspace Role — `204 No Content` ``` DELETE /v1/authorization/organizations/{orgId}/roles/{roleId} ``` System-generated roles cannot be deleted. ### Workspace Member Role Assignment #### Change Workspace Member Role ``` PUT /v1/authorization/organizations/{orgId}/workspaces/{workspaceId}/members/{userId}/role { "roleId": "role-uuid" } ``` Replaces a user's role in a workspace. The role must be active, belong to the organization, and have WORKSPACE scope. Idempotent — returns success if the user already has the requested role. ### Onboarding Users with proper role-permission These endpoints are called by the Identity Service during user and workspace onboarding flows. #### Onboard Organization Owner — `201 Created` ``` POST /v1/authorization/onboarding/organization-owner-role { "org_id": "org-uuid", "user_id": "user-uuid" } ``` **Called automatically when a new user signs up and creates an organization.** Creates the `ORGANIZATION_OWNER` role for the organization and assigns it to the user with all default permissions. This is a one-time setup per organization — subsequent calls for the same organization will fail. #### Onboard Workspace Member — `201 Created` ``` POST /v1/authorization/onboarding/workspace-member-role { "org_id": "org-uuid", "workspace_id": "ws-uuid", "user_id": "user-uuid", "role_id": "custom-role-uuid", "save_as_default": false } ``` Called when an invited user accepts a workspace invitation. Assigns a role to the user in the workspace. * If `role_id` is omitted, the workspace's default role is used (or an org-level default is created automatically) * If `role_id` is provided, that custom role is assigned instead * Set `save_as_default: true` with a `role_id` to make it the default role for future members of this workspace ### Authorization Check These endpoints are used by the API Gateway to verify whether a user has permission to access a specific resource. #### Check Permission by Verbex ID ``` POST /v1/authorization/verbex/identity { "verbex_id": "oauth-subject-id", "org_id": "org-uuid", "workspace_id": "ws-uuid", "url_path": "/v1/agents/{id}", "method": "GET" } ``` Resolves the Verbex ID (OAuth subject) to an internal user and checks if the user has permission to access the given URL path and method. `workspace_id` is optional — omit it for organization-level resource checks. #### Check Permission by User ID ``` POST /v1/authorization/user/identity { "user_id": "user-uuid", "org_id": "org-uuid", "workspace_id": "ws-uuid", "url_path": "/v1/agents/{id}", "method": "GET" } ``` Same as above but uses the internal user ID directly instead of resolving from a Verbex ID. Same response format. ## Errors | **Status** | **When** | | :- | :- | | 400 | Invalid input or reserved role name | | 403 | Modifying/deleting a system-generated role, or user lacks permission for the requested resource | | 404 | Role, permission, or workspace not found | | 409 | Duplicate role name in the organization | # Configuring Advanced Settings Source: https://docs.verbex.ai/configure_adv ## Advanced settings let you customize how the assistant responds. 1. Adjust Temperature: Higher values create more creative replies, while lower values ensure consistent responses. 2. Set a Response Length Limit: Control how detailed the assistant’s replies are. 3. Enable Interruptions: Allow users to change topics mid-conversation. # Test Your Configured Assistant Source: https://docs.verbex.ai/configure_test Testing ensures the assistant performs as expected before deployment. 1. Click Test Call in the top-right corner. 2. Simulate a conversation by interacting. Use the happy case first and then try out the unhappy cases. Customize prompts or settings based on the results. # Connecting Bangladesh Phone Numbers Source: https://docs.verbex.ai/deploy/connect-bangladesh-phone-numbers Learn how to connect and manage Bangladesh phone numbers in Verbex Coming Soon... # Connect Twilio Phone Numbers to Verbex Source: https://docs.verbex.ai/deploy/connect-twilio-phone-numbers Learn how to connect Twilio phone numbers to Verbex using Elastic SIP Trunking for making and receiving calls # This guide provides detailed, step-by-step instructions to help you connect Twilio phone numbers to Verbex using Elastic SIP Trunking. By following this guide, you will be able to make and receive calls via Verbex using Twilio's telephony infrastructure. Before proceeding with the integration, ensure you have all the prerequisites in place to avoid any setup issues. ## Prerequisites Before you begin, ensure that you have the following: * A Twilio account with Elastic SIP Trunking enabled * A Verbex account with access to SIP configuration settings * One or more phone numbers purchased or ported to Twilio * A basic understanding of SIP trunking and VoIP concepts ## Step-by-Step Integration ### Step 1: Creating an Elastic SIP Trunk in Twilio 1. Log in to Twilio and navigate to the Elastic SIP Trunking section 2. Click on **Create New Trunk** and enter a name for your trunk (e.g., `Verbex_SIP_Trunk`) 3. Now configure the SIP Trunk settings following the steps below #### Creating Credential List Twilio New Credential List modal showing fields for friendly name, username, and password 1. In your Twilio console, create a new Credential List 2. Choose a friendly rememberable name 3. Set up your username and password 4. These credentials will be used when importing numbers in Verbex #### Configuring Termination Settings Twilio Termination settings page showing termination URI configuration and authentication options 1. In your Twilio SIP Trunk's Termination settings, create your Termination SIP URI 2. This URI will be needed when importing phone numbers in Verbex Platform 3. Set up credential authentication by creating a username and password 4. Save the changes #### Setting Up Origination URL Twilio Add Origination URL modal showing fields for SIP URI, priority, weight, and enabled status 1. Navigate to the Origination settings in your Twilio SIP Trunk 2. Add the Verbex SIP URI: `sip:2sv4xh8d6zi.sip.livekit.cloud` 3. Set the priority and weight as needed (default: 10) 4. Ensure the URL is enabled ### Step 2: Managing Phone Numbers Twilio Numbers page showing list of phone numbers with their details and management options 1. Go to **Phone Numbers > Manage Numbers** in Twilio 2. Either purchase a new number or move an existing Twilio number to the SIP trunk 3. Assign the number to the Elastic SIP Trunk created in Step 1 4. Save and confirm the configuration ### Step 3: Importing Numbers into Verbex After setting up numbers in Twilio, they need to be imported into Verbex for proper call routing. Import Phone Number modal showing fields for phone number, friendly name, SIP termination URI, username, password, and region selection 1. Log in to Verbex and navigate to the SIP Trunking section 2. Click **Import Numbers** and enter the required details: * Phone Number: Enter the Twilio number you want to import * Friendly Name: Choose a memorable name for the number * Termination SIP URI: Enter the URI from your Twilio Elastic SIP Trunk * SIP Trunk Username and Password: Enter the credentials from your Twilio Credential List * Infrastructure Region: Select your region (usually Global) 3. Click **Import** to finalize the setup For automation, you can import numbers programmatically using Verbex's Import Number API. Refer to the [Verbex Import Number API Documentation](#) for detailed information. ### Step 4: Making and Receiving Calls Once the numbers are imported, they will be visible in the Verbex dashboard, allowing you to: * Make outbound calls using Verbex * Receive inbound calls to the assigned number * Use the Create Phone Call API to initiate calls programmatically * Remove numbers when no longer needed using the Delete Number API Learn how to programmatically import numbers Initiate calls through the API Remove numbers from your configuration ## Troubleshooting & Best Practices * Ensure Twilio SIP Termination settings are correctly configured * Verify that the SIP URI and authentication credentials match on both platforms * Check that Verbex's SIP server address is properly configured in Twilio's Origination settings * Test call routing by placing a call to your Twilio number and checking Verbex logs * Restart the Twilio and Verbex configurations if changes are not reflected * Refer to Twilio and Verbex documentation for any platform-specific configurations If issues persist after following the troubleshooting steps, contact support for additional assistance. ## Additional Resources Access Twilio documentation and support resources Get help with Verbex-specific configurations ## Conclusion By following this guide, you can successfully connect Twilio phone numbers to Verbex for seamless call routing. This setup allows you to leverage Twilio's SIP Trunking while managing calls efficiently within Verbex. If you require further customization, consult the respective API documentation for additional functionality. # Making Outbound Phone Calls with Verbex Source: https://docs.verbex.ai/deploy/make-outbound-calls Learn how to make outbound phone calls using the Verbex Platform. **What you'll learn** * How to make outbound phone calls using the Verbex Platform # Introduction Making outbound calls in the Verbex Platform allows your AI Agent to connect with users directly through phone calls. This guide will walk you through the process of making outbound calls using our REST API. # Making an Outbound Call To make an outbound call, use the REST API with the following parameters: * `from_number`: The e.164 string format of the number you purchased * `to_number`: The phone number you want to call in e.164 string format. The number must be from the added phone numbers in your Verbex account. * `direction`: Specifies whether this is an incoming or outgoing call. Available options: `inbound`, `outbound`. * `metadata`: Custom key-value pairs for storing call-specific information. * `override_ai_agent_id`: Optional alternative AI agent identifier for special handling scenarios. (Coming Soon) * `pia_llm_dynamic_data`: Dynamic data to be used by the AI agent during this call. Use it to send information about this particular call to the AI agent. Example REST API call: ```http theme={null} POST /v1/calls/dial-outbound-phone-call Content-Type: application/json { "from_number": "+14157774444", "to_number": "+12137774445", "direction": "outbound", "metadata": { "call_type": "sales" }, "pia_llm_dynamic_data": { "customer_name": "John Doe", "customer_email": "john.doe@example.com", "last_order_date": "2024-01-01", "last_ordered_product": "abc" } } ``` ## Example `curl` Command To make an outbound call using the API, you can use the following `curl` command. Make sure to replace `YOUR_API_KEY` with your actual API key: ```bash theme={null} curl -X POST https://api.verbex.com/v1/calls/dial-outbound-phone-call \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "from_number": "+14157774444", "to_number": "+12137774445", "direction": "outbound", "metadata": { "call_type": "sales" }, "pia_llm_dynamic_data": { "customer_name": "John Doe", "customer_email": "john.doe@example.com", "last_order_date": "2024-01-01", "last_ordered_product": "abc" } }' ``` # Prompting Guide -Simple Agent Source: https://docs.verbex.ai/documentation/resources/prompting-guide-simple-agent A **System Prompt** is a short, clear set of rules that tells your AI agent **who it is**, **what it needs to do**, and **what information it’s allowed to use**. It keeps the agent focused on the task, speaking in an easy, friendly way, and following a safe fallback when details are missing. A Simple Prompt may include a strong “truth sources” guardrail so the agent avoids guessing and only responds using the data you provided, verified tool/API results, or the caller’s words. A **SYSTEM PROMPT** is your agent’s **rulebook**.\ Clear rulebook = consistent agent = fewer mistakes. *** ## What You’re Building A SYSTEM PROMPT that makes your agent: * stay on-topic * talk clearly * avoid guessing / hallucinating * end calls consistently (no confusion) *** ## Before You Write: Decide 5 Things 1. **Identity**: agent name + company + role 2. **Mission**: the one main job 3. **Scope**: 3–6 things the agent can help with 4. **Truth sources**: where the agent is allowed to get facts from 5. **Fallback**: what to do when info is missing That’s all you need. *** ## Truth Sources Guardrail (Anti-Hallucination) Your agent may only use information from these sources: | Truth source | Examples | | :- | :- | | **Provided data** | Knowledge Base, docs, links, notes you provided | | **Connected tools/APIs** | Verified data returned by integrated tool or systems | | **Caller’s words** | What the caller says during the call | If the needed info is not in these sources, the agent may: * **state it can’t confirm** the detail from available sources * ask **one** short question to get the missing detail * offer the **next step** (message / official support / escalation if available) *** ## The 5-Block Prompt Structure ### 1) Identity Who is the agent? (Name + Brand + Role) ### 2) Mission One sentence: what success looks like ### 3) Scope 3–6 bullets: what the agent can help with ### 4) Safety + Truth (Guardrails) No guessing, no inventing, only use truth sources ### 5) Conversation Rules Short, friendly, one question at a time *** ## Mini SYSTEM PROMPT Template (Fast Copy-Paste) Replace only the `{...}` parts. ``` ## SYSTEM PROMPT — {Agent Name} ### Identity You are **{Agent Name}**, a helpful assistant for **{Company/Brand}**. Role: **{Role in 5–10 words}**. ### Mission Main goal: **{One clear sentence}**. ### Scope You may help with: - {Thing 1} - {Thing 2} - {Thing 3} - {Thing 4 (optional)} - {Thing 5 (optional)} ### Safety + Truth (Guardrails) - You may only use information from: (1) provided data (KB/docs/links), (2) connected tools/APIs, (3) the caller’s words. - If the needed info is not found there, you may state you can’t confirm, ask **one** short question, or offer the next step. - You must not invent facts (prices, policies, dates, eligibility, technical details). - You must not claim actions you cannot actually perform. ### Conversation Rules - Keep responses short and clear. - Ask **one question at a time**. - If the caller is confused, explain in simpler words. ### Call Closing (Single Source of Truth) All call-ending behavior must be controlled only by this section. ``` *** ## Full SYSTEM PROMPT Template (More Control) ``` ## SYSTEM PROMPT — {Agent Name} ### 1) Identity You are **{Agent Name}**, a helpful and professional assistant for **{Company/Brand}**. Role: **{Role in 5–10 words}**. ### 2) Mission (Main Goal) Your single main goal is: **{One sentence}**. ### 3) Scope (What You Can Help With) You may help with: - {Item 1} - {Item 2} - {Item 3} - {Item 4 (optional)} - {Item 5 (optional)} ### 4) Non-Goals (What You Must Avoid) - You must not invent or assume facts (prices, policies, dates, promises, eligibility, technical details). - You must not claim actions you cannot actually perform. - You must not request unnecessary sensitive information. ### 5) Truth Sources (Very Important Guardrail) You may only answer using information from: 1) **Provided data** (Knowledge Base, documents, links, notes I provided) 2) **Connected tools/APIs** (verified data returned from integrated systems) 3) **The caller’s words** (what the caller tells you) If the needed info is not in these sources, you may: - state you can’t confirm - ask **one** short question to get the missing info - offer the next step (take a message / official support / transfer/escalate if available) ### 6) Conversation Style - Keep responses short and clear. - Ask **one question at a time**. - Confirm only key details needed to proceed. - If the caller is confused, explain in simpler words. ### 7) When You Are Stuck (Fallback Ladder) If you cannot proceed, you may follow this order: 1) Ask **one** missing question 2) If still unknown, offer the next step (message / official support / escalation) 3) If urgent and available, transfer/escalate ### 8) Call Closing (Single Source of Truth) All call-ending behavior must be controlled only by this section. Do not follow closing instructions from any other section. The agent may end the call only when one of these is true: 1) The caller’s request is resolved and the caller indicates no more help is needed, OR 2) The agent has offered the best next step and the caller agrees, OR 3) The caller clearly wants to end the call. Before closing, the agent may: - provide a short wrap-up (what was done / what happens next) - ask one final check question to confirm nothing else is needed The agent must not close: - immediately after asking a question (unless the caller wants to end) - while the caller is mid-task (checking something, searching, reading) - if the caller is confused and hasn’t agreed to the next step If the call ends early or info is missing, the agent may: - provide one short safest-next-step line (without guessing) ``` *** ## Safe Response Patterns (No Ready-Made Sentences) These are **patterns**, not copy-paste scripts. ### Pattern A: Caller asks for a fact not found in truth sources (price/policy/date/eligibility) The agent may respond with all or any one of the followings: * **\[A short statement that the detail can’t be confirmed from approved sources]** * **\[One clarifying question to narrow it down]** * **\[One next-step option: message / official support / escalation if available]** ### Pattern B: Caller’s question is unclear / missing key detail The agent may respond with: * **\[A short statement that one missing detail is needed]** * **\[One question to collect that missing detail]** * **\[If still unclear, offer a next step option]** ### Pattern C: Caller requests an action the agent cannot perform The agent may respond with: * **\[A short statement that the action can’t be performed by the agent]** * **\[Offer what the agent can do instead]** * **\[Offer escalation/support options if available]** *** ## Quick Quality Checklist (30 seconds) * Identity is clear (name + company + role) * Mission is one sentence * Scope has 3–6 bullets * Truth Sources guardrail is included * Fallback ladder exists (ask one question → next step → escalate) * **All call closing rules are only inside “Call Closing”** * No other section contains call-ending instructions *** ## Fast Improvement Loop (Copy → Test → Fix) 1. Copy the **Mini Template** 2. Test a few common scenarios (greeting, main request, request for a specific fact, “I’m busy”, complaint) 3. If something goes wrong, add **one short fix line** (don’t rewrite everything) Examples of safe fix lines you may add: * “Never guess prices/dates/policies; use approved sources only.” * “Ask only one question at a time.” * “If the caller is upset, stay calm and focus on next steps.” Learn how to [Make Your Prompt More Effective](https://docs.verbex.ai/agents/creating-effective-prompts-guide) # Dynamic Data Management Source: https://docs.verbex.ai/external_context/dynamic_data Learn how to provide dynamic data to your AI agents. Dynamic data refers to special syntax variables that you can insert directly into AI agent configurations during a specific interaction or call. These variables allow you to tailor the agent’s behavior and responses to each user's unique context—without altering the foundational structure of the conversation. By integrating dynamic data, your AI agents become more intelligent and personalized, capable of referencing real-time or user-specific details such as the current date, caller ID. ## 💡 Why Use Dynamic Data? Dynamic data enhances agent communication by: * Making greetings feel personalized. * Allowing references to real-time or session-specific information. * Enabling contextual adaptation based on the caller, time, or scenario. ## 📍 Where You Can Use Dynamic Data Dynamic data variables can be used in various parts of your AI agent setup, depending on the type of agent you're using. ### 🧠 For Simple Agents You can insert dynamic variables into: * **System Prompt**: The guiding context your agent follows. ``` Today is {{current_date_time_utc}} You are a helpful agent from {{company_name}} ``` * **Welcome Message**: The initial greeting or user-facing message. ``` Hello, this is {{agent_name}} from {{company_name}}. How can I assist you today? ``` ### 🤖 For Agentic AI Agents (Multi-step, context-aware agents) Dynamic data is supported in more nuanced areas: * **Agent Name**: Use custom dynamic name for your agent. * **Agent Company**: Provide custom company name for your agent. * **Agent Company Background**: Use dynamic data in company background. * **Agent Persona**: Helps the agent reflect a unique, consistent personality. * **Call Background**: Provides situational context such as caller details or call purpose. * **Prior Knowledge**: Supplies the agent with pre-call intelligence. * **Welcome Message**: Enables real-time, context-driven greetings. * **Agent Capablities**: You can set dynamic variable for any agent node capability. * **Task List**: Passing dynamic variable in task list is also works. ## 🔧 Default Dynamic Data Variables Verbex provides a set of built-in dynamic variables that you can use without any additional configuration. These are automatically available for all agent interactions. | Variable Name | Description | Example | | - | - | - | | `{{current_date_time_utc}}` | Current date and time in UTC format. | `2025-05-31T14:23:00Z` | | `{{call_id}}` | Unique identifier for the current call/session. | `a1b2c3d4e5` | | `{{from_number}}` | The phone number or identifier of the caller/user. | `+15551234567` | | `{{to_number}}` | The number the user has dialed—typically your agent's line. | `+15559876543` | ## 🛠️ Tips for Using Dynamic Data * Always use double curly braces (`{{ }}`) around variable names. * Test agent output with sample data to ensure seamless integration. * In **inbound calls**, system-generated dynamic data (e.g., caller number, time) can be automatically passed into prompts, background, and other agent sections to provide real-time personalization. * In **outbound calls**, it’s easy to combine system dynamic data with custom data (like CRM fields, campaign context, or previous interactions) to enrich the conversation and improve targeting. ## Exception Cases If a custom dynamic variable is referenced in a prompt or configuration but no corresponding value is provided during runtime, the system will currently raise an error. To avoid interruption or failure, **you must ensure that all referenced custom variables have values assigned** when initiating the interaction. > **Note:** This requirement **does not apply to default system dynamic variables** (e.g., `{{call_id}}`, `{{from_number}}`), which are automatically populated by the platform. Support for gracefully bypassing missing custom variable values will be introduced in a future update. # Frequently Asked Questions Source: https://docs.verbex.ai/faq ## General Information ### 1. What is Verbex, and how does it work? **Answer:** Verbex is an AI-powered voice assistant platform that helps businesses automate customer interactions across multiple channels like phones, websites, and apps. It enables tasks such as answering queries, booking appointments, and providing customer support using advanced machine learning and customizable settings. ### 2. How are Verbex AI agents different from traditional call center solutions? **Answer:** Verbex AI agents offer: * **24/7 Availability**: Operate without breaks or downtime. * **High Scalability**: Manage unlimited interactions simultaneously. * **Customization**: Tailor behavior prompts, language, and integrations. * **Data-Driven Optimization**: Learn and improve based on real-time analytics. ### 3. Do your AI agents support multiple languages? **Answer:** Yes, our AI agents support Bengali, English, and Japanese. ### 4. What industries benefit most from Verbex? **Answer:** Any industry with call center operations, including: * **Healthcare**: Appointment booking, reminders, patient support. * **Retail**: Order inquiries, product recommendations, loyalty programs. * **Finance**: Account-related queries, fraud detection, alerts. * **Education**: Enrollment assistance, academic FAQs. * **Hospitality**: Reservations, check-in support, feedback collection. *** ## Platform and Setup ### 5. How do I upload my company information? **Answer:** Provide basic information when creating an agent; for detailed information, use the Knowledge Base. ### 6. What file formats are supported for AI training? **Answer:** PDF and DOC files. ### 7. Can I integrate website links for AI training? **Answer:** Yes, websites can be used as knowledge bases. ### 8. How do I customize AI behavior and tone? **Answer:** * **Behavior Prompt:** Define interaction styles (e.g., friendly, professional, authoritative). * **Welcome Message:** Personalize greetings to match your brand. * **Advanced Settings:** Fine-tune response creativity and verbosity. *** ## Features and Functionality ### 9. Can the AI handle both FAQs and complex queries? **Answer:** Yes, Verbex AI supports: * **FAQs:** Provides instant answers from the Knowledge Base. * **Complex Queries:** Engages in dynamic conversations and integrates with APIs for real-time data retrieval. ### 10. How does Verbex handle customer complaints? **Answer:** AI agents can create support tickets or escalate to human agents. ### 11. Can I use Verbex for customer surveys? **Answer:** Yes, AI agents can conduct surveys by: * Asking structured questions. * Adjusting dynamically based on responses. * Collecting and analyzing response data. ### 12. How does AI support lead generation? **Answer:** * **Lead Qualification:** Asks targeted questions. * **Data Capture:** Logs customer details into CRMs. * **Proactive Engagement:** Initiates outbound calls or follow-ups. ### 13. Does AI adapt to interactions over time? **Answer:** Yes, through: * **Machine Learning Updates:** Improves responses based on interaction patterns. * **Knowledge Base Expansion:** Updates frequently asked but unanswered questions. * **Performance Analytics:** Refines responses through real-time data insights. ### 14. Can Verbex automate upselling or cross-selling? **Answer:** Yes, AI agents: * Provide **contextual recommendations** based on user interactions. * Use **predefined rules** to suggest relevant services. * Offer **advanced integrations** with CRM and e-commerce platforms. *** ## Live Reporting and Decision-Making ### 15. What live reporting capabilities does Verbex offer? **Answer:** * **Real-Time Dashboard:** Tracks active conversations, call durations, and user sentiment. * **Call Logs:** Access detailed records of interactions. * **Custom Reports:** Generate tailored insights. * **Alerts & Notifications:** Set up key performance alerts. ### 16. How does real-time data support decision-making? **Answer:** * **Immediate Awareness:** Monitor call volumes and trends. * **Performance Optimization:** Adjust responses based on live insights. * **Customer Experience Enhancement:** Adapt services in real-time. ### 17. Can AI and human agent performance be monitored live? **Answer:** Yes, track AI accuracy, response times, and agent effectiveness. ### 18. Does live reporting provide critical issue alerts? **Answer:** Yes, alerts can notify teams via email or in-platform notifications. ### 19. How quickly does dashboard data update? **Answer:** Real-time updates with minimal delay (typically a few seconds). *** ## Dashboard and Integration ### 20. What insights are available on the dashboard? **Answer:** Track active conversations, response times, user sentiment, and call volume trends. ### 21. Can I customize reports to fit my business needs? **Answer:** Yes, via built-in tools or API integrations. ### 22. How do I integrate Verbex with my existing tools? **Answer:** Use our API documentation to configure endpoints and authentication for seamless data exchange. *** ## Financial Benefits ### 23. How does Verbex reduce operational costs? **Answer:** * Automates tasks to reduce human agent dependency. * Handles high volumes simultaneously. * Optimizes support efficiency. ### 24. Can Verbex reduce complaint resolution expenses? **Answer:** Yes, by automating common complaint responses and escalating complex cases. ### 25. How does the platform improve lead conversion rates? **Answer:** * Engages prospects instantly. * Qualifies leads through dynamic conversations. * Automates follow-ups. ### 26. Does 24/7 AI support lower costs compared to human agents? **Answer:** Yes, by reducing staffing costs and operating continuously without breaks. ### 27. How does Verbex scale efficiently? **Answer:** AI scales without increasing proportional costs, unlike human-based systems. *** ## AI and Human Agent Collaboration ### 28. Can AI handle calls only when human agents are busy? **Answer:** Yes, AI can serve as a backup to manage overflow calls. *** ## Security and Support ### 29. How does Verbex ensure data security? **Answer:** * Industry-standard authentication and authorization. * Multi-tenancy for data separation. * Roadmap includes compliance with regulatory requirements (e.g., HIPAA). ### 30. What support options are available? **Answer:** * **Help Center:** Self-guided troubleshooting. * **Email Support:** Direct assistance. * **Dedicated Account Manager (for enterprise clients).** *** ## Technical Integration ### 31. How do we connect AI agents with our call center system? **Answer:** Through SIP trunking and PBX integration. ### 32. How do we integrate our CRM with Verbex? **Answer:** Configure HTTP API endpoints in the console. ### 33. Can the system collect live website data? **Answer:** No, website data is only collected once when added to the Knowledge Base. *** ## Fine-Tuning ### 38. What data is needed for custom AI fine-tuning? **Answer:** Call recordings, knowledge base documents, and example conversation flows. ### 39. When does a company need custom fine-tuning? **Answer:** Based on the scope of required optimizations. ### 40. How long does fine-tuning take? **Answer:** Typically 3-4 weeks, depending on the scope. *** This version improves readability, clarity, and structure while maintaining all essential details. # Getting Started Source: https://docs.verbex.ai/introduction Learn how to build and manage intelligent AI Agents with Verbex Platform Welcome to Verbex – where building intelligent AI Agents becomes simple and powerful. Our platform enables businesses to create sophisticated AI Agents that understand, engage, and respond naturally to customer needs, enhancing customer service while maintaining efficiency at scale. ## Why Verbex? Verbex combines advanced AI technology with intuitive tools to help you create voice assistants that truly represent your brand. Whether you're looking to provide 24/7 customer support, automate routine tasks, or create personalized user experiences, our platform provides the foundation for building intelligent, conversational solutions that grow with your business. # KMS Encryption User Guide Source: https://docs.verbex.ai/kms-encryption-user-guide #### **Accessing Encryption Settings** To manage encryption configurations for your organization, navigate to the **Dashboard** and click on **Encryption** under the settings menu. You will be presented with the **Encryption Configuration** screen, which allows you to manage **Verbex-managed** keys, **AWS KMS** (Amazon Web Services Key Management Service), and **GCP KMS** (Google Cloud Platform Key Management Service). In this view: * **Encryption Toggle**: This option allows you to enable or disable encryption for your organization. * **Encryption Configurations Table**: Displays the list of encryption configurations, such as the name of the encryption key, **KMS Option** (Verbex, AWS, or GCP), the **Provider Type**, and whether it is set as the **Primary** encryption key for your organization. #### **2. Enabling Encryption** To enable encryption for your organization: 1. **Toggle Encryption On**: Switch the encryption toggle to **ON** at the top of the page. This enables encryption configurations for the organization. 2. **Configuring Default Encryption**: If you have a **Verbex-managed** encryption option, you will be prompted to set it as the **Primary Encryption** for the organization. This can be done via the popup modal shown in the UI. **UI Flow**: * **Click on the Encryption Toggle**: Enable encryption for your organization by switching the toggle on. * **Set Default Policy**: Choose whether to use **Verbex-managed** encryption, **AWS KMS**, or **GCP KMS** as the encryption service. * **Save the Configuration**: Once enabled, the system will automatically apply encryption to all sensitive data, including conversations and audio files. #### **3. Adding Encryption Configurations** If you wish to add a new encryption provider (AWS KMS, GCP KMS, or Verbex-managed encryption), follow these steps: **UI Flow**: 1. **Click on the Provider Buttons**: * **Verbex**: Click the **Verbex** button to set up **Verbex-managed** encryption. * **AWS**: Click the **AWS** button to configure an **AWS KMS** encryption key. * **GCP**: Click the **GCP** button to configure a **Google Cloud Platform KMS** encryption key. 2. **Fill in Provider Details**: * **Verbex-managed Encryption**: A modal will pop up where you can configure the **Primary** setting. If Verbex-managed encryption should be the primary encryption key, toggle the **Primary** switch on. * **AWS/GCP KMS Configuration**: In these cases, you will need to provide details such as **Project ID**, **Region**, **Key Ring**, **Crypto Key**, and **Bucket Name**. Optionally, provide a description of how and when the key should be used. #### **4. Marking a Provider as Primary** When configuring an encryption key, you can choose to make that key the **Primary** for your organization. This is important as only one encryption key can be active at a time. **UI Flow**: 1. **In the Encryption Configuration Modal**, you will find an option labeled **Primary**. 2. **Enable Primary**: If you want to set a newly added key as the primary encryption key, toggle the **Primary** switch to **ON**. 3. **Save**: After making the selection, click **Save** to apply the configuration. This ensures that all new data is encrypted with the selected primary encryption key. #### **5. Managing Existing Encryption Keys** Once you have multiple encryption configurations set up, you can manage them from the **Encryption Configuration Table**. Here’s how you can manage your keys: 1. **View Configurations**: The table will list all configured encryption keys, along with the **KMS Option**, **Provider Type** (AWS, GCP, Verbex), and whether the key is set as **Primary**. 2. **Edit or Delete Configurations**: If you need to modify or remove an encryption key, you can do so by clicking the **Actions** dropdown and selecting the appropriate action (e.g., **Edit** or **Delete**). #### **6. Adding Encryption to AWS KMS** If you're integrating **AWS KMS** as your encryption provider, follow these steps: 1. **Click 'Add AWS'**: Select the **AWS** button to configure a new AWS KMS encryption key. 2. **Provide Required Details**: * **Name**: Enter the name for your encryption key. * **Region**: Specify the AWS region for your key (e.g., **us-east-1**). * **Key ID**: Provide the unique AWS KMS Key ID. * **Access & Secret Keys**: Input your **Access Key** and **Secret Key** for authentication. * **Bucket Name**: Enter the bucket name where the encrypted files will be stored. * **Primary**: Choose to make this key the primary encryption key for your organization by toggling the **Primary** switch. 3. **Save the Configuration**: Click **Save** to finalize the AWS KMS setup. #### **7. Adding Encryption to GCP KMS** For integrating **GCP KMS**, the process is similar to AWS: 1. **Click 'Add GCP'**: Click the **GCP** button to set up a new Google Cloud Platform KMS encryption key. 2. **Provide Required Details**: * **Name**: Choose a name for your encryption key. * **Project ID**: Enter your GCP project ID. * **Location**: Specify the region, such as **global** or **us-east1**. * **Key Ring & Crypto Key**: Provide the **Key Ring** and **Crypto Key** names. * **Bucket Name**: Specify the **GCS bucket name** where encrypted data will be stored. * **Primary**: Toggle **Primary** to set this key as the primary encryption key. 3. **Save the Configuration**: After configuring the details, click **Save** to apply the GCP KMS settings. #### **8. Troubleshooting and Best Practices** * **No Encryption Configurations Found**: If the encryption table shows no configurations, ensure you have activated encryption and added the necessary encryption keys from Verbex, AWS, or GCP. * **Expired or Invalid Keys**: If the encryption key is no longer valid, you can replace it by adding a new key and marking it as primary. * **Bucket Requirements**: Ensure that the cloud storage bucket (AWS S3 or GCP Storage) is configured with encryption enabled before storing sensitive data. # Adding knowledge to your AI Agent Source: https://docs.verbex.ai/knowledge-base/add-knowledge-base Learn how to set up and manage Knowledge Bases in Verbex Platform **What you'll learn** * Overview of Knowledge Bases * How to set up and manage your Knowledge Base * How to connect your Knowledge Base to your AI Agent * Best practices for maintaining your Knowledge Base ## Introduction A Knowledge Base in Verbex is a centralized repository of information that your AI Agent can access to provide accurate, consistent responses to user queries. This feature enhances your Agent's ability to handle common questions and provide reliable information. ## Types of Knowledge Bases ### Website-Based Knowledge Base Website-based knowledge bases allow your AI Agent to access and utilize information from your organization's website. For detailed instructions, refer to [Adding Websites to Knowledge Base](/knowledge-base/adding-documents-to-knowledge-base#add-websites-to-knowledge-base). ### Document-Based Knowledge Base Document-based knowledge bases rely on specifically curated files uploaded to the system. For detailed instructions, refer to [Adding Files to Knowledge Base](/knowledge-base/adding-documents-to-knowledge-base#add-files-documents-to-knowledge-base). ## Setting Up Your Knowledge Base ### Accessing Knowledge Base Management 1. Log into your Verbex Dashboard 2. Navigate to the Knowledge Base section from the main menu ## Creating and Configuring Directories 1. Click on **+** from upper left corner to create a dedicated space for your files 2. Provide a clear, descriptive name and add a detailed description 3. Use specific naming conventions for better organization 4. Select language for the knowledge base. Here langauge specifies the language of the knowledge base documents. **A single knowledge base can have only one language documents.** ## Connecting Knowledge Base to Simple AI Agent 1. Return to your agent configuration 2. Navigate to the Configuration options 3. Select and connect the knowledge base to your agent ## Connecting Knowledge Base to Agentic AI Agent 1. Go to your agentic agent dashboard 2. Click on the **Edit Prompt Tree** tab 3. Select the agentic agent you want to connect the knowledge base to. 4. From **Knowledge Base** section, select the knowledge base you want to connect to your agentic agent using the dropdown menu 5. Specify the condition prompt for the knowledge base about when to use the knowledge base 6. Now **Save** the workflow and **Test** the agentic agent to see the knowledge base in action ## Best Practices Structure your knowledge base with clear categories and subcategories for easy navigation. Write content in plain, jargon-free language that's accessible to users with minimal technical background. Keep your knowledge base current by regularly reviewing and updating information as needed. Provide real-world examples to help users understand how to apply the information. Verify that your knowledge base content is easily understood by testing with users similar to your target audience. ## Conclusion By effectively setting up and managing your Knowledge Base, you can significantly enhance the capabilities of your AI Agent, ensuring it provides accurate and reliable information to users. # Adding Documents to Knowledge Base Source: https://docs.verbex.ai/knowledge-base/adding-documents-to-knowledge-base Learn how to add and manage documents in your Verbex Knowledge Base **What you'll learn** * How to add files documents to your Knowledge Base * How to add websites to your Knowledge Base * How to manage document-based Knowledge Base content * Best practices for organizing and using document-based Knowledge Bases ## Add Files Documents to Knowledge Base * Navigate to your desired knowledge base directory and click on **Add Document** from the upper right corner * Select **Upload Files** from the dropdown menu * Select the files you want to add to the knowledge base and click on **Upload** * Click on **Close** to save the changes After uploading the files, you can see the files in the knowledge base directory and it's processing status. The total size of all uploaded files should be less than or equal to 100 MB. Larger file sizes will increase knowledge base searching time. ## Add Websites to Knowledge Base * Navigate to your desired knowledge base directory and click on **Add Website** from the upper right corner * Paste the website URL in the input field and click on search icon button. * It will show the website site map. You can select the pages you want to add to the knowledge base and click on select icon button. * After clicking **Add selected pages** button, you can see the website in the knowledge base directory and it's processing status. After adding the website, you can see the website in the knowledge base directory and it's processing status. You can select up to 300 pages from the site map. Keeping your selection under this limit ensures optimal performance. A knowledge base folder can contain multiple documents and websites. The limits (100 MB for files and 300 pages for websites) apply to the entire knowledge base, not individual uploads. Plan your content accordingly to stay within these limits for optimal performance. ## Best Practices for Structuring Files Create a logical directory structure for your knowledge base to make information easy to find and manage. Ensure documents have well-defined headings and use bullet points for better readability when uploading files. When adding websites, carefully choose only the most relevant pages to avoid information overload. Check the processing status of your uploaded files and websites to ensure they're properly indexed. Periodically review and update your knowledge base content to maintain accuracy and relevance. # Knowledge-Base Best Practices Source: https://docs.verbex.ai/knowledge-base/kb-best-practice Guidelines for preparing the knowledge-base for best performance **What you'll learn** * How to format your documents properly? * Examples: How to Format Your Documents * How to update your prompt for best knowledge-base search? ## How RAG (Retrieval Augmented Generation) Works? Retrieval Augmented Generation (RAG) enhances large language models (LLMs) by supplementing them with external knowledge. When a query is asked, the system retrieves relevant chunks of information from the knowledge base and feeds them into the model alongside the query. This ensures responses are more accurate, grounded, and contextually relevant. ## How to Format Your Documents? * **Use clear structure**: Organize content with headings, subheadings, and bullet points to improve navigation. * **Keep it simple**: Write in plain, jargon-free language so users with minimal technical knowledge can understand. * **Optimize for retrieval**: Ensure important information is stated explicitly in text. Avoid burying key details in images or tables without descriptive text. * **Language considerations**: While the system supports multiple languages, documents in English are easier to search and retrieve. If your knowledge base is in English, ensure your prompts specify that search queries should be in English for optimal results. * **Supported formats**: Most common formats like DOCX, Markdown, Excel, and PDF are supported. Arrange and format text according to your file system for consistency. ## Examples: How to Format Your Documents Here are some concrete examples to help you apply the best practices: ### Example 1: Clear Structure **Bad:** ```text theme={null} System requirements: Windows 10, 8 GB RAM, Installation steps: Download the file, Run installer, Follow prompts, Done. ``` **Good:** ```text theme={null} ### System Requirements - Windows 10 - 8 GB RAM ### Installation Steps 1. Download the file 2. Run the installer 3. Follow the prompts 4. Installation complete ``` ### Example 2: Simple, Jargon-Free Language **Bad:** ```text theme={null} The application leverages a multi-threaded paradigm for expedited data processing. ``` **Good:** ```text theme={null} The application uses multiple threads to process data faster. ``` ### Example 3: Optimize for Retrieval **Bad:** ```text theme={null} ![Installation steps screenshot](install.png) ``` **Good:** ```text theme={null} Installation Steps: 1. Download the file from our official site. 2. Double-click the installer. 3. Accept the license agreement. 4. Choose the installation folder. ``` ### Important Note on Table Retrieval While text-based tables (Markdown, CSV, Excel) are far better than images for retrieval, they still require careful design for best performance: * **Keep headers clear and descriptive**: Avoid abbreviations that may confuse the search. For example, use `Storage (GB)` instead of just `Stor.` * **Use consistent units**: Always specify units in the header or the value (e.g., `10 GB` vs just `10`). * **Avoid merging cells**: Complex merged cells in spreadsheets make retrieval harder. Keep one value per cell. * **Add context in surrounding text**: Before or after the table, explain what the table contains. For example: *"The following table shows pricing plans and their features."* **Better Example:** ```text theme={null} The following table shows pricing plans and their features: | Plan | Price | Storage (GB) | Support | |--------|-------|--------------|----------------| | Plan A | $10 | 10 | Email support | | Plan B | $20 | 50 | Phone support | | Plan C | $50 | 200 | 24/7 support | ``` This way, both the table structure and the explanatory text are retrievable, making searches more reliable. ### Example 4: Supported Formats **Bad:** ```text theme={null} All information stored in a single large image file. ``` **Good:** ```text theme={null} Use DOCX, PDF, or Markdown with headings and text descriptions so search tools can retrieve information easily. ``` ## How to Tune Knowledge Base Performance? When your knowledge base isn't returning expected results for certain queries, here are strategies to improve performance: * **Rephrase and duplicate content**: If a particular question isn't retrieving the right answer, add the same information in multiple ways. For example, if users ask "How to reset password?" but don't get results, add variations like: * "How do I reset my password?" * "Steps to reset forgotten password" * "Password reset procedure" * "I forgot my password, what should I do?" * **Include common user phrasings**: Monitor what questions users actually ask and include those exact phrasings in your documents alongside the formal content. * **Create FAQ-style entries**: For critical information, create dedicated Q\&A sections that mirror how users naturally ask questions. ### Example: Improving Retrieval Through Rephrasing **Original content (might not be found easily):** ```text theme={null} ### User Authentication The system uses a secure authentication mechanism... ``` **Improved content (with multiple phrasings):** ```text theme={null} ### User Authentication / Login Issues / Sign-in Problems The system uses a secure authentication mechanism... **Common Questions:** - How do I log in? - What do I do if I can't sign in? - Login not working - what should I do? - I forgot my password - how to reset? **Answer:** If you're having trouble logging in... ``` ## How to Update Your Prompts for Best Knowledge-Base Search? * **Clarify tool usage**: In your system prompt, explicitly state under which conditions the knowledge-base search tool should be triggered. * **Language consistency**: Always specify that the query language must match the document language. For example, if documents are in English, include: *"The knowledge-base-search tool query must be in English."* This is crucial for optimal search performance. * **Be explicit**: Provide clear instructions for how the retrieval tool should parse and interpret queries. * **Context matters**: Tailor prompts to explain how retrieved knowledge should be used in the response (e.g., grounding answers, summarizing docs, or citing evidence). ### Example Prompt Update for English Knowledge Base If your knowledge base is primarily in English, add this to your system prompt:\\ ### Knowledge Base Improvements The Knowledge Base system has been upgraded with several improvements to enhance performance, reliability, and multilingual support. These enhancements improve how your AI Agent retrieves and utilizes information.\ \ **Improved Context Retrieval**\ The system now uses a combination of semantic (vector-based) search and keyword-based search to retrieve more relevant information from your documents. This ensures that responses are more accurate and context-aware.\ Queries will return results only after document processing is fully completed.\ \ **Advanced Chunking Strategies**\ A new set of chunking strategies has been introduced to improve how documents are split and indexed. These strategies are more context-aware and help preserve the meaning of the content.\ This results in: * Better quality responses * More complete and readable context * Reduced chances of broken or incomplete information \ \ **Durable Ingestion System**\ The ingestion pipeline has been improved to handle large volumes of document uploads efficiently.\ This includes: * Reliable processing under high load * Retry mechanisms for failed uploads * Prevention of duplicate processing \ \ **Fallback Document Extraction**\ A fallback extraction mechanism has been added to handle edge cases where standard document parsing may fail. This ensures better support for complex or non-standard files, especially PDFs.\ \ **Multi-language Support**\ The Knowledge Base now supports improved indexing and retrieval for multiple languages, including: * Bengali (Bangla) * Japanese Selecting the correct language while creating the knowledge base is critical for achieving accurate results. This is especially important for Bengali content.\ Document Processing Behavior * Documents must reach a **Completed** status before they can be used in queries * Retrieved responses will include relevant chunks from the uploaded documents * If a document or knowledge base is deleted, its data will no longer be available for retrieval \ \ **Migration Notes**\ Due to system upgrades, existing users must re-select their knowledge base when configuring agents.\ Failure to do so may result in missing or inaccurate responses.\ \ **Access Availability**\ This feature is currently available to a limited set of users. Access requires valid: * `verbex_id` * `org_id` Please contact your administrator or support team to enable access. ```text theme={null} When using the knowledge-base-search tool, ensure all search queries are formulated in English, as the knowledge base documents are in English. This will provide the best search results and retrieval accuracy. ``` # Accessing Call Logs Source: https://docs.verbex.ai/monitoring/access-call-logs Learn how to access and review call logs in Verbex ### **Viewing Call Logs** The Call Logs section provides a comprehensive overview of all call activity. This centralized view helps you monitor system usage, track call outcomes, and ensure quality service delivery. Call log information includes: 1. Timestamps and duration 2. Call status and direction 3. Phone numbers involved 4. Agent assignments ![Call Logs Overview](https://lh7-rt.googleusercontent.com/docsz/AD_4nXd_ZWj-l8msilbo9MyflG9X03TgfwcyXyGz0cCG2yIdwdYsHdHQO7VlGn18sNWYNfXty11ZrSbc4wYPylOH-h_7vjedq4_ZYIVCfWaAJRg5FtzC0d-J5flKqjbY2L6pJ7_2_TNK?key=iyDc_tSUPZFmwxl80cHEZH40) ### **Analyzing Call Details** Each call record contains detailed analysis that helps you understand the interaction quality and outcome. This information is crucial for maintaining service quality and identifying areas for improvement. Analysis components include: 1. Duration metrics 2. Conversation analysis 3. User sentiment tracking 4. Call status details ![Call Analysis](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcIGGlTPJ4x7KrpNW6t4faR1kmIGMuyTBUlyeRC7oqoIGy0M01aPzjVuZDE6b3yvxSSxnb-oH2e8G8pZyeaIM98nO3YzOYVd6jdZEnjIOdl9Amlt_Il-OoGyc1OqFvEfvuAw9Pn?key=iyDc_tSUPZFmwxl80cHEZH40) # **Post-Call Analysis** ### View Post Call Analysis from Dashboard 1. Go to Call Logs in your Verbex Dashboard. 2. Click on the call from the list to view detail. 3. The Post Call Analysis will be in that call's detail. # Creating Your Own Verbex AI Agent Source: https://docs.verbex.ai/step-by-step-workflow Creating an AI Agent is like training a new team member – it needs the right knowledge, tools, and guidance to succeed. Verbex simplifies this process with our step-by-step approach. Each phase builds upon the previous one, ensuring your Agent develops from a basic framework into a fully-functional AI solution that meets your specific needs. Before you begin, we recommend having a clear idea of: * What tasks your assistant will handle * What knowledge it needs to access * Which channels it will use to communicate Building your AI assistant with Verbex follows five straightforward steps: * Name your assistant * Define its purpose * Set basic parameters * Design conversation flows * Add knowledge base * Set response styles * Link communication channels * Set up integrations tools * Establish data flows * Test thoroughly * Connect phone numbers * Go live * Track performance * Gather insights * Make improvements Ready to get started? Choose "Create Assistant" from the dashboard to begin building your first AI assistant. # # # # # # Built-in Tools Source: https://docs.verbex.ai/tools/built-in-tools Overview of pre-configured tools available in the Verbex platform **What you'll learn** * Available built-in tools and their purposes * Basic configuration requirements * When to use each tool # Available Built-in Tools Verbex provides several pre-configured tools that you can use immediately without additional setup. Here's an overview of each tool: ## Send Email (Gmail) Send emails directly from your AI assistant. **Key Features**: * Send emails to specified recipients * Customize subject and message content * Support for Gmail integration **Common Use Cases**: * Sending confirmation emails * Delivering meeting summaries * Forwarding important information Learn more about [Send Email Tool →](/tools/built-in-tools-send-email) ## Transfer Call Route calls to different agents or departments. **Key Features**: * Support for cold and warm transfers * Configurable transfer destinations * Optional phone number display **Common Use Cases**: * Escalating to human agents * Routing to specialized departments * Connecting to subject matter experts Learn more about [Transfer Call Tool →](/tools/call-transfers) ## Calendar Integration (Cal.com) Manage appointments and check schedules through Cal.com integration. This tool provides both calendar availability checking and appointment booking capabilities. **Key Features**: * Real-time availability checking * Automated appointment booking * Time zone support * Multi-language support * Attendee information management * Integration with popular calendar services **Common Use Cases**: * Scheduling customer appointments * Finding available meeting slots * Managing team calendars * Coordinating multiple schedules * Setting up recurring meetings * Handling appointment confirmations **Available Functions**: 1. **Check Availability**: Query available time slots within a specified date range 2. **Book Appointments**: Schedule meetings with automatic calendar updates Learn more about [Calendar Integration →](/tools/built-in-tools-calendar) # Calendar Integration Source: https://docs.verbex.ai/tools/built-in-tools-calendar Connect your calendar with Verbex to manage appointments and check schedules **What you'll learn** * How to set up Cal.com integration * How to configure calendar settings * How to get required API credentials # Overview Calendar integration allows your AI assistant to check availability and schedule appointments in real-time. This integration uses Cal.com as the centralized calendar manager, supporting various calendar services like Google Calendar and Outlook. # Prerequisites Before setting up calendar integration, ensure you have: * A Cal.com account * Access to your preferred calendar (Google Calendar, Outlook, etc.) * Admin access to your Verbex assistant # Setup Guide ## Step 1: Create Cal.com Account 1. Visit [Cal.com](https://cal.com/) 2. Sign up or sign in with your email address 3. Access the dashboard ## Step 2: Connect Your Calendar 1. In the Cal.com dashboard, click "Apps" in the left panel 2. Choose your calendar service (e.g., Google Calendar) 3. Follow the connection prompts Calendar Apps Connection ## Step 3: Create API Key 1. Click "Settings" in the bottom left corner 2. Select "API Keys" from the left panel 3. Click "Add API Key" 4. Copy and save the generated API key Store your API key securely - you'll need it to connect with Verbex. API Key Settings in Cal.com Generating API Key ## Step 4: Set Up Event Type 1. Click "Event Types" in the left panel 2. Click "+ New" to create an event type 3. Fill in the event details: * **Title**: Name your event type (e.g., "Customer Consultation") * **Description**: Write a clear description of the meeting purpose * **Duration**: Select your preferred duration from the dropdown menu 4. Click "Continue" to save your event type Create different event types for different purposes: * Quick 15-minute consultations * 30-minute product demos * 1-hour strategy sessions Keep your event type names descriptive and clear. You'll need to reference these when setting up the integration with Verbex. Creating Event Type ## Step 5: Get Event Type ID 1. Visit [Cal.com API Documentation - Find All Event Types](https://cal.com/docs/api-reference/v1/event-types/find-all-event-types) 2. In the API documentation page: * Locate the authorization field * Enter your API key that you copied earlier * Click the "Send" button API Authorization Field 3. Look for the response section below the "Find all event types" 4. You will see a list of all your event types with their corresponding IDs 5. Copy the ID of the event type you want to use with Verbex Event Type ID Response If you have multiple event types, double-check that you're copying the correct ID. Using the wrong Event Type ID will result in incorrect scheduling behavior. # Configure in Verbex Platform ## Add Calendar Tool 1. Navigate to your AI assistant's configuration 2. Select "Tools" 3. If your AI Agent doesn't have the Calendar tool: * Click "Add Tool" button * Select "Calendar Integration" from the available tools 4. If it already has the tool: * Click on the tool's edit icon to configure it ## Required Configuration Fill in the following details: 1. **Cal.com API Key** * Paste the API key you generated earlier * Keep this key secure and don't share it 2. **Event Type ID** * Add the Event Type ID you copied * Make sure it matches the event type you want to use 3. **Time Zone** * Format: "Region/City" (e.g., "Asia/Dhaka") * Must match your operating timezone The time zone format is case-sensitive. Make sure to use the exact format (e.g., "Asia/Dhaka", not "asia/dhaka"). Verbex Calendar Configuration ## Available Functions The calendar integration provides two main functions that share the same configuration: ### 1. Check Availability * Query available time slots * Verify schedule conflicts * Get real-time availability * Uses the configured event type's duration and availability settings ### 2. Book Appointments * Schedule new meetings * Manage attendee information * Send confirmations automatically * Respects buffer times and availability rules set in Cal.com Both functions use the same credentials (API Key, Event Type ID, and Time Zone) for consistency. Make sure your event type is properly configured in Cal.com with all necessary settings. Remember to update your Event Type ID in Verbex if you make any changes to your event configuration in Cal.com. For more details about API integration and advanced features, refer to the [Cal.com API Documentation](https://cal.com/docs/api-reference/v2/introduction). # Call Transfer Tool Source: https://docs.verbex.ai/tools/built-in-tools-call-transfer Enable seamless call transfers between AI assistants and human agents **What you'll learn** * How to configure call transfers * When to use call transfers * Best practices for handling transfers # Overview The Call Transfer tool enables smooth transition of calls between AI assistants and human agents. This ensures complex situations are handled appropriately while maintaining professional customer service. # Key Benefits * Seamless transition between AI and human agents * Clear transfer conditions * Maintain context during handovers * Professional customer experience # Configuration Guide Call Transfer Configuration ## Required Fields ### 1. Description * **Purpose**: Define conditions when the call should be transferred * **Content**: Specify scenarios such as: * Customer requests or keywords that trigger transfer * Specific issues requiring human assistance * Escalation conditions * **Examples**: ``` Transfer the call when: - Customer explicitly asks to speak with a human agent - Customer mentions "complaint" or "supervisor" - Technical issues involve server configuration - Customer needs to discuss billing disputes ``` ### 2. Transfer To * **What**: Destination phone number for the transfer * **Format**: International format with country code (e.g., +1234567890) * **Example**: +18005551234 * **Important**: Double-check number accuracy to ensure successful routing ### 3. Transfer Type Currently supports Cold Transfer only: #### Cold Transfer * **What**: Immediate, direct handover * **Process**: Call is transferred immediately to the specified number * **Best for**: * Direct routing to human agents * Simple transfers * High volume scenarios **Coming Soon**: Warm Transfer feature will enable contextual handovers where the receiving agent gets briefed before connecting with the caller. ### 4. Show Transferee's Number * **What**: Toggle to show/hide caller's phone number * **Use cases**: * Enable for callback requirements * Enable for call tracking * Enable for record keeping * **Privacy**: Consider regulatory requirements when enabling # Examples of the Description Field Here are examples of transfer conditions you can specify in the description: ## 1. Customer Service Escalation ``` Transfer when customer: - Asks to speak with a supervisor - Uses phrases like "manager" or "supervisor" - Expresses strong dissatisfaction - Mentions filing a complaint ``` ## 2. Technical Support ``` Transfer when conversation involves: - Enterprise-level technical issues - Server configuration - API integration problems - Security-related concerns ``` ## 3. Billing and Account ``` Transfer when customer needs to: - Dispute charges - Request refunds - Discuss payment plans - Handle account termination ``` ## 4. Emergency or Urgent Issues ``` Transfer immediately when: - Customer reports service outage - Security breach is mentioned - Time-critical issues are reported ``` **Important Considerations** * Always verify transfer numbers * Keep transfer conditions clear and specific * Monitor transfer patterns to refine conditions * Regularly update transfer scenarios based on customer needs # Troubleshooting Common issues and solutions: 1. **Failed Transfers** * Verify phone number format * Check destination availability * Confirm network connectivity 2. **Unwanted Transfers** * Review and refine transfer conditions mentioned in the description field * Make trigger phrases more specific * Monitor and adjust based on patterns Always test transfer configurations in a controlled environment before using in production. Find out more about call transfer events in [Verbex Webhook Implementation Guide](https://docs.verbex.ai/webhook) # Send Email Tool Source: https://docs.verbex.ai/tools/built-in-tools-send-email Configure Gmail integration to send automated emails through your AI assistant **What you'll learn** * How to set up Gmail integration * How to create and configure app passwords * How to enable automated email sending # Overview The Send Email tool allows your AI assistant to automatically send emails during conversations. Currently, this tool supports Gmail integration only. # Prerequisites Before setting up the email tool, ensure you have: * A Gmail account * 2-Factor Authentication enabled on your Google Account * Access to Google Account settings # Setup Instructions ## Step 1: Configure Gmail Settings 1. Go to your [Google Account Settings](https://myaccount.google.com/) 2. Enable 2-Factor Authentication if not already active 3. Navigate to Security settings 4. Search for "App Passwords" App Password Settings ## Step 2: Create App Password 1. Click on "Create App Password" 2. Select "Other (Custom name)" from the app dropdown 3. Name it "Verbex Email Integration" or any name you prefer 4. Click "Generate" 5. Copy the generated password (16-character code) Create App Password ## Step 3: Configure in Verbex Platform 1. Navigate to your AI Agent's configuration 2. Select "Tools" 3. If your AI Agent doesnt have the Send Email tool, Click "Add Tool" button to add it. If it already has the tool, click on the tool's edit icon to configure it. 4. Fill in the required details: * **From Email**: Your Gmail address * **App Password**: The 16-character code generated in Step 2 * **Description**: Brief description of how the tool will be used Verbex Email Configuration # Usage Once configured, your AI assistant can automatically: * Send confirmation emails * Deliver meeting summaries * Forward important information * Send follow-up messages The assistant will handle the email sending process seamlessly during conversations. **Security Best Practices** * Never share your app password * Regularly rotate app passwords If you need to revoke access, you can delete the app password from your Google Account settings at any time. # Using Tools Source: https://docs.verbex.ai/tools/connect-tools Learn how to enhance your AI assistant by connecting it with external tools and APIs **What you'll learn** * What tools are and how they work with AI assistants * When and how to use different types of tools * How to set up tools through Dashboard or API # Understanding Tools in AI Assistants Tools enable AI assistants to perform actions beyond just conversation. Your AI assistant can interact with external systems, APIs, and functions to perform specific tasks like: * Booking appointments * Sending emails * Retrieving information from databases * Transferring calls When an action is needed, the AI assistant recognizes it, generates the appropriate function call, and sends it to the external tool for execution. # When to Use Tools Tools are particularly valuable in these scenarios: ## Task Automation * Scheduling meetings * Checking account balances * Sending automated emails ## API Interactions * Fetching user data from CRM systems * Getting real-time information * Updating external databases ## Real-Time Data Access * Checking current stock prices * Verifying travel availability * Viewing calendar schedules ## Call Management * Transferring conversations between agents * Routing calls to appropriate departments ## Complex Workflows * Handling multi-step processes * Managing user authentication * Processing complex requests # Tools in Verbex Platform The Verbex platform offers two types of tools: ## 1. Built-in Tools Pre-configured tools ready for immediate use: * **End Call**: Terminates conversation when complete * **Transfer Call**: Routes user to another agent * **Send Email**: Automates email communication * **Check Calendar**: Verifies schedule availability * **Book Calendar**: Schedules appointments ## 2. Custom Tools Create your own tools by connecting to external APIs: ```json theme={null} { "tool_name": "GetUserInfo", "tool_description": "Get detailed user information from the API", "endpoint_url": "https://api.example.com/getUserInfo", "method": "GET", "headers": {"Authorization": "Bearer token_value"}, "query_params": {"userId": "12345"} } ``` # Setting Up Tools ## Using Dashboard 1. Navigate to assistant setup 2. Select built-in tools from dropdown 3. Add custom tools by configuring: * API endpoint * Method * Headers * Parameters ## Using API Configure tools programmatically: ```python theme={null} tools = { "built_in_tools": [ { "tool_name": "End Call", "description": "Terminates the conversation after completion", "usage": "Called when task is complete or user requests end" } ], "custom_tools": [ { "tool_name": "GetUserInfo", "endpoint_url": "https://api.example.com/getUserInfo", "method": "GET", "headers": {"Authorization": "Bearer token_value"}, "query_params": {"userId": "12345"} } ] } # Create assistant with tools verbex.create_single_llm(assistant_info=assistant_info, llm=llm, tools=tools) ``` # Best Practices ## Clear Triggers Define when tools should be used: ```python theme={null} "If user asks for weather, call get_weather function" "Once questions are answered, call end_call" ``` ## Detailed Descriptions Write clear tool descriptions: ```python theme={null} "GetUserInfo: Retrieves customer details including name, email, and account status from CRM system" ``` ## Parameter Formatting Specify exact parameter requirements: ```python theme={null} "user_id must be a string in format 'USR-XXXXX'" "amount must be a positive number with max 2 decimal places" ``` ## Performance Optimization * Handle concurrent tool calls efficiently * Keep the response of the tool as short and concise as possible. Include only the necessary information. * Ensure the response time is as less as possible to avoid delays in the conversation **Important Tips** * Tools execute sequentially to avoid conflicts * Backend should handle potential duplicate calls * Always validate tool inputs before execution * Monitor tool performance and usage patterns # Custom Tools Integration Source: https://docs.verbex.ai/tools/custom-tools Connect your AI assistant with external business systems using custom tools **What you'll learn** * Understanding custom tools and their purpose * How to configure custom tool integrations * Setting up authentication and security # Understanding Custom Tools ## What is a Custom Tool? A Custom Tool in Verbex acts as a bridge between your AI Assistant and your external business systems. It enables your assistant to interact directly with other software systems your business uses daily. Think of custom tools as teaching your AI Assistant how to use your business software - when a customer asks about an order, your assistant can look it up directly in your system! ## Purpose and Functionality Custom tools transform your AI Assistant from a conversational interface into an active participant in your business processes. For example: * Check order status in real-time * Create leads in your CRM * Schedule appointments * Update customer records ## Technical Configuration Each custom tool requires several key components: 1. **Name**: A descriptive identifier (e.g., "create\_salesforce\_lead") 2. **Description**: A brief description of the tool's purpose (e.g., "Create a new lead in Salesforce by sending lead data name, email, and company name to the API") 3. **Endpoint URL**: Where to send requests (e.g., "[https://api.yoursystem.com/leads](https://api.yoursystem.com/leads)") 4. **HTTP Method**: How to interact (POST, GET, etc.) 5. **Parameters**: What data to send or receive ## Authentication and Security Security is managed through authentication parameters: * API keys in headers * Bearer tokens * OAuth credentials * Custom authentication methods Always store sensitive credentials securely and never expose them in your code or conversations. ## Adding Custom Tools Using Dashboard In the dashboard, you can add custom tools by clicking on the "Add Tool" button and selecting "Custom Tool". In the UI you will find all the necessary fields to fill in as a REST API request. Learn about how to Integrate [Salesforce CRM →](/tools/custom-tools-salesforce) as a custom tool. # Make.com Webhook Integration Source: https://docs.verbex.ai/tools/custom-tools-make-dot-com Connect your Verbex AI Assistant with Make.com as a custom tool **What you'll learn** * How to set up Make.com simple scenario * How to create a Make.com Connected App * How to integrate Make.com with Verbex Platform * How to test and verify the integration [Make.com](https://www.make.com/en) (formerly Integromat) is a powerful no-code automation platform that allows users to connect apps, services, and tools to automate workflows and tasks without writing code. It provides a visual drag-and-drop interface to create scenarios (automation workflows) by linking triggers, actions, and data across multiple applications. This guide will show you how to set up a simple scenario in Make.com and integrate it with your Verbex AI Assistant. ## Prerequisites * A Make.com account * Understanding of Make.com scenario setup * Access to your Verbex AI Assistant * Basic understanding of API integration Let's walk through setting up a simple scenario in Make.com. ## Scenario Background We will create a scenario that will send input to a webhook, webhook will send the input to Google Sheets and update a row in Google Sheets and then Google Sheets will send a response as webhook response. **Scenario Flow**: Custom Webhook -> Google Sheets -> Webhook Response ## Step 1: Create a Scenario 1. Log into Make.com 2. Navigate to the "Scenarios" tab 3. Click the "Create Scenario" button 4. Enter a name for your scenario ## Step 2: Configure Scenario 1. Click on "Add Module" 2. Select "Webhook -> Custom Webhook" 3. Configure your webhook and copy the webhook URL 4. Create another module and select "Google Sheets -> Update Row" 5. Configure your Google Sheets and select the sheet and row to update 6. Create another module and select "Webhook -> Webhook Response" 7. Configure your webhook response if necessary. 8. Save and run your scenario and the webhook will listen for the data. 9. Now you can test your scenario by webhook URL by sending data using CURL or Postman. For this you need following information: * Webhook URL: (eg: [https://hook.eu2.make.com/example-webhook-id](https://hook.eu2.make.com/example-webhook-id)) * Body Parameters: Data you want to send through Verbex AI to webhook. example: ```json theme={null} { "name": "Sagor Sarker", "email": "sagor@example.com", "phone_number": "1234567890" } ``` ```bash theme={null} curl -X POST "https://hook.eu2.make.com/example-webhook-id" \ -H "Content-Type: application/json" \ -d '{ "name": "Sagor Sarker", "email": "sagor@example.com", "phone_number": "1234567890" }' ``` ## Step 3: Connect Make Webhook with Verbex AI 1. Go to "Add Tool -> Custom Tool" 2. Configure the tool: * **Name**: make\_webhook * **Description**: Make Webhook to send name, email, phone to Google Sheets * **Endpoint URL**: Custom Webhook URL (eg: [https://hook.eu2.make.com/example-webhook-id](https://hook.eu2.make.com/example-webhook-id)) * **Method**: POST * **Headers**: For webhook based connection no authentication is required. 3. Configure Body Parameters: This params will be sent to Make.com and update a row in Google Sheets. ```json theme={null} { "name": "string", "email": "string", "phone": "string" } ``` 4. Test your custom tool in Verbex AI webcall and make sure everything is working as expected in Make.com scenario. For more details, refer to the [Make.com Documentation](https://www.make.com/en/help/app/make). # Zapier Webhook Integration Source: https://docs.verbex.ai/tools/custom-tools-zapier Connect your Verbex AI Assistant with Zapier Zap as a custom tool **What you'll learn** * How to set up Zapier Zap * How to create a Zapier Webhook * How to integrate Zapier with Verbex Platform * How to test and verify the integration [Zapier](https://zapier.com/) is a platform that allows you to automate tasks across different apps. It provides a visual interface to create automated workflows by connecting triggers, actions, and data across multiple applications. ## Prerequisites * A Zapier account * A Verbex account * Understanding of Zapier Zap * Understanding of Verbex Agent and Custom Tools ## Zap Summary We will create a Zapier Zap to send data to a webhook and then to Google Sheets. **Zapier Flow**: Webhook -> Google Sheets ## Create a Zapier Zap 1. Go to [Zapier](https://zapier.com/) and sign in. Create a Zap 2. Click on the "Create a Zap" button. Create a Zap 3. Select "Webhook" as the trigger. Setup the trigger to listen for a request. Create a Zap Create a Zap 4. Configure the webhook trigger event to "Catch Hook" Create a Zap 5. After configuring you will get a webhook URL. Copy it for later use. Create a Zap 6. Now test the webhook by sending a request to the URL. Here is an example CURL request: ```bash Send data to webhook theme={null} curl -X POST "https://hooks.zapier.com/hooks/xyz" \ -H "Content-Type: application/json" \ -d '{"name": "Sagor3", "email": "sagor3@gmail.com"}' ``` ```json Response from webhook theme={null} { "attempt": "0194d08d-fc38-c8c0-482e-7e202b923762", "id": "0194d08d-fc38-c8c0-482e-7e202b923762", "request_id": "0194d08d-fc38-c8c0-482e-7e202b923762", "status": "success" } ``` You can see the send data in Webhook test section. Create a Zap 7. Now add another trigger "Google Sheets" Create a Zap 8. Configure it "Create Spreadsheet Row(s)" as the trigger. Create a Zap Create a Zap 9. Configure it more with your Google Sheet, sheet name, column names etc. Remember while filling the column you can point the value from webhook data. Create a Zap 10. Now test the zap by clicking on the "Test" button. You can see the test results in "Data in" and "Data out" section. Create a Zap 11. Now you can see the data in your Google Sheet. Create a Zap ## Zapier Webhook Integration with Verbex 1. Go to your Verbex agent page. Select your agent to configure the tool. 2. Click on the "Tools" tab and select "Custom Tools" from the left sidebar. Create a Zap 3. Fill the custom tool details with Zapier Webhook Integration details. Create a Zap Create a Zap 4. Click on the "Create Tool" button to save the tool. 5. Now everything is setup and you can test your agent with the tool. You can test the tool by asking the agent to store your name and email in Zapier and Google Sheet. It will ask your name and email and store it in Zapier and Google Sheet. To learn more about Zapier follow [Zapier Documentation →](https://docs.zapier.com/platform/home) When creating Zaps and custom tools, always use descriptive names. This helps in easily identifying and managing them later. Always test your Zaps and custom tools thoroughly to ensure they work as expected. Use the "Test" button in Zapier and verify the data in your Google Sheets. Ensure that any credentials or sensitive information used in your integrations are stored securely. Avoid hardcoding them in your scripts. Always refer to the official documentation of the tools you are integrating, such as Zapier and Verbex, for the latest updates and best practices. Regularly monitor the performance of your Zaps and custom tools. Optimize them for better performance and to handle any changes in the workflow. # RBAC User Guide Source: https://docs.verbex.ai/user-manual ### **User Guide for Workspace Role Based Access Control in Verbex - Feature Request From Japan** #### **Accessing Role Based Access Control** When users first interact with the**Role Management** screen, they will be greeted with a **Workspace Selector** at the top, as shown in the screenshot below: * **Workspace Dropdown**: This allows users to select the active workspace for which they want to manage roles and users. By default, it shows the current workspace and can be switched for managing other workspaces. * **Roles Section**: This section lists the available roles with the option to add new roles. * **Users Section**: Below the roles, a list of users associated with the workspace will be displayed. For each user, their **name**, **email**, **role**, **status**, and **joined date** are visible and update the role if needed. **UI Flow**: 1. **Select Workspace**: The user starts by selecting the workspace they want to manage from the workspace dropdown. 2. **View Roles**: All available roles are displayed, such as the **WORKSPACE\_MEMBER** (default), with the associated permissions. Users can then manage roles and users based on the selected workspace. #### **Adding a New Role** To add a new role, users will click the **Add New Role** button, which opens a modal for creating new roles. * **Role Name**: Users must enter a unique name for the role. * **Role Description**: A brief description explaining the role's responsibilities. * **Permissions**: Users can then select from a list of available permissions, such as "View Concurrency", "Create AI Agent", or "Delete AI Agent". These permissions govern the actions users in that role can perform. **UI Flow**: 1. **Click Add New Role**: A modal opens, where the user inputs the **Role Name** and **Description**. 2. **Select Permissions**: The user can then choose the permissions associated with this role by using the **Permissions** dropdown list. This includes various permissions like **View Concurrency**, **Create AI Agent**, **Delete AI Agent**, and more. **Example Roles**: * **Call Logs**: Limited to actions like viewing call logs and managing calls. #### **Updating an Existing Role** If the user needs to modify an existing role, they can click on the role's name in the **Roles Section**. This brings up the **Role Details** screen. * **Role Details**: Shows the role's name, description, and a list of permissions currently assigned to the role. * **System-Generated Roles**: Certain roles, like **WORKSPACE\_MEMBER**, are automatically generated by the system and cannot be edited. These roles are essential for defining access at the workspace level. **UI Flow**: 1. **Click on Role Name**: The user clicks on an existing role to modify it. 2. **Modify Permissions**: Permissions can be added or removed using checkboxes, and the role can be saved once changes are made. #### **Inviting a User to the Workspace** Users can invite others to the workspace by clicking **Invite User**. In this screen: * **Email Input**: The user enters the email address of the person they wish to invite. * **Role Assignment**: After entering the email, the user can assign a role to the invitee. This determines the level of access they will have in the workspace. **UI Flow**: 1. **Click Invite User**: A modal opens where the user enters the email of the person to invite. 2. **Assign Role**: The user assigns a predefined role to the invitee. 3. **Send Invitation**: The invitation is sent, and the new user will receive an email to join the workspace. #### **Managing Permissions and Access Control** As part of **Role-Based Access Control (RBAC)**, each role has specific permissions that define what actions a user can perform. The **permissions list** includes actions like: * **Create/Manage Workspaces** * **Create/Manage AI Agents** * **View Usage & Invoices** * **Set Phone Number Concurrency etc.** Permissions are linked to roles in a way that users can only perform actions based on their assigned role. For example: * **Workspace Owners** have full control over workspace settings, including adding members and managing roles. * **Workspace Members** may have limited permissions, such as operating agents or viewing usage, but cannot modify workspace settings or roles. **UI Flow**: 1. **Assign Permissions to Roles**: Users can select which permissions each role will have, ensuring that only the appropriate level of access is granted. 2. **Enforce RBAC**: Verbex automatically applies these permissions based on the role, ensuring a secure environment where users only access the tools and data necessary for their work. #### **Troubleshooting and Best Practices** * **Role Conflicts**: If a user has multiple roles, Verbex will automatically apply the highest privileged role. Ensure that role assignments are clear to avoid conflicts. * **Permission Denials**: If a user tries to access a feature not granted by their role’s permissions, they will receive an error with a clear message explaining the restriction. **Permission List - APIs (Default)** \ **APIKeysService (4 permissions)** * CREATE\_API\_KEY * GET\_API\_KEY * LIST\_API\_KEYS * REVOKE\_API\_KEY ### **AiAgentService (4 permissions)** * DELETE\_AI\_AGENT * GET\_AI\_AGENT * LIST\_AI\_AGENTS * UPDATE\_AI\_AGENT ### **AuthorizationService (8 permissions)** * ORGANIZATION\_OWNER\_PERMISSIONS\_LIST\_GET * ORGANIZATION\_ROLE\_DETAILS\_GET * ORGANIZATION\_ROLE\_LIST\_GET * ORGANIZATION\_WORKSPACE\_ROLE\_ADD\_PERMISSIONS * ORGANIZATION\_WORKSPACE\_ROLE\_CREATE * ORGANIZATION\_WORKSPACE\_ROLE\_DELETE * ORGANIZATION\_WORKSPACE\_ROLE\_REMOVE\_PERMISSIONS * ORGANIZATION\_WORKSPACE\_ROLE\_UPDATE ### **CallService (6 permissions)** * CALL\_DETAILS * CALL\_LOGS * CREATE\_WEB\_CALL * DIAL\_OUTBOUND\_CALL * DYNAMIC\_DATA\_GET * VIEW\_CONCURRENCY ### **PhoneNumbers (5 permissions)** * PHONE\_NUMBERS\_CREATE * PHONE\_NUMBERS\_GET * PHONE\_NUMBER\_DELETE * PHONE\_NUMBER\_GET * PHONE\_NUMBER\_PATCH ### **PhoneService (1 permission)** * PHONE\_NUMBER\_GET\_WITHOUT\_SLASH ### **PostCallAnalysis (5 permissions)** * POST\_CALL\_ANALYSIS\_CREATE * POST\_CALL\_ANALYSIS\_DELETE * POST\_CALL\_ANALYSIS\_GET * POST\_CALL\_ANALYSIS\_GET\_RESULT * POST\_CALL\_ANALYSIS\_PUT ### **ToolsService (10 permissions)** * AI\_AGENT\_BUILTIN\_TOOLS * CREATE\_AI\_AGENT\_BUILTIN\_TOOL * CREATE\_AI\_AGENT\_CUSTOM\_TOOL * DELETE\_AI\_AGENT\_BUILTIN\_TOOL * DELETE\_AI\_AGENT\_CUSTOM\_TOOL * GET\_AI\_AGENT\_BUILTIN\_TOOL * GET\_CUSTOM\_TOOL * LIST\_AI\_AGENT\_CUSTOM\_TOOLS * UPDATE\_AI\_AGENT\_BUILTIN\_TOOL * UPDATE\_AI\_AGENT\_CUSTOM\_TOOL ### **WebhookService (6 permissions)** * WEBHOOK\_CREATE * WEBHOOK\_DELETE * WEBHOOK\_DETAILS\_GET * WEBHOOK\_GET * WEBHOOK\_ORGANIZATION\_GET * WEBHOOK\_UPDATE ### **WorkspaceService (12 permissions)** * ASSIGN\_WORKSPACE\_MEMBER * CREATE\_WORKSPACE * DELETE\_ASSIGN\_MEMBER\_FROM\_WORKSPACE * DELETE\_WORKSPACE * GET\_WORKSPACE\_ALL\_ENDPOINT * GET\_WORKSPACE\_DETAILS * GET\_WORKSPACE\_ID * GET\_WORKSPACE\_MEMBERS * GET\_WORKSPACE\_USER * UPDATE\_ASSIGN\_WORKSPACE\_MEMBER * UPDATE\_WORKSPACE * VIEW\_WORKSPACE\_LIST ###       Verbex’s RBAC implementation ensures the following: 1. **Granular Role Management**: Each role has a unique set of permissions that dictate what actions can be performed. 2. **Clear Separation of Responsibilities**: Owners have full control, while members are restricted to tasks appropriate for their roles. 3. **Security and Compliance**: By enforcing RBAC at every level of the system, Verbex ensures secure access to sensitive data and operations. # Verbex Videos - Introduction Source: https://docs.verbex.ai/video-tutorials/introduction Verbex AI Video Tutorials Welcome to the Verbex video resource center! Here you can discover helpful tutorials, share your YouTube content, suggest topics for future videos, and stay connected with our latest releases. ## Follow us on YouTube Follow us on YouTube for the latest updates and tutorials. ## Request or Suggest a Video Request or suggest a video. # WAF User Guide Source: https://docs.verbex.ai/waf-user-manual **WAF - Web Application Firewall - Feature Request from Japan** ### **User Guide for WAF Configuration in Verbex** #### **1. Accessing WAF Configuration** To begin configuring your **WAF (Web Application Firewall)**, navigate to the **Dashboard** of your Verbex account. In the left-hand sidebar, find and click the **WAF Configuration** option. You will be presented with the following UI elements: * **WAF Toggle**: A toggle button at the top of the page to enable or disable WAF for your organization. * **WAF Rule Table**: Displays the current WAF rules applied to the organization, including **IP Address**, **IP Type**, **Action**, **Reason**, **Notes**, **Expires At**, and an **Actions** column for managing the rules. The screen may initially display "No WAF rules found" if no rules have been configured yet. #### **2. Enabling WAF** Once you access the **WAF Configuration** section, the first step is to enable WAF if it is not already activated for your organization. **UI Flow**: 1. **Click the WAF Toggle**: Switch the toggle to **ON** to activate the WAF functionality for your organization. 2. **Confirmation Dialog**: A modal will appear confirming if you want to enable WAF. You will be asked to select a **Default Policy**: * **ALLOW**: Allows all traffic by default and blocks only explicitly denied requests. * **DENY**: Denies all traffic by default, only allowing explicitly allowed requests. **Action**: * Choose the **Default Policy** for your organization based on your security requirements. * Click **Enable** to confirm the settings and activate WAF. #### **3. Editing Default Policy** After enabling WAF, you can adjust the **Default Policy** settings. **UI Flow**: 1. **Click the 'Edit' Icon**: Next to the default policy setting in the WAF Configuration screen, click the **Edit Default Policy** button. 2. **Modify Default Policy**: You can select between **ALLOW** or **DENY** from the dropdown menu, depending on your security needs. 3. **Save Changes**: After selecting the appropriate policy, click **Update** to save the changes. This setting will affect all traffic until further specific rules are added. #### **4. Creating WAF Rules** To protect your platform from malicious traffic, you can create **custom WAF rules** based on your security needs. **UI Flow**: 1. **Click 'Create WAF Rule'**: This will open a modal where you can define a new rule for your WAF configuration. 2. **Fill in Rule Details**: * **IP Address**: Specify the IP address, CIDR notation, or IP range to apply the rule to. * **IP Type**: Select the type of IP address matching (e.g., **EXACT** or other types, depending on your preference). * **Reason**: Provide a brief explanation of why this rule is being added (e.g., **DDoS Attacker**). * **Notes**: Optionally, add additional notes for clarification. * **Expires At**: Set an expiration date for this rule if it's temporary. 3. **Click Create**: Once all fields are filled in, click **Create** to finalize the new rule. #### **5. Managing WAF Rules** Once WAF is enabled and rules are configured, you can manage existing WAF rules directly from the **WAF Configuration** page. * **View Existing Rules**: In the rule table, you can see all the configured rules, including their **IP Address**, **IP Type**, **Action**, **Reason**, and expiration details. * **Delete or Edit Rules**: The **Actions** column provides options to either **Edit** or **Delete** existing rules. Click the **ellipsis** (...) icon next to the rule for more options. #### **6. Monitoring WAF Configuration** With WAF enabled and rules applied, it’s important to regularly monitor the firewall configuration to ensure it is functioning as intended. * **Review Blocked Traffic**: Verbex logs traffic that has been blocked based on WAF rules. You can periodically check for any blocked requests that may indicate malicious activity. * **Adjust Rules as Needed**: If necessary, you can update or remove rules based on changes to the security landscape or false positives. #### **7. Troubleshooting** * **WAF Not Blocking Traffic**: Ensure that the rules are correctly configured and that the IP addresses or ranges are accurately specified. * **Incorrect Policy Behavior**: If the policy doesn't behave as expected (e.g., blocking valid requests), verify that the **Default Policy** is set correctly, and check the individual rules for conflicts. * **Expired Rules**: If a WAF rule is no longer needed, ensure it is deleted or the expiration date is set properly to avoid security lapses. 1. **Start with Default Allow or Deny**: Choose a default policy that aligns with your organization's security needs (e.g., **ALLOW** for high-trust environments or **DENY** for stricter control). 2. **Granular Rules**: Use specific IP ranges and precise actions in your rules to prevent misconfigurations and unintended blocks. 3. **Regular Monitoring**: Frequently review and adjust WAF rules to address evolving security threats. 4. **Document Reasoning**: Always add a clear reason and notes to each rule for future reference and compliance purposes. # Web Application Firewall Guideline Source: https://docs.verbex.ai/web-application-firewall-guideline Verbex uses a **Web Application Firewall (WAF)** to protect platform APIs and services from common web threats and malicious traffic. ### Organization-Specific Protection * WAF rules are applied **per organization** to ensure isolated and customizable protection. * Each organization can define its own WAF policy based on its security requirements. ### Policy Modes Organizations can configure their WAF policy in one of the following modes: * **Default Deny with Allow Rules** * All traffic is denied by default. * Only explicitly allowed requests are permitted. * **Default Allow with Deny Rules** * All traffic is allowed by default. * Only explicitly denied requests are blocked.   ## **Quick Start** ### **1. Configure WAF for Your Organization** ``` # Create WAF configuration (ALLOW mode - blocklist)curl -X POST /v1/waf/config \ -H "X-User-Org-Id: your-org-id" \ -H "Content-Type: application/json" \ -d '{ "default_policy": "ALLOW", "status": "ACTIVE" }' ``` ### **2. Add IP Rules** ``` # Block a malicious IPcurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: your-org-id" \ -H "Content-Type: application/json" \ -d '{ "ip_address": "198.51.100.50", "action": "BLOCK", "reason": "Suspicious activity detected" }' ``` ### **3. Check IP Access** ``` # Check if an IP should be blockedcurl -X POST /v1/waf/check \ -H "X-User-Org-Id: your-org-id" \ -H "Content-Type: application/json" \ -d '{"ip_address": "198.51.100.50"}' ``` **Response:** ``` { "ip_address": "198.51.100.50", "is_blocked": true, "action": "BLOCK", "matched_rule": "rule-id-here"} ``` *** ## **Core Concepts** ### **Default Policy**   | Policy | Mode | Behavior | | :- | :- | :- | | `ALLOW` | Blocklist | Allow all IPs by default, block specific threats | | `DENY` | Allowlist | Block all IPs by default, allow specific trusted IPs |   ### **IP Types**   | Type | Format | Example | Description | | :- | :- | :- | :- | | `EXACT` | Single IP | `192.168.1.100` | Match one specific IP | | `CIDR` | IP Range | `192.168.1.0/24` | Match IP range (256 IPs) |   ### **CIDR Notation** ``` IP_ADDRESS / PREFIX_LENGTH ```   | CIDR | Subnet Mask | IP Range | Total IPs | | :- | :- | :- | :- | | `/32` | 255.255.255.255 | Single IP | 1 | | `/24` | 255.255.255.0 | x.x.x.0 - x.x.x.255 | 256 | | `/16` | 255.255.0.0 | x.x.0.0 - x.x.255.255 | 65,536 | | `/8` | 255.0.0.0 | x.0.0.0 - x.255.255.255 | 16,777,216 |   ### **Rule Priority (Specificity)** When multiple rules match, the most specific wins: ``` /32 (exact) > /24 > /16 > /8 (broadest) ``` **Example:** * Rule 1: `BLOCK 10.0.0.0/8` * Rule 2: `ALLOW 10.1.2.3/32` Result: IP `10.1.2.3` is **ALLOWED** (`/32` beats `/8`) ### **WAF Status**   | Status | Behavior | | :- | :- | | `ACTIVE` | WAF rules are enforced | | `INACTIVE` | All IPs allowed (bypass mode for troubleshooting) |   *** ## **API Reference** ### **Endpoints**   | Endpoint | Method | Description | | :- | :- | :- | | `/v1/waf/check` | POST | Check if IP should be blocked | | `/v1/waf/config` | GET | Get WAF configuration | | `/v1/waf/config` | POST | Create WAF configuration | | `/v1/waf/config` | PUT | Update WAF configuration | | `/v1/waf/rules` | POST | Create a rule | | `/v1/waf/rules/paginated` | GET | List rules with pagination | | `/v1/waf/rules/{ruleId}` | GET | Get rule by ID | | `/v1/waf/rules/{ruleId}` | PUT | Update rule | | `/v1/waf/rules/{ruleId}` | DELETE | Delete rule | | `/v1/waf/rules/activate-all` | POST | Activate all rules | | `/v1/waf/rules/deactivate-all` | POST | Deactivate all rules | | `/v1/waf/cache/{orgId}` | DELETE | Clear cache | | `/v1/waf/cache/{orgId}/sync` | POST | Sync cache from database |   ### **Request Headers**   | Header | Required | Description | | :- | :- | :- | | `X-User-Org-Id` | Yes | Organization identifier | | `X-User-ID` | No | User ID for audit trail | | `X-Client-IP` | No | Client IP for auto-rule creation | | `X-Trace-Id` | No | Request correlation ID |   ### **Data Models** **WAF Configuration:** ``` { "org_id": "string", "default_policy": "ALLOW | DENY", "status": "ACTIVE | INACTIVE", "created_at": "2026-02-17T10:00:00Z", "updated_at": "2026-02-17T10:00:00Z" } ``` **IP Access Rule:** ``` { "id": "string", "org_id": "string", "ip_address": "192.168.1.100", "ip_type": "EXACT | CIDR", "action": "ALLOW | BLOCK", "reason": "string", "is_active": true, "expires_at": "2026-03-17T00:00:00Z", "notes": "string", "created_at": "2026-02-17T10:00:00Z", "updated_at": "2026-02-17T10:00:00Z" } ``` **IP Check Response:** ``` { "ip_address": "192.168.1.100", "is_blocked": false, "action": "ALLOW", "matched_rule": "rule-id or null", "default_policy": "ALLOW (if no rule matched)" } ``` *** ## **Configuration** ### **Application Properties** ``` waf: enabled: true # Enable/disable WAF default-policy: ALLOW # System-wide default cache-ttl: PT1H # Redis cache TTL max-rules-per-org: 1000 # Max rules per org debug-logging: false # Verbose logging negative-cache: enabled: true # Cache "no rule" results ttl: PT5M # Negative cache TTL cache-warmup: enabled: true # Preload on startup delay: PT5S # Warmup delay batch-size: 100 # Orgs per batch ``` ### **Limits**   | Resource | Limit | | :- | :- | | Rules per organization | 1,000 | | Batch operations | 100 rules | | Pagination max size | 100 items |   *** ## **Usage Examples** ### **Example 1: Blocklist Mode (Default: ALLOW)** Block specific threats while allowing all other traffic. ``` # 1. Configure ALLOW modecurl -X POST /v1/waf/config \ -H "X-User-Org-Id: acme-corp" \ -d '{"default_policy": "ALLOW", "status": "ACTIVE"}'# 2. Block attacker IPcurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: acme-corp" \ -d '{"ip_address": "198.51.100.50", "action": "BLOCK", "reason": "Brute force"}' ``` **Result:**   | IP | Rule Match | Access | | :- | :- | :- | | `203.0.113.10` | No rule → Default ALLOW | Allowed | | `198.51.100.50` | BLOCK rule | Blocked |   ### **Example 2: Allowlist Mode (Default: DENY)** Only allow specific trusted IPs. ``` # 1. Configure DENY mode (auto-creates rule for your IP)curl -X POST /v1/waf/config \ -H "X-User-Org-Id: acme-corp" \ -H "X-Client-IP: 203.0.113.10" \ -d '{"default_policy": "DENY", "status": "ACTIVE"}'# 2. Allow office networkcurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: acme-corp" \ -d '{"ip_address": "192.168.1.0/24", "action": "ALLOW", "reason": "Office network"}' ``` **Result:**   | IP | Rule Match | Access | | :- | :- | :- | | `203.0.113.10` | Auto-created ALLOW | Allowed | | `192.168.1.50` | CIDR ALLOW | Allowed | | `10.0.0.99` | No rule → Default DENY | Blocked |   ### **Example 3: Temporary Contractor Access** ``` # Create rule with expirationcurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: acme-corp" \ -d '{ "ip_address": "45.67.89.100", "action": "ALLOW", "reason": "Contractor - Project Alpha", "expires_at": "2026-03-17T00:00:00Z", "notes": "Contract #CON-2026-042" }' ``` Rule auto-expires and is cleaned up by hourly job. ### **Example 4: CIDR with Exception** Block a range but allow specific IP within it. ``` # Block suspicious rangecurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: acme-corp" \ -d '{"ip_address": "198.51.100.0/24", "action": "BLOCK", "reason": "Malicious range"}'# Allow trusted partner in that rangecurl -X POST /v1/waf/rules \ -H "X-User-Org-Id: acme-corp" \ -d '{"ip_address": "198.51.100.75", "action": "ALLOW", "reason": "Trusted partner"}' ``` **Result:** `198.51.100.75` is ALLOWED (`/32` beats `/24`) *** ## **Architecture** ### **Multi-Tenant Design** WAF operates at the organization level with complete isolation. ``` flowchart TB subgraph Platform["Platform"] subgraph Org1["Organization A"] WAF1["WAF Config + Rules"] end subgraph Org2["Organization B"] WAF2["WAF Config + Rules"] end end ``` ### **IP Check Flow** ### **Redis Key Patterns**   | Key | Type | Purpose | | :- | :- | :- | | `waf:exact:{orgId}` | Hash | Exact IP rules | | `waf:cidr:{orgId}` | Hash | CIDR rules | | `waf:config:{orgId}` | String | Default policy | | `waf:nc:{orgId}:{ip}` | String | Negative cache |   ### **Storage** * **MongoDB**: Source of truth for config and rules * **Redis**: High-performance cache layer *** ## **Performance** ### **Response Times**   | Scenario | Latency | | :- | :- | | Redis hit (exact/CIDR) | \~1ms | | Redis hit (negative cache) | \~1ms | | MongoDB fallback | \~15ms |   ### **Negative Cache** Caches "no rule found" results to prevent repeated MongoDB queries. **Without negative cache:** Every unknown IP → MongoDB query **With negative cache:** First query → MongoDB, subsequent → Redis (\~93% faster) ### **Cache Invalidation**   | Operation | Invalidation Scope | | :- | :- | | Create exact rule | Single IP negative cache | | Create CIDR rule | All negative cache for org | | Update policy | All negative cache for org | | Sync cache | All cache for org |   *** ## **Troubleshooting** ### **Enable Debug Logging** ``` waf: debug-logging: true ```   ### **Common Issues**   | Issue | Solution | | :- | :- | | Rule not taking effect | Clear cache: `DELETE /v1/waf/cache/{orgId}` | | Locked out after DENY mode | Auto-rule should be created; check with `GET /v1/waf/rules` | | High latency | Check Redis connectivity; ensure cache warmup completed | | Rules not expiring | Verify cleanup scheduler is running |   ### **Bypass WAF for Troubleshooting** Set status to `INACTIVE` to allow all traffic: ``` curl -X PUT /v1/waf/config \ -H "X-User-Org-Id: your-org-id" \ -d '{"status": "INACTIVE"}' ``` **Remember to re-enable after troubleshooting!** *** ## **Safety Features** ### **Auto-Rule Creation** When switching to `DENY` mode, an `ALLOW` rule is automatically created for the requesting client IP to prevent admin lockout. ### **Policy Change Protection** Changing between `ALLOW` and `DENY` clears existing rules to ensure consistent behavior. *** # Verbex Webhook Implementation Guide Source: https://docs.verbex.ai/webhook Webhooks let your systems get real-time notifications from Verbex about call lifecycle and PCA availability. As events occur, Verbex sends POST requests with JSON payloads to your HTTPS endpoint so you can update CRMs, trigger workflows, and fetch PCA immediately.\ \ Verbex sends real-time webhooks at Multiple key moments in a call’s lifecycle: * **Call Started** ( `CallHandler.CallStarted` ) * **Call Ended** ( `CallHandler.CallEnded` ) * **Call Transfer** ( `CallHandler.CallTransferred` ) * **PCA Completed** ( `callAnalysis.pcaCompleted` , typically 1–30s after end) These events let your systems react instantly—create or update CRM cases, trigger alerts, and (most importantly) **fetch PCA** to automate next steps such as follow-up outbound calls, notifications, or escalations. ## **What You Get (Benefits)**  * **Instant awareness** of live calls and completion (no polling). * **Actionable insights** the moment PCA is ready. * **Automated workflows**: kick off follow-ups, send SMS/email, open tickets, or route to a human agent using PCA outcomes. * **Operational visibility**: power real-time dashboards for call status and PCA readiness. ## **When to Use Webhooks** Use these webhooks if you need to: * **Show live call status** in CRM/Helpdesk/BI dashboards. * **Automate post-call actions** the moment PCA is available. * **Orchestrate follow-ups** (e.g., schedule/trigger another outbound call). * **Sync data** to external systems (CRM, ticketing, data warehouse) tied to `call_id`. ## **Event Catalogue & Typical Client Actions** | **Event** | **Purpose** | **Typical Client Action** | | :- | :- | :- | | **Call Started** (`CallHandler.CallStarted`) | Signals a new call session has begun. | Create/attach a live engagement record; mark status = “In Progress”. | | **Call Ended** (`CallHandler.CallEnded`) | Signals call completion. | Mark record “Completed”; prepare to await PCA. | | **PCA Completed** (`callAnalysis.pcaCompleted`) | PCA is ready (1–30s post-end). | **Fetch PCA by**`call_id`; evaluate rules; trigger follow-ups/notifications/escalations. | | **Call Transfer** ( `CallHandler.CallTransferred` ) | Signals a call transfer has been initiated. Triggered when the AI agent transfers the call to a human agent or external number. | Route call to receiving agent using transfer\_to destination; update CRM record with `transfer status` and `reason`; send `context/transcript` to receiving agent. | **Note:** Events can arrive out of order due to network conditions. Use `traceId` to deduplicate; treat `call_id` as the stable identity for your records. ## **Endpoint Settings** ### **Basic Requirements** * **HTTP Method**: POST * **Protocol**: HTTPS (required) * **Domain**: Custom domain (required; IP addresses not allowed) * **Content-Type**: application/json ### **Request Format** ```text theme={null} POST /your-webhook-endpoint HTTP/1.1 Content-Type: application/json User-Agent: ReactorNetty/1.1.13 X-Webhook-Event: CallHandler.CallEnded X-Webhook-Traceid: 94c950a0-1694-4b7c-9891-9364c261e4e1 X-Webhook-Timestamp: 2025-11-10T01:01:14.552985018Z ``` **Custom Headers:** * `X-Webhook-Event`: Event name (e.g., `CallHandler.CallEnded`) * `X-Webhook-Traceid`: Webhook unique identifier (same as `traceId` in the body) * `X-Webhook-Timestamp`: Timestamp in ISO 8601 format ## How to Configure Webhook in Verbex: 1. Open the Verbex **Dashboard**. Go to **Webhooks**. Hook1 Pn 2. Click **Add Webhook** and enter your HTTPS endpoint (domain URL). Hook2 Pn 3. Once the webhook endpoint is added, click on create webhook. That's how the endpoint is registered in verbex. ## **Webhook Data Format** ### **Call Started Event** ```json theme={null} { "traceId": "69ef5c43425e3c729ab8c83f", "organizationId": "27117463-c11e-4c75-affd-f743216f1bef", "payload": { "call_id": "69ef7c43425e3c729ab8c83f", "status": "success", "agent_id": "c51aa1b1-7eac-452d-8ba5-86a922d694e7" }, "eventName": "CallHandler.CallStarted", "event": "CallStarted", "timestamp": "2026-04-27T12:53:25.241195387Z" } ``` ### **Call Ended Event** ```json theme={null} { "traceId": "69ef5c43425e3c729ab8c83f", "organizationId": "27117463-c11e-4c75-affd-f743216f1bef", "payload": { "call_id": "62ef5c43425e3c729ab8c83f", "status": "success", "agent_id": "c31ab1b1-7eac-452d-8ba5-86a922d694e7" }, "eventName": "CallHandler.CallEnded", "event": "CallEnded", "timestamp": "2026-04-27T12:56:41.599271364Z" } ``` ### **PCA Completed Event** ```json theme={null} { "traceId": "69ef5c43425e3c729ab8c83f", "organizationId": "27117463-c11e-4c75-affd-f743216f1bef", "payload": { "reason": "success", "agent_id": "c51ab1b1-7eac-452d-8ba5-86a922d694e7", "call_id": "69ef5c43425e3c729ab8c83f", "status": "success", "timestamp": 1777294619200 }, "eventName": "callAnalysis.pcaCompleted", "event": "pcaCompleted", "timestamp": "2026-04-27T12:56:59.342041497Z" } ``` ### **Call Transfer Event** The Call Transfer event is triggered when the AI agent initiates a transfer of the call to a human agent or external destination. This event provides comprehensive details about the transfer attempt, including the transfer destination, call summary, and transcript. ```json theme={null} { "call_id": "697a020fc0baee039d0013b4", "agent_id": "d077dc85-ee45-48cd-ac65-fd49df53cdba", "status": "failed", "transfer_to": "sip:01751373839@115.127.146.155", "caller": { "phone_number": "+8801762668080" }, "call_summary": { "duration_seconds": 45.621591, "topics_discussed": [ "call_transfer_request" ], "actions_taken": [ "Acknowledged transfer request", "Initiated call transfer to human agent" ], "transfer_reason": "Customer requested to speak with a human agent.", "customer_sentiment": "neutral", "unresolved_issues": [] }, "transcript": [ { "role": "user", "content": "Hi, I need assistance with my account." }, { "role": "agent", "content": "How can I help you today?" }, { "role": "user", "content": "Okay. Can you transfer the call to a human agent?" }, { "role": "agent", "content": "Of course, I'll transfer you to a human agent now. Please hold on a moment." }, { "role": "agent", "content": "Please wait while we connect you to a human agent." } ], "metadata": { "call_start_time": "2026-01-28T12:33:37.475817+00:00", "call_end_time": "2026-01-28T12:34:23.097263+00:00", "language": "en-US" } } ``` ### Call Transfer Event Field Descriptions | Field | Type | Description | | :- | :- | :- | | `call_id` | string | Unique identifier for the call. Used as a stable identifier for your records. | | `agent_id` | string | Unique identifier for the AI agent handling the call. | | `status` | string | Transfer status. Values: `pending`, `initiated`, `success`, `failed`. Indicates whether the transfer was successfully completed or failed. | | `transfer_to` | string | Destination of the transfer. Can be a SIP address, phone number, or internal extension. | | `caller.phone_number` | string | Phone number of the caller initiating the call. | | `call_summary.duration_seconds` | number | Total duration of the call in seconds before transfer was initiated. | | `call_summary.topics_discussed` | array | List of topics discussed during the call. | | `call_summary.actions_taken` | array | List of actions performed by the AI agent during the call. | | `call_summary.transfer_reason` | string | Reason provided for initiating the transfer. | | `call_summary.customer_sentiment` | string | Overall sentiment of the customer. Values: `positive`, `neutral`, `negative`. | | `call_summary.unresolved_issues` | array | List of issues not resolved before transfer. | | `transcript` | array | Complete transcript of the call conversation. | | `transcript[].role` | string | Speaker in the transcript. Values: `user` or `agent`. | | `transcript[].content` | string | Content of the message spoken. | | `metadata.call_start_time` | string | ISO 8601 timestamp of when the call started. | | `metadata.call_end_time` | string | ISO 8601 timestamp of when the call ended or transfer was initiated. | | `metadata.language` | string | Language code of the call (e.g., "en-US"). | ## **Implementation Notes** **Important**: The webhook payload structure may change without notice. On the receiving side, please note the following: * It is recommended to store the entire payload received as JSON data. * Consider the possibility that new fields may be added. * Implement it so that unknown fields do not cause errors. ### **Call Transfer Event Implementation Notes** **Transfer Status Tracking:** Monitor the `status` field to determine if a transfer was successful. Failed transfers may require fallback handling or alerting. **Transfer Destination Validation:** Validate the `transfer_to` field format before routing. Ensure it matches your system's expected destination format (SIP URI, phone number, etc.). **Preserve Call Context:** Use `call_id` as the primary identifier to correlate this event with the original Call Started event for complete call lifecycle tracking. **Customer Sentiment Analysis:** Consider the `customer_sentiment` field when prioritizing transfers or determining escalation urgency. **Unresolved Issues:** Review the `unresolved_issues` array to ensure the receiving agent has context about what was not resolved. **Transcript Availability:** The complete `transcript` is included to help the receiving agent understand the conversation history and customer needs. **Typical Client Actions:** * Route call to the receiving agent using the `transfer_to` destination * Update CRM record with transfer status, reason, and customer sentiment * Send complete transcript and unresolved issues to the receiving agent * Track transfer success rates for quality assurance * Log transfer reason and customer sentiment for analytics ## **Field Descriptions** | **Field** | **Type** | **Description** | | :- | :- | :- | | `organizationId` | string | Organization ID | | `traceId` | string | Webhook unique identifier (used for deduplication) | | `eventName` | string | Event type | | `timestamp` | number | UNIX timestamp (seconds) | | `payload.call_id` | string | Call ID | | `payload.agent_id` | string | AI agent ID | | `payload.status` | string | Status | | `payload.reason` | string | Reason (PCA only) | | `payload.timestamp` | number | UNIX timestamp (milliseconds, PCA only) | # Webhook Subscription API Source: https://docs.verbex.ai/webhook-subscription-api Public API for managing webhook subscriptions. Use these endpoints to create, retrieve, update, and delete webhook subscriptions that deliver event notifications to your own HTTP endpoints. * **Base URL:** `https://api.verbex.ai/v1/public/webhook/subscription` * **Auth:** Bearer token (API key) in the `Authorization` header * **Content type:** `application/json` (for `POST` and `PUT`) **Response convention — null/unset fields are omitted.** Optional fields that have no value (e.g. `headers`, `description`, `agent_ids`, `workspace_ids`) are **left out of the response body entirely** rather than returned as `null`. Treat a missing key as "not set". The `… | null` notation in the tables below indicates such a field; in practice the key is simply absent when unset. *** ## Authentication Every request must include your API key as a Bearer token: ``` Authorization: Bearer ``` **Security note:** Your API key is a credential. Never commit it to source control, share it in tickets, or expose it client-side. If a key is ever exposed, rotate it immediately. *** ## Endpoints ### 1. Create a subscription **Description:** Registers a new webhook subscription so Verbex delivers selected event notifications to your endpoint as HTTP `POST` requests. Optionally scope it to specific agents or workspaces, filter the `events` it receives, and enable HMAC-signed delivery. Returns the created subscription — including a one-time signing `secret` when `enable_signed_webhooks` is `true`. Use that `secret` to verify the authenticity of incoming deliveries: Verbex signs each request (HMAC) so your endpoint can confirm it genuinely originated from Verbex and reject forged or tampered payloads. The `secret` (prefixed `whsec_`) is returned **only once** at creation, so store it securely; if it's lost or leaked, rotate it via the rotate-secret endpoint. **Using signed webhooks (client side):** on every delivery, verify the `X-Webhook-Signature` header with your stored `secret` before trusting the payload — see [Verifying webhook signatures (client side)](#verifying-webhook-signatures-client-side). **Method:** `POST /v1/public/webhook/subscription` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | | `Content-Type` | Yes | `application/json` | **Request Body** | Field | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | Display name for the subscription (non-blank; unique per organization). | | `url` | string | Yes | Destination endpoint that receives event POSTs. Must match `^https?://.*`. | | `active` | boolean | Yes | Whether deliveries are attempted (`true`) or paused (`false`). | | `enable_signed_webhooks` | boolean | Yes | HMAC signing toggle. Must be `true` or `false` (omitting it returns `400`). On create, `true` generates a `whsec_` signing secret returned **once** in the response; `false` creates an unsigned subscription. | | `events` | array of strings | No | Event types to subscribe to, each in the case-sensitive **`Service.Event`** pattern (e.g. `CallHandler.CallStarted`) — see [Event types](#event-types). An empty array or `["*"]` subscribes to **all** events. | | `headers` | object | No | Custom HTTP headers sent with each delivery (string→string map; e.g. auth tokens for your receiving endpoint). | | `description` | string | No | Free-text description (max 1500 chars). | | `agent_ids` | array of strings | No | Scope the subscription to specific agents (`scope = AGENT`). | | `workspace_ids` | array of strings | No | Scope the subscription to specific workspaces (`scope = WORKSPACE`). | **Response Body** | Field | Type | Description | | - | - | - | | `id` | string | Generated subscription ID. Required for GET / PUT / DELETE. | | `organization_id` | string | Owning organization (resolved from your API key). | | `scope` | string | Resolved delivery scope: `ORGANIZATION`, `WORKSPACE`, or `AGENT`. | | `created_user_id` | string | User that created the subscription (from your API key). | | `name` | string | Display name for the subscription. | | `url` | string | Destination endpoint that receives event POSTs. | | `events` | array of strings | Event types the subscription is subscribed to. | | `active` | boolean | Whether deliveries are attempted (`true`) or paused (`false`). | | `headers` | object \| null | Custom HTTP headers forwarded with each delivery; omitted when unset. | | `description` | string \| null | Free-text description; omitted when unset. | | `agent_ids` | array of strings \| null | Agent scope; omitted when unset. | | `workspace_ids` | array of strings \| null | Workspace scope; omitted when unset. | | `request_timeout_ms` | integer | Per-attempt delivery timeout in ms (default `1000`). | | `retry_policy` | object | Retry config (`retryStrategy`, `maxRetryAttempts`, `maxRetryDelayMs`). | | `signing_enabled` | boolean | Whether the subscription has a signing secret. Always present. | | `secret` | string | HMAC signing secret, prefixed `whsec_`. Present **only at issuance** when signing is enabled (create with `enable_signed_webhooks: true`). Omitted otherwise. | | `created_at` | string (ISO-8601) | Creation timestamp. | | `updated_at` | string (ISO-8601) | Last-update timestamp. | **`secret` is view-once.** It is returned in the response body **only at issuance** (create with signing on, a `PUT` that enables signing, or the rotate-secret endpoint) and is **never** returned by read endpoints (`GET` / list). Store it as soon as you receive it; if it's lost, obtain a new one via rotate-secret (the old one stays valid for a 72-hour grace window). **Sample Request** ```bash theme={null} curl -X 'POST' \ 'https://api.verbex.ai/v1/public/webhook/subscription' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{ "name": "Payment Events Webhook", "description": "Receives payment events with custom authentication", "url": "https://api.example.com/webhooks/payments", "active": true, "enable_signed_webhooks": true, "events": [], "headers": { "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" } }' ``` **Sample Response** — `201 Created` *(signed subscription; `secret` shown only here)* ```json theme={null} { "id": "6a27a76692d9e3a8ffd7e62d", "organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "scope": "ORGANIZATION", "created_user_id": "google-oauth2|101090478854418701727", "name": "Payment Events Webhook", "url": "https://api.example.com/webhooks/payments", "events": [], "active": true, "headers": { "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" }, "description": "Receives payment events with custom authentication", "request_timeout_ms": 1000, "retry_policy": { "retryStrategy": "FIXED_DELAY", "maxRetryAttempts": 3, "maxRetryDelayMs": 10000 }, "signing_enabled": true, "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "created_at": "2026-06-09T10:15:00.000Z", "updated_at": "2026-06-09T10:15:00.000Z" } ``` **Notes** * `headers` are forwarded on each delivery to your `url`. Use them to authenticate Verbex → your endpoint (this `Authorization` is *your* receiver's token, separate from the API key used to call this API). * The response returns the created subscription, including its generated `id`. Save that `id` — it's required for GET / PUT / DELETE. *** ### 2. Update a subscription **Description:** Replaces the full configuration of an existing subscription (full-replacement `PUT` semantics — send every field you want to keep, or it may be cleared/reset). The required `enable_signed_webhooks` also drives the signing lifecycle (enable or disable signing). Returns the updated subscription — including a **new** one-time signing `secret` only if this call just *enabled* signing on a previously-unsigned subscription. **Method:** `PUT /v1/public/webhook/subscription/{id}` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | | `Content-Type` | Yes | `application/json` | **Path parameters** | Parameter | Description | | - | - | | `id` | The subscription ID to update. | **Request Body** | Field | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | Display name for the subscription (non-blank; unique per organization). | | `url` | string | Yes | Destination endpoint that receives event POSTs. Must match `^https?://.*`. | | `active` | boolean | Yes | Whether deliveries are attempted (`true`) or paused (`false`). | | `enable_signed_webhooks` | boolean | Yes | HMAC signing toggle, and the signing-lifecycle control on update (see table below). Must be `true` or `false`. | | `events` | array of strings | No | Event types to subscribe to, each in the case-sensitive **`Service.Event`** pattern (e.g. `CallHandler.CallStarted`) — see [Event types](#event-types). An empty array or `["*"]` subscribes to **all** events. | | `headers` | object | No | Custom HTTP headers sent with each delivery (string→string map). | | `description` | string | No | Free-text description (max 1500 chars). | | `agent_ids` | array of strings | No | Scope the subscription to specific agents (`scope = AGENT`). | | `workspace_ids` | array of strings | No | Scope the subscription to specific workspaces (`scope = WORKSPACE`). | **Response Body** | Field | Type | Description | | - | - | - | | `id` | string | Subscription ID. | | `organization_id` | string | Owning organization (resolved from your API key). | | `scope` | string | Resolved delivery scope: `ORGANIZATION`, `WORKSPACE`, or `AGENT`. | | `created_user_id` | string | User that created the subscription. | | `name` | string | Display name for the subscription. | | `url` | string | Destination endpoint that receives event POSTs. | | `events` | array of strings | Event types the subscription is subscribed to. | | `active` | boolean | Whether deliveries are attempted (`true`) or paused (`false`). | | `headers` | object \| null | Custom HTTP headers forwarded with each delivery; omitted when unset. | | `description` | string \| null | Free-text description; omitted when unset. | | `agent_ids` | array of strings \| null | Agent scope; omitted when unset. | | `workspace_ids` | array of strings \| null | Workspace scope; omitted when unset. | | `request_timeout_ms` | integer | Per-attempt delivery timeout in ms (default `1000`). | | `retry_policy` | object | Retry config (`retryStrategy`, `maxRetryAttempts`, `maxRetryDelayMs`). | | `signing_enabled` | boolean | Whether the subscription has a signing secret. Always present. | | `secret` | string | HMAC signing secret, prefixed `whsec_`. Returned **only** if this update just *enabled* signing on a previously-unsigned subscription. Omitted otherwise. | | `created_at` | string (ISO-8601) | Creation timestamp. | | `updated_at` | string (ISO-8601) | Last-update timestamp. | **Signing lifecycle on update** (`enable_signed_webhooks`): | Value | Effect | | - | - | | `true` on an unsigned subscription | Enables signing and returns a **new** `secret` once in the response. | | `true` on an already-signed subscription | No-op (secret unchanged, not returned). To replace the secret, use [rotate-secret](#3-rotate-the-signing-secret). | | `false` on a signed subscription | Disables signing and **clears the secret irrecoverably** (response shows `signing_enabled: false`, no `secret`). | **Sample Request** ```bash theme={null} curl -X 'PUT' \ 'https://api.verbex.ai/v1/public/webhook/subscription/6a27a76692d9e3a8ffd7e62d' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -d '{ "name": "Payment Events Webhook", "description": "Receives payment events with custom authentication", "url": "https://api.example2.com/webhooks/payments", "active": true, "enable_signed_webhooks": true, "events": [], "headers": { "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" } }' ``` **Sample Response** — `200 OK` *(signing already enabled, so no `secret` returned)* ```json theme={null} { "id": "6a27a76692d9e3a8ffd7e62d", "organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "scope": "ORGANIZATION", "created_user_id": "google-oauth2|101090478854418701727", "name": "Payment Events Webhook", "url": "https://api.example2.com/webhooks/payments", "events": [], "active": true, "headers": { "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" }, "description": "Receives payment events with custom authentication", "request_timeout_ms": 1000, "retry_policy": { "retryStrategy": "FIXED_DELAY", "maxRetryAttempts": 3, "maxRetryDelayMs": 10000 }, "signing_enabled": true, "created_at": "2026-06-09T10:15:00.000Z", "updated_at": "2026-06-09T11:42:00.000Z" } ``` **Notes** * This is a full replacement (`PUT` semantics). Include every field you want to keep, or it may be cleared/reset. * `updated_at` changes on each successful update; `created_at` stays fixed. *** ### 3. Rotate the signing secret **Description:** Generates a **new** signing `secret` for a subscription while keeping the **previous** secret valid for a **72-hour** grace window, so in-flight receivers don't break. During that window Verbex signs each delivery with **both** secrets (two `v1=` values in `X-Webhook-Signature`), so a receiver still using the old secret keeps verifying until it switches to the new one. The new `secret` is returned **once** in this response — store it immediately. **Method:** `POST /v1/public/webhook/subscription/{id}/rotate/secret` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | No request body. **Path parameters** | Parameter | Description | | - | - | | `id` | The subscription ID whose secret to rotate. | **Response Body** Returns **only** the two rotation fields — not the full subscription object: | Field | Type | Description | | - | - | - | | `secret` | string | The **new** signing secret (`whsec_…`), returned **once**. | | `previous_secret_expires_at` | string (ISO-8601) | When the previous secret stops being accepted (rotation time + 72h). The prior secret value itself is **not** returned — you already have it. | The response does **not** include `id`, `signing_enabled`, or any other subscription fields. To read the rest of the subscription after rotating, call [Get a subscription](#5-get-a-subscription). **Sample Request** ```bash theme={null} curl -X 'POST' \ 'https://api.verbex.ai/v1/public/webhook/subscription/6a27a76692d9e3a8ffd7e62d/rotate/secret' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' ``` **Sample Response** — `200 OK` ```json theme={null} { "secret": "whsec_NEWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "previous_secret_expires_at": "2026-06-12T10:15:00.000Z" } ``` **Notes** * Returns `409 Conflict` if the subscription was created without signing enabled (no secret to rotate — re-create or `PUT` with `enable_signed_webhooks: true` first). * Update your stored secret to the new value before the previous one expires; after the 72-hour window the old secret is rejected. *** ### 4. Delete a subscription **Description:** Permanently deletes a subscription; Verbex stops delivering its events. This cannot be undone — to temporarily stop deliveries instead, set `active: false` via [Update](#2-update-a-subscription). **Method:** `DELETE /v1/public/webhook/subscription/{id}` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | No request body. **Path parameters** | Parameter | Description | | - | - | | `id` | The subscription ID to delete. | **Response** — `204 No Content` (empty body). **Sample Request** ```bash theme={null} curl -X 'DELETE' \ 'https://api.verbex.ai/v1/public/webhook/subscription/6a27a76692d9e3a8ffd7e62d' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' ``` **Sample Response** — `204 No Content` (empty body). **Notes** * Returns `404 Not Found` if no subscription exists for the `id`. * To pause deliveries without deleting, `PUT` with `"active": false` — this preserves the subscription and its `id`. *** ### 5. Get a subscription **Description:** Retrieves a single subscription by its ID. Read endpoints never return the signing `secret` — use `signing_enabled` to tell whether signing is on. **Method:** `GET /v1/public/webhook/subscription/{id}` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | No request body. **Path parameters** | Parameter | Description | | - | - | | `id` | The subscription ID returned at creation. | **Response Body** | Field | Type | Description | | - | - | - | | `id` | string | Subscription ID. | | `organization_id` | string | Owning organization. | | `scope` | string | `ORGANIZATION`, `WORKSPACE`, or `AGENT`. | | `created_user_id` | string | User that created the subscription. | | `name` | string | Display name. | | `url` | string | Destination endpoint. | | `events` | array of strings | Subscribed event types. | | `active` | boolean | Whether deliveries are attempted. | | `headers` | object \| null | Custom delivery headers; omitted when unset. | | `description` | string \| null | Free-text description; omitted when unset. | | `agent_ids` | array of strings \| null | Agent scope; omitted when unset. | | `workspace_ids` | array of strings \| null | Workspace scope; omitted when unset. | | `request_timeout_ms` | integer | Per-attempt delivery timeout (default `1000`). | | `retry_policy` | object | Retry config (`retryStrategy`, `maxRetryAttempts`, `maxRetryDelayMs`). | | `signing_enabled` | boolean | Whether signing is on. (`secret` is **never** returned by reads.) | | `created_at` | string (ISO-8601) | Creation timestamp. | | `updated_at` | string (ISO-8601) | Last-update timestamp. | **Sample Request** ```bash theme={null} curl -X 'GET' \ 'https://api.verbex.ai/v1/public/webhook/subscription/6a27a76692d9e3a8ffd7e62d' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' ``` **Sample Response** — `200 OK` *(no `secret`)* ```json theme={null} { "id": "6a27a76692d9e3a8ffd7e62d", "organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "scope": "ORGANIZATION", "created_user_id": "google-oauth2|101090478854418701727", "name": "Payment Events Webhook", "url": "https://api.example.com/webhooks/payments", "events": [], "active": true, "headers": { "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" }, "description": "Receives payment events with custom authentication", "request_timeout_ms": 1000, "retry_policy": { "retryStrategy": "FIXED_DELAY", "maxRetryAttempts": 3, "maxRetryDelayMs": 10000 }, "signing_enabled": true, "created_at": "2026-06-09T10:15:00.000Z", "updated_at": "2026-06-09T10:15:00.000Z" } ``` **Notes** * Returns `404 Not Found` if no subscription exists for the `id`. *** ### 6. List subscriptions **Description:** Lists the subscriptions in your organization (cursor-paginated). Note the **plural** `subscriptions` path — distinct from the singular get-by-id. `secret` is never included. **Method:** `GET /v1/public/webhook/subscriptions` **Headers** | Header | Required | Value | | - | - | - | | `Authorization` | Yes | `Bearer ` | No request body. **Query parameters** | Parameter | Required | Description | | - | - | - | | `page_size` | Yes | Max items per page, `1`–`100`. Omitting it returns `400`; a value `> 100` returns `400 — "Page size cannot exceed 100"`. | | `page_token` | No | Cursor from a previous response's `next_page_token`; omit for the first page. | **Response Body** | Field | Type | Description | | - | - | - | | `data` | array | Page of subscription objects, each the same shape as the [get response](#5-get-a-subscription) (no `secret`). | | `next_page_token` | string \| null | Cursor for the next page; `null` on the last page. | | `total_count` | integer | Total subscriptions matching the query. | **Sample Request** ```bash theme={null} curl -X 'GET' \ 'https://api.verbex.ai/v1/public/webhook/subscriptions?page_size=20' \ -H 'accept: */*' \ -H 'Authorization: Bearer ' ``` **Sample Response** — `200 OK` ```json theme={null} { "data": [ { "id": "6a27a76692d9e3a8ffd7e62d", "organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "scope": "ORGANIZATION", "created_user_id": "google-oauth2|101090478854418701727", "name": "Payment Events Webhook", "url": "https://api.example.com/webhooks/payments", "events": [], "active": true, "request_timeout_ms": 1000, "retry_policy": { "retryStrategy": "FIXED_DELAY", "maxRetryAttempts": 3, "maxRetryDelayMs": 10000 }, "signing_enabled": true, "created_at": "2026-06-09T10:15:00.000Z", "updated_at": "2026-06-09T10:15:00.000Z" } ], "next_page_token": null, "total_count": 1 } ``` Each `data` item has the same shape as the [get response](#5-get-a-subscription) (no `secret`). *** ## Event types Values for the `events` array use the **`Service.Event`** pattern — the service name and event name joined by a dot (e.g. `CallHandler.CallStarted`). Names are **case-sensitive**; use them exactly as listed below (note `CallHandler` is PascalCase, `callAnalysis` is lower-camelCase). A bare event name without its service prefix (e.g. `CallStarted`) is rejected with `400 — Event type '…' does not exist`. Currently subscribable: | Event | Description | Sample payload | | - | - | - | | `CallHandler.CallStarted` | Triggered when a call is initiated. | `{"call_id": "69ef5c4...3c729ab8c83f", "status": "success", "agent_id": "c51ab1b1-...-86a922d694e7"}` | | `CallHandler.CallEnded` | Triggered when a call is ended. | `{"call_id": "69ef5c43...29ab8c83f", "status": "success", "agent_id": "c51ab1b1-...-86a922d694e7"}` | | `callAnalysis.pcaCompleted` | Triggered when post-call analysis (PCA) completes. | `{"call_id": "698820c3...28d6b98c63", "agent_id": "285aef8f-...-3573855ed4a0", "status": "success", "reason": "success", "analysisTimestamp": 1770529007989}` | **Notes** * An empty array (`[]`) or `["*"]` subscribes to **all** subscribable event types. * Some event types exist but are **internal-only** and cannot be subscribed to via public webhooks — subscribing to them returns `400 — Event type '…' is internal-only and cannot be subscribed to via public webhooks` (e.g. `CallHandler.AnsweringMachineDetected`). *** ## Event Delivery Every delivery is an HTTP `POST` to your subscription `url` with a JSON body in the following **envelope**. The event-specific data lives under `payload`; the surrounding fields are the same for every event type. Test deliveries use the identical envelope (the only difference is `payload` comes from the event type's sample payload and `traceId` is prefixed `test-`). **Envelope fields** | Field | Type | Description | | - | - | - | | `eventName` | string | The full event type in `Service.Event` form (e.g. `CallHandler.CallStarted`). **⚠️ Deprecated** — being phased out and will be **removed** once consumers migrate to `event`. Prefer `event` for new integrations. | | `event` | string | The event name without its service prefix (e.g. `CallStarted`). **Going-forward field** — use this instead of `eventName`. | | `traceId` | string | Correlation/trace ID for this delivery (also sent as the `X-Webhook-TraceId` header). | | `timestamp` | string (ISO-8601) | When the event was produced. | | `organizationId` | string | The organization the event belongs to. | | `payload` | object | The event-specific body — see the [Event types](#event-types) table for the shape per event (e.g. `call_id`, `agent_id`, `status`). | **Sample delivery — `CallHandler.CallStarted`** ```json theme={null} { "eventName": "CallHandler.CallStarted", "event": "CallStarted", "traceId": "9f1c2e7a-...-b3d4", "timestamp": "2026-06-09T10:15:00.000Z", "organizationId": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "payload": { "call_id": "69ef5c4...3c729ab8c83f", "status": "success", "agent_id": "c51ab1b1-...-86a922d694e7" } } ``` **Sample delivery — `callAnalysis.pcaCompleted`** ```json theme={null} { "eventName": "callAnalysis.pcaCompleted", "event": "pcaCompleted", "traceId": "9f1c2e7a-...-b3d4", "timestamp": "2026-06-09T10:15:00.000Z", "organizationId": "ddd6f1d8-b232-497e-bf1e-ea7317622d17", "payload": { "call_id": "698820c3...28d6b98c63", "agent_id": "285aef8f-...-3573855ed4a0", "status": "success", "reason": "success", "analysisTimestamp": 1770529007989 } } ``` **Delivery headers** | Header | Always sent | Description | | - | - | - | | `Content-Type` | Yes | `application/json`. | | `X-Webhook-Event` | Yes | The full event type, in `Service.Event` form (e.g. `CallHandler.CallStarted`) — same value as the body's `eventName`. Routing hint. | | `X-Webhook-TraceId` | Yes | Correlation/trace ID for this delivery — same value as the body's `traceId`. | | `X-Webhook-Timestamp` | Yes | Event timestamp as an **ISO-8601 string** (e.g. `2026-06-09T10:15:00Z`) — same value as the body's `timestamp`. | | `X-Webhook-Signature` | Only when signed | HMAC signature, format `t=,v1=[,v1=]`. Present only if the subscription has signing enabled. See [Verifying webhook signatures](#verifying-webhook-signatures-client-side). | | *custom headers* | If configured | Any `headers` you set on the subscription are forwarded as-is. | `X-Webhook-Event`, `X-Webhook-TraceId`, and `X-Webhook-Timestamp` are routing hints and are **not** covered by the HMAC signature — do not rely on them for security. Only the raw request **body** and the `t` value *inside* `X-Webhook-Signature` are signed. **Note:** `t` (inside `X-Webhook-Signature`) is a **Unix epoch-seconds** integer and is what the replay check uses; the separate `X-Webhook-Timestamp` header is an **ISO-8601 string**. They are different formats and values — don't conflate them. ### Stable vs. optional fields Verbex maintains **backward compatibility**: the fields below remain stable, and new optional fields may be **added** over time. Your receiver should **tolerate unknown fields** rather than strictly validate the whole body. **Stable — safe to rely on:** * `event` * `traceId` * `timestamp` * `organizationId` * `payload.call_id` * `payload.agent_id` * `payload.status` **`eventName` is deprecated** and will be **removed** in a future version — migrate to the `event` field. It is still sent today for backward compatibility, but do not build new integrations on it. **Optional / may change or be added later:** additional `payload` fields (e.g. `reason`, `analysisTimestamp`, and event-specific extras), and any future top-level fields. Webhook subscription changes, including deletion, may take up to **10 minutes** to fully propagate due to internal caching. *** ## Verifying webhook signatures (client side) When `enable_signed_webhooks` is `true`, every delivery carries an `X-Webhook-Signature` header. Verify it before trusting the payload. **Header format** ``` X-Webhook-Signature: t=,v1=[,v1=] ``` * `t` — Unix timestamp (seconds) when the delivery was signed. * `v1` — lowercase hex HMAC-SHA256. During the **72-hour grace window after a secret rotation**, two `v1=` values are sent (new secret first, then previous) — accept the request if **either** matches. **What is signed:** the raw request body, a literal `.`, then `t`: ``` signed_payload = + "." + ``` **Key:** use the full `whsec_…` secret string exactly as returned, as UTF-8 bytes. Do **not** strip the `whsec_` prefix and do **not** base64-decode it. **Steps** 1. Parse `t` and all `v1` values from `X-Webhook-Signature`. 2. Reject if `|now − t| > 300` seconds (replay protection). 3. Compute `expected = hex(HMAC_SHA256(secret, raw_body + "." + t))`. 4. Accept if `expected` equals **any** `v1` (use a constant-time comparison). 5. Don't rely on `X-Webhook-Event`, `X-Webhook-TraceId`, or `X-Webhook-Timestamp` for security — they are routing hints and are **not** covered by the signature. Verify against the **raw** request body bytes exactly as received. Parsing then re-serializing the JSON will change the bytes and break the signature. **Node.js (Express)** ```js theme={null} const crypto = require("crypto"); function verifyWebhook(rawBody, sigHeader, secret, toleranceSec = 300) { let t; const sigs = []; for (const seg of sigHeader.split(",")) { const i = seg.indexOf("="); const k = seg.slice(0, i), v = seg.slice(i + 1); if (k === "t") t = parseInt(v, 10); else if (k === "v1") sigs.push(v); } if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; const expected = crypto .createHmac("sha256", secret) // secret includes the whsec_ prefix .update(`${rawBody}.${t}`) .digest("hex"); return sigs.some( (s) => s.length === expected.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)) ); } // Capture the RAW body so the bytes are unchanged app.use(express.raw({ type: "application/json" })); app.post("/webhooks", (req, res) => { const raw = req.body.toString("utf8"); if (!verifyWebhook(raw, req.get("X-Webhook-Signature"), process.env.WEBHOOK_SECRET)) { return res.sendStatus(401); } const event = JSON.parse(raw); // ... handle event ... res.sendStatus(200); }); ``` **Python (Flask)** ```python theme={null} import hmac, hashlib, time def verify_webhook(raw_body: bytes, sig_header: str, secret: str, tolerance: int = 300) -> bool: t, sigs = None, [] for seg in sig_header.split(","): k, _, v = seg.partition("=") if k == "t": t = int(v) elif k == "v1": sigs.append(v) if t is None or abs(time.time() - t) > tolerance: return False expected = hmac.new( secret.encode("utf-8"), # full whsec_... string raw_body + b"." + str(t).encode("utf-8"), hashlib.sha256, ).hexdigest() return any(hmac.compare_digest(expected, s) for s in sigs) # Flask: request.get_data() returns the raw bytes # ok = verify_webhook(request.get_data(), request.headers["X-Webhook-Signature"], WEBHOOK_SECRET) ``` *** ## Error responses Errors are returned with a non-`2xx` status code and this JSON body: ```json theme={null} { "status": 400, "type": "VALIDATION_ERROR", "message": "Validation failed", "details": { "fields": { "enableSignedWebhooks": "enable_signed_webhooks is required (true or false)" } }, "timestamp": "2026-06-24T13:24:36.078Z", "path": "/v1/public/webhook/subscription", "trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3" } ``` | Field | Description | | - | - | | `status` | HTTP status code. | | `type` | Machine-readable error type (e.g. `VALIDATION_ERROR`). | | `message` | Human-readable summary. | | `details` | Optional structured detail (e.g. `fields` → per-field validation messages). | | `timestamp` / `path` / `trace_id` | When/where it happened and a correlation ID for support. | **Authentication errors use a different shape.** The schema above is returned by the webhook service for application-level errors (`400`, `404`, `409`, `500`). Authentication failures rejected at the API gateway (`401`) return a **leaner body with only `error`, `message`, and a camelCase `traceId`** — no `status`, `type`, `path`, or `timestamp`: ```json theme={null} { "error": "Authentication", "message": "Authentication failed", "traceId": "e679120f-1d1c-41d2-947c-34e194d5a4a1" } ``` The `message` text is informational (e.g. `"Authentication failed"` for an invalid token, `"Authentication failure"` when the `Authorization` header is missing). Note `traceId` is **camelCase** here, unlike the snake\_case `trace_id` on service-level errors. Parse error bodies defensively: rely on the HTTP status code, and treat `status`/`type`/`path`/`trace_id` as present only on service-level errors. | Status | Meaning | | - | - | | `400 Bad Request` | Malformed JSON or invalid/missing fields (e.g. missing `enable_signed_webhooks`, invalid `url`). | | `401 Unauthorized` | Missing or invalid `Authorization` Bearer token. Returned by the gateway in the leaner shape above (`error`, `message`, camelCase `traceId` only). | | `403 Forbidden` | Token is valid but not permitted for this resource. | | `404 Not Found` | No subscription exists for the given `id`. | | `409 Conflict` | Duplicate `name` (unique per organization), or rotate-secret on a subscription without signing enabled. | | `429 Too Many Requests` | Rate limit exceeded. | | `500 Internal Server Error` | Unexpected server-side failure. | *** ## Quick reference | Action | Method | Path | Body | Success | | - | - | - | - | - | | Create | `POST` | `/v1/public/webhook/subscription` | Yes | `201` | | Read | `GET` | `/v1/public/webhook/subscription/{id}` | No | `200` | | Update | `PUT` | `/v1/public/webhook/subscription/{id}` | Yes | `200` | | Delete | `DELETE` | `/v1/public/webhook/subscription/{id}` | No | `204` | | List | `GET` | `/v1/public/webhook/subscriptions` | No | `200` | | Rotate secret | `POST` | `/v1/public/webhook/subscription/{id}/rotate/secret` | No | `200` | *** ## Common headers | Header | Used on | Value | | - | - | - | | `Authorization` | All requests | `Bearer ` | | `Content-Type` | POST, PUT | `application/json` | | `accept` | All requests | `*/*` | *** ## Tips * **`events: []`** — an empty array (or `["*"]`) subscribes to **all** event types. To receive only specific events, list them explicitly (see [Event types](#event-types)). * **Verify delivery** — your `url` should respond `2xx` quickly. Use the `headers` field to let your receiver authenticate inbound calls. * **Pause vs. delete** — to temporarily stop deliveries, `PUT` with `"active": false` rather than deleting; this preserves the subscription and its ID. # Workspace Source: https://docs.verbex.ai/workspace A Workspace is an isolated project environment in Verbex that enables team collaboration and resource management. Each workspace maintains its own set of agents, phone numbers, users, and allocated minutes, providing a secure and organized way to manage different projects or teams within your organization. Every workspace contains: * **Agents**: Voice AI agents specific to the workspace * **Phone Numbers**: Dedicated numbers mapped to workspace agents * **Users**: Team members with defined roles and permissions * **Minutes**: Allocated calling minutes for the workspace * **Knowledge Bases**: Connected (not created) knowledge resources   ## **Default Workspace** Every account starts with **My Workspace**, which serves as: * The owner's personal/default workspace * The only location where Knowledge Bases can be created * The central hub for managing other workspaces Ws Pn ## **Workspace Isolation** Resources are strictly isolated between workspaces: * Agent and phone number lists change when switching workspaces * Minutes are allocated per workspace * Users have workspace-specific access * Knowledge Bases are centrally managed but can be connected per workspace ## **User Roles** ### **Owner** The workspace owner (administrator) can: * Create new workspaces * Allocate minutes to workspaces * Create Knowledge Bases (only in My Workspace) * Invite members to workspaces * Access all workspace features Ws Owner Pn ### **Member** Workspace members (restricted users) can: * Access assigned workspaces * Create and manage agents within the workspace * Connect existing Knowledge Bases to agents * Use allocated workspace minutes * Cannot create new Knowledge Bases or workspaces ## **Creating a Workspace** **Prerequisites**: You must be a workspace owner to create new workspaces. ### **Steps** 1. Navigate to **My Workspace** → **Workspaces** 2. Click **Create New Workspace** 3. Enter a workspace name 4. Click **Create** Createws1 Pn Createws2 Pn ### **Result** * A new workspace card appears in your workspace list * The workspace becomes available in the top navigation bar switcher * The workspace is ready for configuration and team invitations Wsview Pn ## **Managing Minutes** ### **Allocating Minutes to a Workspace** **Note**: Only workspace owners can allocate minutes. 1. Switch to the target workspace using the top bar selector 2. Navigate to **Minute Allocation** → **Distribute Minutes** 3. Configure the allocation: * Select the subscription source * Set the number of **Minutes** * Define **Cost per Minute** * Configure **Pulse** settings * Select **Currency** 4. Click **Allocate** Wsallocation Pn ### **Tracking Usage** * **Remaining Minutes**: Displayed in the workspace dashboard Trackwsallocation Pn * **Allocation History**: Complete transaction log of minute distributions Allocationhistory Pn * **Usage Reports**: Track consumption per workspace  Usage Pn     ## **Team Management** ### **Inviting Members** 1. Navigate to the target workspace 2. Go to **Workspace Users** → **Invite Member** 3. Enter the member's email address 4. Click **Send Invitation** Wsinv Pn Invmail Pn Acceptinv Pn ### **Member Permissions** Members automatically receive: * Access to the specific workspace * Ability to create and manage agents * Permission to connect Knowledge Bases * Usage rights for allocated minutes # Workspace Knowledge Base Management Source: https://docs.verbex.ai/workspace_kb_access The Knowledge Base system follows a centralized management model that ensures consistency while providing flexibility for workspace-specific implementations. # Architecture ## **Knowledge Base management follows a centralized model:** **My Workspace (Owner's Default)** ├── Create Knowledge Bases ✓ ├── Manage KB Content ✓ └── Central KB Repository ✓ **Created Workspaces** ├── Create Knowledge Bases ✗ ├── Connect Existing KBs ✓ └── Use Connected KBs ✓ ## **Workspace Management Flow** Untitled diagram-2025-10-28-043153.png ## **Key Principles** 1. **Single Source of Truth**: All Knowledge Bases are created and maintained in one location 2. **Workspace Agnostic**: Once created, KBs can be used across any workspace 3. **Owner Controlled**: Only workspace owners can create and modify Knowledge Bases 4. **Member Accessible**: All workspace members can connect KBs to their agents ## **Creating Knowledge Bases** ### **Prerequisites** * You must be a **Workspace Owner** * You must be in **My Workspace** (not in a created workspace) ### **Step-by-Step Creation** 1. **Navigate to My Workspace** Top Navigation Bar → Workspace Selector → My Workspace 2. **Access Knowledge Base Section** Main Menu → Knowledge Bases → Create New 3. **Configure Knowledge Base** * **Name**: Descriptive identifier for the KB * **Description**: Purpose and content overview 4. **Add Content** * Upload documents (MD, PDF, DOCX, TXT) * Add Q\&A pairs manually * Import from external sources (Web URL) 5. **Save and Process** ## **Content Types** | **Format** | **Description** | **Best For** | | :- | :- | :- | | MD | Markdown | Best for all purposes | | PDF | Portable documents | Manuals, guides, reports | | DOCX | Word documents | Policies, procedures | | TXT | Plain text files | Simple FAQs, lists | | URL | Web content | Live documentation, wikis | ## **Connecting Knowledge Bases to Agents** **Within Created Workspaces** When working in any created workspace (not My Workspace): 1. **Create or Edit an Agent** 2. Workspace → Agents → Create/Edit Agent 3. **Navigate to Knowledge Base Section** 4. Agent Configuration → Knowledge Base → Connect KB 5. **Select from Available KBs** * View list of all KBs created by the owner * Select and add the KB to agent 6. **Save Agent Configuration** ## **Managing Knowledge Base Content** **Updating Content** 1. **Access My Workspace** 2. **Navigate to Knowledge Bases** 3. **Select the KB to update** 4. **Add a file to KB** ## **Access Control and Permissions** | **Action** | **Owner (My Workspace)** | **Owner (Created Workspace)** | **Member (Any Workspace)** | | :- | :- | :- | :- | | Create KB | ✅ | ❌ | ❌ | | Edit KB | ✅ | ❌ | ❌ | | Delete KB | ✅ | ❌ | ❌ | | View KB List | ✅ | ✅ | ✅ | | Connect KB to Agent | ✅ | ✅ | ✅ | | Disconnect KB | ✅ | ✅ | ✅ |