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 Concepts → The builder UI → Triggers, 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¶
- Concepts
- The builder UI
- Triggers — starting a flow
- Variables & dynamic text
- Pause / resume (waiting for the user)
- Node reference
- Messaging · Logic · AI & RAG · Data · CRM & conversation
- Multilingual flows
- Deploying, activating & publishing
- Testing & debugging
- End-to-end scenarios
- Best practices
- 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)¶
- Channel —
all, or one ofWHATSAPP_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_idand 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, orbtn_0id), 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:
- Capture the language into a
langsession variable (a Quick Reply language-picker with Save = payload, or a Set Variable from{{contact.language}}). - Author localized Quick Reply bodies + button labels (per-language editor in the node). Default content is the fallback.
- For template sends, use Send Message
templateNameBase+localizedBodies. - 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¶
- Add a Trigger node and save the flow (deploy refuses without a trigger).
- Click Deploy / Publish. ConnectGain compiles the graph to an n8n workflow, (re)creates it, and activates it.
- 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:
404→ workflow inactive (activation failed);200→ active. - Session inspection —
bot_sessionsholds the livevariablesandcurrent_node_idfor 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 hours → Assign 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¶
- Bot Flows — feature overview & node list
- Building Multilingual Bot Flows
- Bot Flow Automation Recipes
- Automations · Templates · Sequences
- respond.io Parity Spec (developer)
Last Updated: June 2026