Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.anyreach.ai/llms.txt

Use this file to discover all available pages before exploring further.

A workflow execution carries a single accumulating object — the context (ctx) — that grows as each step runs. Understanding ctx is the key to writing expressions that reference data from any earlier step.

The context object

When a workflow starts, ctx contains the trigger data and any input provided:
{
  "input": { ... trigger event data or manual input data ... }
}
After each step runs and produces output, ctx gets a new key named after that step ID:
{
  "n1": { "customer_email": "alice@example.com" },
  "n2": {
    "status_code": 200,
    "headers": { ... },
    "body": { "id": "c_123", "first_name": "Alice", "tier": "gold" }
  }
}
By the time the workflow reaches an Output step, ctx contains every step’s output.

Referencing data with expressions

Suppose your workflow has executed two steps so far:
  • n1: a manual Input step
  • n2: an Action step
The context (ctx) at this point might look like:
{
  "n1": { "customer_email": "alice@example.com" },
  "n2": {
    "status_code": 200,
    "headers": { ... },
    "body": { "id": "c_123", "first_name": "Alice", "tier": "gold" }
  }
}
To read the customer_email value produced by the Input step n1, use this expression:
{{n1.customer_email}}
In this expression, n1 refers to the step ID, and customer_email is the specific key from that step’s output. See Referencing step output for the full syntax reference.

What each step contributes to ctx

StepWhat it adds to ctx
TriggerThe trigger payload (conversation data, timer metadata, or external app event)
ActionWhatever the action returned from the native or Pipedream operation
ConditionThe label of the matched branch (or null for default)
CodeWhatever the Python function returned
HTTP API{ status_code, headers, body }
OutputThe defined output fields — also ends the execution path
Wait{ waited_seconds }
InputThe user-defined input fields provided at run time

Type preservation

Expressions preserve types when the entire field value is an expression. When mixed with text, they coerce to string.
// Whole-field expression — preserves the original type
"account_id": "{{ Lookup.body.id }}"12345   (integer)

// Interpolated expression — always a string
"message": "Account {{ Lookup.body.id }}""Account 12345"  (string)
This matters when downstream steps (HTTP request bodies, Output schemas) expect specific types.

Working with lists

There is no built-in loop step. To iterate over a list, use a Code step:
def run(ctx):
    contacts = ctx["Lookup"]["body"]["contacts"]
    results = []
    for contact in contacts:
        r = requests.post("https://api.example.com/notify", json={"id": contact["id"]})
        results.append(r.json())
    return {"results": results}
For long-running loops where each iteration might fail independently, consider invoking sub-workflows asynchronously from the Code step — see Sync vs async.

Referencing Upstream Step Data in the Current Step

Each step’s configuration form includes smart input components that allow you to easily select properties from upstream steps. This makes it simple and error-free to insert expressions referencing outputs from previous steps. When you choose a variable using the variable selector, the correct expression is automatically inserted into your configuration field.
Variable selector open in builder
A variable inserted into field using variable selector
Here clicking on the “name” property of the “Input” step node automatically builds the expression {{n1.name}} where n1 is the id of the Input step.