Flow Builder
Reference for node types, routing, variables, and validation in the visual flow builder
Flows are directed graphs. A Trigger starts the run, each node returns an outcome, and edges decide where execution goes next. Nodes pass data through run context and reusable variables.
Core concepts
| Concept | Meaning |
|---|---|
| Node | A step in the automation, such as sending a message or calling an API |
| Edge | A connection from one node to another |
| Outcome | The result a node returns, such as default, success, error, or timeout |
| Context | Per-run data produced by trigger events and nodes |
| Variables | Named values created by Set Variable, User Input, or LLM nodes |
| Parking node | A node that can pause the run until a future message or timer resumes it |
Use template variables in supported fields:
{{nodes.trigger.message}}
{{variables.customerName}}Undefined or null values resolve to an empty string.
Trigger
Entry point for every flow. It inspects incoming WhatsApp messages and decides whether the flow should start.
| Field | Description |
|---|---|
| Trigger type | incoming_message |
| Mode | keyword or regex |
| Keyword | Comma-separated words, converted to a case-insensitive regex |
| Regex | Raw case-insensitive regex pattern |
A blank keyword/regex behaves as a catch-all trigger.
Edges: default
Context output: message text, remote JID, message ID, timestamp, trigger type, matched trigger value, selected row/button metadata when present.
Send Message
Sends a text message, image, or video to the current contact.
| Field | Description |
|---|---|
| Message type | text, image, or video |
| Text | Message body or caption |
| Media URL | Image or video URL |
Edges: default
May terminate: yes. If it has no outgoing edge, the flow can end here.
Send Interactive
Sends a WhatsApp interactive list, button set, or product-style message. Lists are the most common option for menu flows.
{
"sections": [
{
"title": "Main menu",
"rows": [
{ "id": "sales", "title": "Sales" },
{ "id": "support", "title": "Support" }
]
}
]
}Edges: default plus edge rules for selected rows/buttons when configured by the editor.
Parking: yes. Interactive replies can resume routing from this node when the selected row ID belongs to the list.
The current engine does not require a separate Wait node after Send Interactive. A user's list selection can dispatch from the interactive node itself.
Condition
Branches the flow based on text, selected row/button IDs, outcomes, or other context values. Branches are evaluated in order, and the first match wins.
| Operator | Use when |
|---|---|
| equals / not_equals | Exact string comparisons |
| contains | The field includes a substring |
| starts_with / ends_with | Prefix or suffix checks |
| regex | Flexible text matching |
| is_empty / not_empty | Presence checks |
Edges: one edge per branch and one default edge.
Context output: matchedBranch
HTTP Request
Calls an external HTTP API and stores the response.
| Field | Description |
|---|---|
| Method | GET, POST, PUT, PATCH, or DELETE |
| URL | External endpoint |
| Headers | Key-value header pairs |
| Body | JSON body string |
| Timeout | Request timeout in seconds |
Edges: success, error
May terminate: yes.
The executor validates outbound URLs before calling them. Private, loopback, link-local, and otherwise unsafe targets are blocked to reduce SSRF risk.
Delay
Pauses the run for a configured number of seconds.
| Field | Description |
|---|---|
| Delay | Seconds to wait before continuing |
Edges: default
Parking: yes.
Go To
Jumps directly to another node by ID. Use it for loops or returning to a menu.
| Field | Description |
|---|---|
| Target node | Existing node to continue from |
Edges: none. The jump target is stored in node configuration, not represented as an edge.
Validation: publish fails if the target is missing.
Set Variable
Creates or updates named variables from static text or interpolated values.
customerName = {{nodes.user-input.capturedText}}Edges: default
May terminate: yes.
Variables are referenced later with {{variables.name}}.
User Input
Sends an optional prompt and waits for the contact's next text message.
| Field | Description |
|---|---|
| Prompt | Message sent before waiting |
| Variable name | Stores the reply text in variables |
| Timeout | Seconds before the timeout outcome |
Edges: default, timeout
Parking: yes.
Context output: capturedText, plus the named variable when configured.
Media
Sends an image or video with an optional caption.
| Field | Description |
|---|---|
| Media type | image or video |
| Media URL | Publicly reachable media URL |
| Caption | Optional caption text |
Edges: default
May terminate: yes.
LLM
Runs the placeholder LLM step and stores a response. The current executor records the prompt and writes a placeholder response until a model provider is configured.
| Field | Description |
|---|---|
| Prompt | Prompt text with interpolation support |
| Model | Model identifier |
| Variable name | Optional variable to store the response |
Edges: default, error
May terminate: yes.
End
Marks the run as ended. End lives under Advanced in the editor because many action nodes can terminate implicitly.
| Field | Description |
|---|---|
| Clear context | Reserved for terminal cleanup behavior |
Edges: none.
Edge summary
| Node | Edges | Notes |
|---|---|---|
| Trigger | default | Starts the flow |
| Send Message | default | Can end implicitly |
| Send Interactive | default | Parks for list/button replies |
| Condition | branch IDs, default | First matching branch wins |
| HTTP Request | success, error | Blocks unsafe URLs |
| Delay | default | Resumes after timer |
| Go To | none | Jumps to configured target |
| Set Variable | default | Can end implicitly |
| User Input | default, timeout | Captures next text reply |
| Media | default | Can end implicitly |
| LLM | default, error | Placeholder response today |
| End | none | Explicit terminal node |
Validation before publish
Publishing calls the shared graph validator from @wp-engine/nodes.
Blocking errors include:
| Code | Meaning |
|---|---|
NO_TRIGGER | The graph needs exactly one Trigger node |
DUPLICATE_ID | Two nodes share the same ID |
UNKNOWN_TYPE | A node type is not registered |
DISCONNECTED | A non-terminal node has no outgoing path |
GO_TO_TARGET_MISSING | A Go To node points at a missing node |
INVALID_DATA | A node is missing required config |
Warnings include unreachable nodes and implicit terminal nodes. Warnings help clean up the graph but do not always block publishing.
Common patterns
Simple auto-reply
Trigger -> Send MessageMenu with support capture
Trigger -> Send Interactive -> Condition
sales -> Send Message
support -> User Input -> Send Message
default -> Send MessageFollow-up loop
Send Message -> Delay -> Go To(target: Send Message)Use loops carefully. Add an exit condition or timeout path so contacts do not get repeated messages indefinitely.