Skip to content

Code snippets (Pro)

On Professional and Enterprise plans, a flow’s pre-hook or post-hook tree can include a code snippet step: a short piece of your own code that runs during hook processing to reshape data, compute a value, or call one of your own webhooks directly.

A snippet runs inside a locked-down sandbox (see What’s blocked below), and the editor’s Test button runs it through the exact same sandbox a live call uses — what you see while testing is what runs on the call.

You define one function, run:

def run(variables, variables_patch):
# ... your code ...
return result
  • variables — a read-only snapshot of the flow’s current variables.
  • variables_patch — an empty object you fill in with variables to write back, keyed the same way as variables.
  • whatever you return becomes the step’s result, available to later steps and node text.

Reading and writing variables by name — vars

Section titled “Reading and writing variables by name — vars”

Alongside variables/variables_patch, a vars helper reads and writes any variable by the name you gave it in the editor:

def run(variables, variables_patch):
name = vars.get("customer_name", "there")
vars.set("greeting", f"Hello {name}!")
return {"ok": True}
  • vars.get(name, default=None) — read a variable (yours or a system variable) by name.
  • vars.set(name, value) — write a variable by name. Writing a system variable is rejected — they are read-only.

A read-only context object carries call metadata (never a secret): the call id, direction (inbound/outbound), caller and dialled numbers, locale, the project id, and which node the snippet is running in. A field that isn’t available on a given call reads as empty rather than raising — read it defensively.

The value run returns becomes the step’s result. Anything you print is captured and shown to you while testing, bounded so a runaway print loop is truncated rather than flooding the log. The returned result must be plain data — numbers, strings, booleans, lists, and objects.

A snippet runs in a confined sandbox. It cannot:

  • read files — your project’s secrets or any file outside the language’s own standard library are unreadable;
  • read platform credentials — no API keys, tokens, or database credentials are visible to it;
  • write files;
  • start other processes;
  • run forever — a snippet is stopped once it exceeds its timeout, and its memory and output are bounded.

A snippet can make outbound network requests — this is intentional, so it can call your own webhooks or APIs. It is still your own code running with real network access, so don’t paste in code you don’t trust.

Each snippet step has a configurable timeout, between 1 and 30 seconds. A snippet that exceeds it is stopped and the step is reported as failed — it never holds up the rest of the call.

Open a code-snippet step and use the Test panel to run it against sample values for your flow’s variables — including live data-store values and the read-only system variables — and see the result, any writes it made, and anything it printed, before you save the flow. Because Test runs the snippet through the same sandbox as a live call, a snippet that passes Test behaves the same way once the flow is active.

Code-snippet steps are a Professional/Enterprise capability — see Pro-flow nodes for the other node types coming to that same tier. The + menu only offers a code-snippet step on a Professional/Enterprise project, and saving a flow that contains one on a lower plan is rejected.