Accessing Output Downstream
Using $output.{nodeId} in expressions to read a previous node's data — property paths, array indexing, and expression engine evaluation.
The $output Variable
Inside any expression field in a node's config (input mapping, conditions, message body, etc.), $output is a dictionary of all previously executed node outputs keyed by nodeId.
$output.{nodeId} // full output object
$output.{nodeId}.field // top-level field
$output.{nodeId}.nested.field // nested field
$output.{nodeId}.items[0].name // array element field
Concrete Examples
// Node "fetchUser" returned: { userId: "u-123", email: "alice@acme.com", roles: ["admin"] }
$output.fetchUser.userId // → "u-123"
$output.fetchUser.email // → "alice@acme.com"
$output.fetchUser.roles[0] // → "admin"
$output.fetchUser.roles.length // → 1
// Node "queryInvoices" returned: { items: [{id: "inv-1", amount: 500}], rowCount: 1 }
$output.queryInvoices.items[0].amount // → 500
$output.queryInvoices.rowCount // → 1
When Is Output Available?
A node's output becomes available in $output as soon as that node completes — whether it was in the same execution branch or a parallel branch. The engine always writes to ExecutionMemory before scheduling downstream nodes, so any node that executes after a given node can safely read its output.
$output.nodeB because NodeB hasn't completed yet. Only nodes that run after both complete (e.g., after a join/merge gateway) can safely read both outputs.
Null-Safe Access
If a node has not yet executed (or was skipped), $output.{nodeId} returns null. Use null-coalescing in expressions to guard against this:
// Safe access with fallback
$output.optionalNode?.amount ?? 0
// Check before use
$output.lookupNode != null ? $output.lookupNode.userId : $context.actorId
Full Expression Context
The expression engine provides several root variables alongside $output:
| Variable | Description |
|---|---|
$output | Map of all completed node outputs by nodeId |
$json | The workflow's trigger input data |
$context | Execution context (actorId, tenantId, executionId, timestamp) |
$env | Environment variables and platform config values |
TypeScript — Accessing Output in the Designer
In the React designer, the expression autocomplete is aware of node output schemas. When you type $output., the editor suggests available node IDs. This is powered by the WorkflowNodeOutputSchema type registered for each node type:
// packages/flow-studio-designer/src/stores/expressionContext.ts
export function buildExpressionContext(
nodes: WorkflowNode[],
memory: ExecutionMemorySnapshot
): ExpressionContext {
const output: Record<string, unknown> = {};
for (const node of nodes) {
if (memory.nodeOutputs[node.id] !== undefined) {
output[node.id] = memory.nodeOutputs[node.id];
}
}
return { $output: output, $json: memory.triggerData, $context: memory.context };
}