Skip to content

Bot Builder — Complete Guide

The definitive, scenario-driven guide to ConnectGain's visual Bot Builder (/flows). It covers every node type, every trigger, variables, the pause/resume model, AI/RAG, deployment, testing, troubleshooting, and full worked examples.

New here? Skim ConceptsThe builder UITriggers, then jump to the node you need or to End-to-end scenarios.

Backward compatibility promise: the builder is versioned additively. New node types, triggers, and fields are always optional. Flows you built in older versions keep running unchanged — nothing in this guide requires you to rebuild an existing flow.


Table of contents

  1. Concepts
  2. The builder UI
  3. Triggers — starting a flow
  4. Variables & dynamic text
  5. Pause / resume (waiting for the user)
  6. Node reference
  7. Messaging · Logic · AI & RAG · Data · CRM & conversation
  8. Multilingual flows
  9. Deploying, activating & publishing
  10. Testing & debugging
  11. End-to-end scenarios
  12. Best practices
  13. Troubleshooting

1. Concepts

Term Meaning
Flow A chatbot/automation graph. Lives in bot_flows; has a status of Draft or Published.
Node One step (send a message, branch, call an API, create a deal…). 37 types across 6 categories.
Edge A connection from one node's output handle to another node's input. Defines execution order/branches.
Trigger node The required entry point. Defines what event starts the flow and which channel it listens to.
Session Per-conversation state (bot_sessions) holding variables and the current pause point.
Variable A named value in the session ({{name}}). Set by inputs, API calls, AI, or Set Variable.
Deployment Publishing compiles the flow to an n8n workflow and activates its webhook. The runtime is n8n.

How a flow actually runs: an inbound message hits a channel webhook (WhatsApp, Messenger, …) → ConnectGain POSTs the event to the flow's n8n webhook → n8n executes node-by-node → node actions (sending messages, CRM writes) call back into ConnectGain edge functions. A flow only runs when it is Published and its n8n workflow is active.


2. The builder UI

  • Canvas — drag-and-drop, zoom/pan, snap-to-grid. Connect nodes by dragging from a node's output handle to another node's input.
  • Add-node palette — grouped by category (Triggers, Messaging, AI & RAG, Logic, Data, CRM). Each node shows an icon + one-line description.
  • Node inspector — click a node to configure it. The inspector also lists available variables from upstream nodes (computed by walking the edge graph backwards).
  • Node search / jump — quickly find and focus a node in large flows.
  • Flow settings — name, description, status.
  • Deploy / Publish — compiles to n8n and activates. Undeploy removes it from n8n.
  • Test — sample-webhook tester + preview.
  • Flows list paginates at 50 per page.

3. Triggers — starting a flow

Every flow needs at least one Trigger node. Configure its event and (for message events) a channel filter.

Trigger events

Conversation & messaging - message.received — inbound customer message (the most common trigger) - message.sent — an outbound message was sent - conversation.created / conversation.assigned / conversation.status.changed - Broadcast Response (broadcast.response) — the contact replied within 72h of receiving a campaign. Payload carries campaign_id, campaign_name. - Manual Shortcut (manual.shortcut) — an agent launches the flow from the inbox ⚡ Shortcuts menu.

Contact - contact.created / contact.assigned - contact.updated — any contact edit. Set the optional Field to watch (e.g. lead_score) to fire only when that field changes (Field Updated). - Tag Updated (contact.tag.updated) — contact tags changed. - Lifecycle Updated (contact.lifecycle.updated) — the contact's lifecycle stage changed.

Deals & tasks - deal.created / deal.stage.changed / deal.updated / deal.assigned - task.created / task.updated / task.completed / task.overdue

Other - Call Ended (call.ended) — a call recording arrived (carries call id, contact, duration). - Incoming Webhook (HTTP POST) · Zoom Recording Completed (zoom.recording.completed)

Channel filtering (message triggers)

  • Channelall, or one of WHATSAPP_LITE, WHATSAPP_CLOUD, FB_MESSENGER, INSTAGRAM, TELEGRAM, TIKTOK, SHOPIFY_INBOX, BULK_EMAIL, LINKEDIN.
  • Channel account — pin to one connected account (e.g. only "Pullman WA Cloud"), or all. Prevents a flow meant for one number firing on another.

Multiple triggers in one flow

Add several Trigger nodes to a single flow and each starts its own branch from the same webhook; events are routed to the matching branch by event type. Use this to share setup (variables, lookups) across related events.

Inbox Shortcuts (agent-launched)

Build a flow with a Manual Shortcut trigger and publish it. A ⚡ Shortcuts menu appears in the inbox conversation header; selecting your flow runs it for the current conversation, passing the conversation/contact context. The webhook URL is never exposed to the browser — launches go through the org-validated trigger-shortcut-flow endpoint.


4. Variables & dynamic text

Reference any session value in any text field with handlebars: {{variable}} or dot-paths {{contact.first_name}}.

Where variables come from - The trigger payload: {{message.text}}, {{contact.id}}, {{contact.first_name}}, {{contact.phone}}, {{conversation.id}} - Collect Input / Quick Reply (collect mode) — the user's answer - Set Variable, HTTP Request (responseVariable), Database Query/Memory (outputVariable), AI Response (response), AI Agent (agentResponse)

Rules to remember - Missing variable → the literal {{token}} is left unchanged (never blanked). This is what makes interpolation safe to add to old flows. - Dot-paths are static{{order.id}} works; nested/dynamic keys like {{texts.{{lang}}.greeting}} do not. Compute the final flat value first (Set Variable / Database Query), then reference it. - Numeric helper: {{counter}} + 1 increments in text fields.

Dates & the current time

There is no generic {{now}} text variable — flows can't stamp the current date into an arbitrary message field. Use one of these instead:

  • Resolve relative dates from what the user says → use the AI Agent. The AI Agent (and RAG agent) are automatically given the real current date/time at run time, so "book me in tomorrow at 3 PM", "next Monday", "this Friday at 10 AM" resolve to a correct absolute ISO 8601 datetime you can pass to the Scheduler. Set the agent's Timezone (for dates) field to your local IANA zone (e.g. Africa/Cairo) so relative dates land on the correct local day. This is injected at Publish time — re-publish a flow after changing the timezone or after this feature was deployed. (See UC-FLOW-019.)
  • Branch on the current time → use the Date & Time node. It evaluates now (in a chosen timezone) against business-hours windows and takes the In hours / Out of hours output. Use it for open/closed routing, not for emitting a date string.
  • Compute a date server-side → use the Scheduler node. It returns real, bookable slots (available_slots) computed from your availability rules — no date maths in the flow.

5. Pause / resume (waiting for the user)

Two nodes pause the flow and wait for the next inbound message: Quick Reply and Collect Input. This is fundamental to conversational bots.

  • When a pause node runs, the session stores current_node_id and what it's awaiting (awaiting_buttons / awaiting_input_variable).
  • The customer's next message resumes the flow at that exact point — Quick Reply matches a button (by number 1/2, exact title, payload, or btn_0 id), Collect Input captures free text into the variable.
  • If a reply doesn't match any button, the flow restarts from the trigger (so a stray "hi" re-greets rather than dead-ends).
  • Bot flows pause for the user automatically; they only stop on an explicit human handoff (ai_handoff_at).

Chaining tip: enable Collect into variable on Quick Reply to collapse its many per-button outputs into a single "answered" output. You can chain several Quick Replies and send one summary at the end, instead of 15-edge spaghetti.


6. Node reference

Each node lists its purpose, key config, the variables it outputs, and notes. Configure everything in the node inspector. All text fields accept {{variables}}.

Messaging nodes

Send Message

Sends a text/template message on the chosen channel. - Key config: channelAccountId, message (supports {{vars}}), messageSource = custom | freeformOrTemplate | quickReply | waCloudTemplate | llm. For multilingual templates: templateNameBase + localizedBodies (see Multilingual). - Outputs: messageId, status (sent/failed). - Notes: freeformOrTemplate smart-send picks freeform inside the 24h window, else a Meta template. Respects the WhatsApp 24-hour customer-service window.

Send Media

Sends an image, video, audio, or document. - Key config: mediaType (image | video | audio | document), mediaUrl (URL or {{var}}), caption. - Outputs: messageId. - Notes: provider media URLs expire — prefer re-hosted/Storage URLs.

Quick Reply

Sends a prompt with tappable buttons. - Key config: message, buttons[] (title, payload), and optionally Collect into variable (collectAsVariable, variableName, saveMode = index | title | payload). Per-language localized message + button labels are supported. - Outputs: the chosen button as {variableName} (collect mode), or selectedValue/selectedLabel; one output handle per button otherwise. - Notes: WhatsApp Cloud renders ≤3 as buttons, 4–10 as a list, more as numbered text. Other channels use numbered text. Pauses the flow. See Multilingual.

Collect Input

Prompts the user and waits for a validated reply. - Key config: inputType (text | number | email | phone | date | choice), prompt, variableName. - Outputs: {variableName} (validated/coerced). - Notes: Pauses the flow until the user replies.

Logic nodes

If Condition

Branches on one or more comparisons. - Key config: field (or {{var}}), conditions[] of { operator, value }, combinator = and | or. - Operators: equals, not equals, contains, does not contain, starts with, ends with, regex, >, >=, <, <=, is empty, is not empty. - Outputs: true / false handle.

Switch

Multi-way branch — one handle per case + default. - Key config: inputVariable (e.g. {{intent}} or {{lang}}), cases[] of { value, label }. - Outputs: the matched case, or default.

Loop

Iterates over an array with index tracking. - Key config: the array variable to iterate; body runs per item.

Delay

Waits before continuing. - Key config: duration (seconds/minutes/hours/days).

Date & Time

Branches on whether now is inside configured business-hours windows. - Key config: timezone (IANA), businessHours[] of { day, startTime, endTime }. - Outputs: In hours / Out of hours. An empty schedule always takes In hours.

Merge

Waits for multiple branches and combines them. - Key config: inputCount (2–6), mode = combineAll | combineByPosition | append. - Outputs: merged payload with fields from every branch. Use after a fan-out so downstream sees all results together.

Jump To

Redirects execution to another node (loops, skip-ahead, reusable sections). - Key config: targetNodeId. - Notes: transparent at deploy time (compiles away); cycle-guarded. Great for converging language/branch paths back to a shared tail.

Trigger Flow (Sub-flow)

Starts another published flow for the same contact. - Key config: targetFlowId, passVariables (default on), waitForCompletion. - Notes: build reusable sub-flows (e.g. a Booking flow) once and call them from many parents.

Error Handler

Catches errors from upstream nodes. - Key config: fallbackMessage. - Outputs: errorMessage, and an error / success branch.

End Flow

Terminates the flow. Optional final message.

AI & RAG nodes

All LLM nodes need an LLM API key. Enter it in the node, or rely on a platform key / an existing n8n credential. An AI node with no resolvable key blocks n8n activation — the deploy now fails with a clear message instead of silently killing the trigger. Google's AI Response node can run key-in-URL, but the AI Agent node needs a real credential.

AI Response

Calls an LLM with a system prompt + user input, returns text. - Key config: llmProvider (openai | google | anthropic | groq | deepseek | mistral | ollama), model, prompt (supports {{vars}}), userInput (e.g. {{message.text}}), temperature. - Outputs: response, tokensUsed.

AI Agent

A LangChain tools-agent that autonomously picks tools to answer. - Key config: llmProvider/llmModel, systemPrompt, temperature, memoryEnabled + memoryWindowSize (1–50), Timezone (for dates), and tools: databaseQuery, updateContact, createDeal, addTag, httpRequest (give the HTTP tool a base URL + description). - Outputs: agentResponse. - Current date awareness: the agent is automatically told the current date/time at run time (see Dates & the current time), so it resolves "tomorrow at 3 PM" / "next Monday" correctly and outputs ISO 8601. Set Timezone to your local IANA zone (e.g. Africa/Cairo). - Notes: its system prompt now interpolates {{variables}}. Keeps per-conversation chat memory. Tools call back into ConnectGain securely.

Classify Intent

AI intent detection — usually feeding a Switch. - Key config: the input text + the candidate intents. - Outputs: the detected intent (switch on {{intent}}).

RAG System

Full Retrieval-Augmented Generation: agent + embeddings + vector retriever + an upload pipeline for your knowledge files. - Key config: LLM + embedding providers/models, knowledge base, uploaded files (ingested to the vector store on deploy). - Notes: zero-hallucination answering grounded in your documents.

Voice Agent

Hands a call to an ElevenLabs voice agent. - Key config: agentId, prompt, voice. - Outputs: transcript, summary.

Data nodes

Set Variable / Get Variable

Store / read a value in flow- or global-scoped state. - Set: variableName, value (supports {{vars}}), scope (flow | global). - Get: variableName → value into context.

Transform Data

Runs a JS expression and stores the result. - Key config: inputVariable, expression (e.g. input.toUpperCase), outputVariable.

HTTP Request

Calls an external API and stores the response. - Key config: url (supports {{vars}}), method, headers (JSON), body (JSON), responseVariable. - Outputs: {responseVariable}.status, {responseVariable}.body.

Database Query

Runs a parameterised query against an allow-listed table and stores rows. - Key config: table/operation, filters/data (JSON, support {{vars}}), columns, limit (≤500), outputVariable. - Allow-listed tables: contacts, deals, tasks, conversations, messages, bot_sessions, companies, notes, products.

Memory

Per-session / per-contact / org key-value memory, or CRUD on allow-listed tables. - Key config: mode (memory | database); memory mode: operation (set/get/append/delete/clear), scope (session/contact/org), key, value, ttlSeconds; database mode mirrors Database Query. - Outputs: {outputVariable}, success.

CRM & conversation nodes

Update Contact

Sets fields on the current contact. Key config: fields.

Add Tag

Adds or removes a tag on the contact. Key config: tags, mode = add | remove (supports {{vars}}).

Update Lifecycle

Moves the contact to a lifecycle stage and fires the Lifecycle Updated event. Key config: stageId. Stages are defined in Settings → Lifecycle Stages.

Create Deal / Update Deal

Create a deal (title, value, stageId) → dealId; or update an existing deal (dealId, fields).

Create Task / Auto Assign Task

Create a task (title, assigneeId?, dueDate?) → taskId; or auto-assign by availability/round-robin (respects can_be_auto_assigned_tasks).

Assign Conversation

Assigns the conversation to an agent (specific, round-robin, or availability-based; respects can_be_auto_assigned_conversations).

Add Comment

Adds an internal note to the contact's activity timeline (not sent to the customer). Supports {{vars}}.

Close Conversation / Open Conversation

Mark the conversation closed, or reopen it (e.g. close after resolution; reopen when the customer replies).

Handoff to Agent

Transfers the conversation to a human, preserves context, and stops the bot for that conversation (sets the handoff flag) so the bot won't talk over the agent.


7. Multilingual flows

One flow can answer each customer in their own language. The short version:

  1. Capture the language into a lang session variable (a Quick Reply language-picker with Save = payload, or a Set Variable from {{contact.language}}).
  2. Author localized Quick Reply bodies + button labels (per-language editor in the node). Default content is the fallback.
  3. For template sends, use Send Message templateNameBase + localizedBodies.
  4. Need different paths per language (not just text)? Switch on {{lang}} and converge with Jump To.

Full step-by-step, data shapes, and fallback rules: Building Multilingual Bot Flows.


8. Deploying, activating & publishing

  1. Add a Trigger node and save the flow (deploy refuses without a trigger).
  2. Click Deploy / Publish. ConnectGain compiles the graph to an n8n workflow, (re)creates it, and activates it.
  3. On success the flow is Published and its webhook is live; on failure the toast shows the reason.

What activation means: n8n only serves a flow's production webhook while the workflow is active. If a node is invalid (classically, an AI node with no LLM key), n8n refuses to activate — and the deploy now surfaces that error and leaves the flow Draft instead of pretending success. Fix the named node and redeploy.

Undeploy removes the workflow from n8n and returns the flow to Draft.


9. Testing & debugging

  • Sample-webhook tester — fire a representative event into the flow without a real customer message.
  • n8n executions — each run appears in n8n; open one to see node-by-node inputs/outputs and errors.
  • Quick activation check — POST to the flow's webhook URL:
    curl -i -X POST "<flow n8n_webhook_url>" -H "Content-Type: application/json" -d '{}'
    
    404 → workflow inactive (activation failed); 200 → active.
  • Session inspectionbot_sessions holds the live variables and current_node_id for a conversation; useful when a pause/resume misbehaves.

10. End-to-end scenarios

A. Welcome + route

Trigger message.received (channel all) → Send "Hi {{contact.first_name}}! How can we help?" → Quick Reply [Sales, Support, Hours] (collect into topic) → Switch on {{topic}} → Sales path / Support path / Date & Time (hours) path.

B. FAQ deflection with auto-close

Trigger → Classify Intent → Switch on {{intent}} → Send the matching answer → Quick Reply "Did that help? Yes/No" (collect resolved) → If resolved contains "yes" → Add Comment "Auto-resolved" → Close Conversation; else Handoff to Agent.

C. Lead capture → deal

Trigger → Collect Input name → Collect Input email → Update Contact (fields from the answers) → Create Deal ("New web lead", stage = New) → Google Sheets append row → Send confirmation.

D. Business-hours routing

Trigger → Date & Time (Mon–Fri 09:00–17:00, Africa/Cairo): In hoursAssign Conversation + "An agent will be right with you"; Out of hours → "We're closed, we'll reply at 9 AM" → Collect Input (their question) → Add Comment.

E. Multilingual support bot

Trigger → Quick Reply language picker (save payload → lang) → localized Quick Reply menu (one node, per-language body + buttons) → Switch on the choice → localized answers. See Multilingual.

F. Campaign reply engagement

Trigger Broadcast Response → Add Tag "Campaign Engaged" → Send "Thanks for replying to {{campaign_name}}!" → Quick Reply "Book a demo? Yes/No" → on Yes, Trigger Flow → Booking sub-flow.

G. Post-call follow-up

Trigger Call Ended → Send "Thanks for the call!" → Add Comment "Follow-up sent after {{duration_seconds}}s" → Create Task "Send proposal" (due +2 days).

H. Lifecycle onboarding

Trigger Lifecycle Updated → If lifecycle_stage equals "Customer" → Send onboarding checklist → Create Task "Onboarding call".

I. AI knowledge agent

Trigger → RAG System (your docs) answers grounded questions; fall back to Handoff to Agent when confidence is low or the user asks for a human.

J. Agent one-click playbook

Trigger Manual Shortcut → Send pricing pack → Add Tag "Pricing Sent" → Update Lifecycle → Opportunity. Launch it from the inbox ⚡ Shortcuts menu.

More ready-to-build recipes: Bot Flow Automation Recipes.


11. Best practices

  • Always offer an exit to a human (Handoff) on any branch a bot can't resolve.
  • Keep flows focused. Extract reusable pieces into sub-flows and call them with Trigger Flow.
  • Name variables clearly (rating_call, lead_score) and prefer collecting into variables over wide button fan-outs.
  • Use Jump To to converge branch/language tails instead of duplicating nodes.
  • Pin the channel/account on triggers when a flow is meant for one number, so it doesn't fire elsewhere.
  • Test after every deploy — confirm the workflow activated (toast or curl check) before relying on it.
  • Localize content, branch only on flow shape — most multilingual needs are content, handled in-node.

12. Troubleshooting

Symptom Likely cause / fix
No executions in n8n for a message Workflow not active. The trigger is a channel POST to the n8n webhook; n8n only serves it while active. Redeploy and read the toast; curl the webhook (404 = inactive).
"Deploy failed: AI Agent node is missing the LLM API key…" Enter the LLM key in the AI Agent node (or set the platform key). Google AI Agent needs a real credential, not key-in-URL.
Deploy reports success but bot never replies The flow may be Draft after a failed activation — check status and the deploy toast for the blocking node.
Flow re-greets instead of resuming The user's reply didn't match any awaiting button — check button titles/payloads, or use Collect-into-variable.
{{var}} shows literally in a message The variable wasn't set upstream (missing tokens are left as-is by design). Verify the producing node ran and the name matches.
Wrong language sent Ensure a lang/language variable is set before the localized node; missing/blank translations fall back to Default.
Bot talks over a human agent A Handoff sets the stop flag; ensure your handoff path runs before further bot messages.

See also


Last Updated: June 2026