For the complete documentation index, see llms.txt. Any page on this site can be fetched as Markdown by appending .md to its URL.

Variables & Data

Storing data, referencing it with $(name), querying databases, and calling integrations.

Variables are how a flow carries data from one step to the next: a caller's input, a value looked up in a database, a field from an API response. They're scoped to the conversation and can be read by any node downstream of where they're set. See Scope for what "the conversation" covers when a call passes through more than one workflow.

The $(name) syntax

Reference a variable anywhere a field accepts it by wrapping its name in $(...). When the node runs, $(name) is replaced with the variable's current value.

For example, if a variable customerName holds "Alex", a Send SMS body of:

Hi $(customerName), thanks for calling!

is sent as Hi Alex, thanks for calling!. You can reference several variables in one field, and combine them with literal text.

A variable must be set before it's read. Referencing $(name) on a path where that variable was never assigned yields no value. Order your flow so the node that sets a variable runs before the nodes that use it.

Setting variables

Use a Set Variable node to create or update variables during a run. Beyond plain assignment, Set Variable can compute a value with built-in operations, so you can derive a value once and reuse it instead of recomputing it in several places:

  • Arithmetic — add, subtract, multiply, divide, round, min/max, and more.
  • String — append, prepend, length, slice, and find-and-replace (including regex replace).
  • Date — create, format, diff, and read or set parts of a date/time.
  • JSONPath — extract a value from a JSON structure held in a variable.

The inputs to these operations can themselves be $(name) references, so you can build a value from other variables.

Patterns Regex Replace refuses

Regex Replace and Regex Replace All refuse a pattern whose matching time can grow exponentially with the input. A pattern is refused when it has a group repeated by +, *, or a brace quantifier that allows more than one repetition ({2}, {2,}, {1,5}), and that group either:

  • contains +, *, ?, or a variable-count brace such as {1,3} or {2,}, at any depth, or
  • has two alternatives that can start with the same character. An alternative that starts with a character class, a group, or something that can match nothing counts as starting with any character.
PatternResult
(a|aa)+Refused
(\d+)+Refused
(ab|cd)+Accepted
\d{1,3}(,\d{3})*Accepted
(\.\d+)?Accepted

The check errs toward refusing. Some safe patterns are refused, for example (\d|\s)+ and ((ab)|(cd))+. Rewrite one as a character class ([\d\s]+) or without the inner groups ((ab|cd)+).

The check runs when the node runs, not when you save. A workflow with a refused pattern saves and publishes normally. When the node runs, it takes its fallback exit and sets none of its variables, including the ones that did not use the pattern.

Scope

A conversation has one set of variables, shared by everything that handles it. A call that starts in one workflow, hands off to an AI agent, and has that agent invoke a second workflow uses the same set throughout: what the first workflow set, the agent's tools and the second workflow can read.

That is what makes context carry across a hand-off, and it has one consequence worth designing around. Two workflows that write the same variable name overwrite each other. The later write wins, and neither one is told. Variables with different names never collide, so the fix is a naming convention rather than avoiding shared variables.

If a workflow is meant to be reusable across calls that already carry data, prefix its own working values with something specific to it — refund_step, not step.

Variables do not outlive the conversation, and two conversations never see each other's.

System variables

Every run also carries values the platform fills in itself: the conversation's id, the caller's number, the current date and time. They live under the sys. prefix and are referenced the same way:

Thanks for calling from $(sys.telephony.ani).

You can't set or overwrite them; a Set Variable node writing to a sys. name is rejected. See the system variable reference for every available token, its type, and when it's present.

Getting data from a database

SharpenDB nodes read and write records directly (requires the Sharpen integration):

  • SELECT reads rows; capture the columns you need into variables.
  • INSERT, UPDATE, and DELETE modify rows.

SELECT (and the other operations) save results into variables by JSONPath, so a value returned by a query becomes available to later nodes as $(name). See the node reference for each node's fields and exits.

Getting data from an integration

Integration and Invoke Lambda nodes call external services and, like the database nodes, capture fields from the JSON response into variables by JSONPath. That response data is then usable downstream with $(name) — for instance, branch on it in a Condition or include it in a message.

Nodes that call out (database, integration, Lambda) expose a timeout exit. Wire it so the flow still behaves sensibly when a call is slow or fails — see Error Handling.

Next steps

On this page