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:
def run():
    return True
The function:
  • Must be named run and take no arguments
  • Must return a bool, list[bool], or tuple[bool, ...]
  • Must not use decorators, nested functions, or classes
  • Must not use imports, global, or nonlocal
  • Must only call allow-listed functions
Invalid return values (a string, a number, a non-boolean list) fail closed.
def run():
    return "true"   # invalid

def run():
    return 1        # invalid
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.
def run():
    email = {{contact.email}}
    {{contact.email_verified}} = bool(email and "@" in email)
    return {{contact.email_verified}}
See Variables & Inputs for reads, writes, the custom namespace, and input_1-style mapped inputs.

Compile and Run

The Code Step is validated twice — once at startup, and again before each execution:
  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
Startup compile success is logged internally, not written as a user-facing note. 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:
Tool | Code Step | Print: email present: True
Tool | Code Step | Run success: outputs={'0': True, '1': False}
Tool | Code Step | Run error on line 2: name 'input_1' is not defined | return bool(input_1)
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