setVarstableSet variable
Save a value to a flow variable so later steps can read it as {{vars.name}}. Add cases below to branch on the value right here — no separate Branch node n…
What it does
Writes a value to a flow variable so later steps can read it as
{{vars.<name>}} in templates or via vars.<name> in customScripts.
The op field controls how the new value combines with what's already
there: set overwrites, append and prepend concatenate strings,
increment and decrement do numeric math, toggle flips a boolean,
push adds an entry to an array, delete removes the variable entirely,
and random / randomInt produce stochastic values for game-style
flows. The value field is rendered as a template before the op runs,
so {{event.from}}, {{vars.other}}, and {{config.x}} all work.
After the write, this node auto-advances. If you've configured cases
on it (the unified { path, op, value, nodeId } shape — see invariant
I-3), it dispatches on the just-written value and follows the matching
case's edge. When no case matches, it falls through to the first
outgoing transition wired in the canvas. This means a single node can
do "compute → branch on result" in one step — the dedicated Branch on
variable node is only needed when you're routing on a value somebody
else already wrote.
When to use it
- Stash the caller's number at the start of a flow so a later sub-flow
can read it without referencing
event.from - Build a counter for retry logic:
op: incrementon avars.attemptsvariable, then route via cases — "after 3 attempts, give up" - Compose a formatted string for a TTS prompt —
op: appendto glue pieces together as the flow progresses - Roll a die for game-show callers (
op: randomInt,value: "1,6") and route on the result with cases on the same node - Toggle a boolean flag (
op: toggle) to flip between two paths on alternating calls — useful for crude round-robin between two destinations without a real queue - Clear out a stale value (
op: delete) before re-running a sub-flow that reads it as an input
Configuration
Save a value to a flow variable so later steps can read it as {{vars.name}}. Add cases below to branch on the value right here — no separate Branch node needed.
| Field | Label | Type | Required | Default | Notes |
|---|---|---|---|---|---|
name | Variable name | text | Required | callerTier | Reference later as {{vars.callerTier}}. |
op | Operation | select | Optional | set | Options: set, append, prepend, increment, decrement, toggle, push, delete, random, randomInt. How to combine the new value with the existing variable. |
value | Value | text | Optional | gold | Plain text or a template. Examples: {{event.from}}, {{vars.gatheredDigits}}. For randomInt, use "min,max" — e.g. "1,6" for a die. For toggle/random/delete this field is ignored. |
Examples
Stash a value and continue
The simplest form: write vars.callerTier to gold and follow the
single outgoing edge.
{
"id": "mark-vip",
"type": "setVar",
"config": {
"name": "callerTier",
"op": "set",
"value": "gold"
},
"on": { "__next": "vip-queue" }
}
Increment a retry counter and branch on the result
After three failed gather attempts, hand off to a human; otherwise loop back to the prompt. The cases are evaluated against the value just written.
{
"id": "bump-attempts",
"type": "setVar",
"config": {
"name": "attempts",
"op": "increment",
"value": "1",
"cases": [
{ "path": "vars.attempts", "op": ">=", "value": "3", "nodeId": "give-up" }
]
},
"on": { "__next": "retry-prompt" }
}
Gotchas
op: incrementanddecrementquietly coerce non-numeric values. The current value runs throughNumber(...)and falls back to0when it'sNaN. So anincrementagainst an unset or string-shaped variable starts at0 + step, not at the string. Useful for "first time through" counters; surprising if you were storing"3"and wanted strict typing.op: pushparses the rendered value as JSON before pushing. Ifvalueparses successfully, the parsed object is pushed; if it doesn't parse, the raw string is pushed instead. Pushing a literal"foo"works; pushing{"id":1}works too — but a string that happens to look like JSON (e.g. a phone number with leading+1) will land as a string because it's not valid JSON.op: deleteclears the var; subsequent reads returnundefined. Templates renderundefinedas the empty string, not the literal word "undefined." If something downstream is doing equality on the missing var, it will compare against"".- Cases run on the value AFTER the op. The case dispatcher
sees the newly-written value, not the previous one. If you need
to branch on the old value, do that with a separate
branchnode before the write. randomIntparsesvalueas"min,max","min..max", or"min-max". All three separators work. An unparseable value defaults to the range0..100. The bounds are inclusive on both ends, so"1,6"rolls a fair six-sided die.nameis templated throughString(...)only, not rendered. The variable name itself does NOT support{{vars.x}}— only thevaluefield does. If you need a dynamically-named variable, use a customScript and write tovars[someKey]directly.
