Skip to main content

What is a Code Step?

The Code Step is a flow tool that runs small, allow-listed Python snippets to validate data, update variables, and route the conversation. It runs on a normal tool step. Use it for the precise, deterministic work that an LLM shouldn’t guess at — format checks, counters, flag logic, and parsing structured data returned by a webhook.

The run() Contract

Every Code Step must define exactly one top-level function named run:
The function:
  • Must be named run and take no arguments
  • Must return a bool, a list[bool] or tuple[bool, ...], or a whole number (int) naming a condition row
  • Must not use decorators, nested functions, or classes
  • Must not use imports, global, or nonlocal
  • Must only call allow-listed functions
How the return value routes the step: Other return values (a string, a decimal such as 1.0, a list of strings, or a list that mixes booleans and numbers) fail closed: the step routes to Otherwise and the error is written to the call’s system notes.
See Routing with multiple conditions for worked examples.
Do not indent def run(): — it must start at the first column.

Variables and Inputs

Read and write configured variables with double-brace {{...}} placeholders, and pass extra values in as mapped inputs.
See Variables & Inputs for reads, writes, the custom namespace, and input_1-style mapped inputs.

Compile and Run

The Code Step is checked when you save it and again when the flow is compiled. When the call reaches the step, the code is prepared once (placeholders rendered, validated against the allow-list, compiled) and that prepared version is reused every time the step runs:
  1. Placeholders are rendered into executable Python
  2. The code is parsed and checked against the deny-by-default validator
  3. run() executes and its return value is normalized into ordered boolean outputs
Compile errors, run errors, run success, and any print(...) output are written to the call’s system notes, including the line number on failure. For example:
Use print(...) for debugging: unquoted placeholders like print({{contact.email}}) print the resolved value, while print("{{contact.email}}") prints the literal placeholder text.

Next Steps