Once blocks are connected, you need ways to pull the right value out of a connected block's output and get it into the field you're configuring. This page covers the techniques available beyond basic tag syntax.
Reference Sources
A connection tag can point at more than just a directly-connected block's output:
| Source | Syntax | Resolves to |
|---|---|---|
| Block output | <blockName.field> | The named block's output, once it has run |
| Loop context | <loop.index>, <loop.currentItem>, <loop.items> | The current iteration inside a Loop block |
| Loop results | <loopName.results> | The accumulated array of results from a completed loop |
| Parallel context | <parallel.index>, <parallel.currentItem>, <parallel.items> | The current branch inside a Parallel block |
| Workflow variable | <variable.variableName> | A value set with a Variables block or defined at the workflow level |
| Environment variable | {{VAR_NAME}} | A personal or workspace secret, using double-brace syntax instead of angle brackets |
These sources are checked in order — loop context first, then parallel context, then workflow
variables, then environment variables, and finally block outputs. A block named loop,
parallel, or variable would shadow the built-in context, so those names are reserved.
Dot Notation and Array Indexing
Nested fields use dot notation; array elements use bracket indices in the same path:
<agent1.tokens.total>
<api1.data.results[0].id>
<function1.result.calculations.total>You can combine multiple indices for deeply nested arrays, such as <api1.data.items[0][1]>. See Data Structure for what each block type actually outputs.
Manipulating Data with Function Blocks
Connection tags give you read access to a value as-is. When you need to reshape, filter, or combine data — not just reference it — insert a Function block between the source and destination:
// Reformat an API response before it reaches downstream blocks
const users = <api1.data.users>
return users.map(u => ({ id: u.id, label: `${u.name} <${u.email}>` }))Inside a Function block, referenced block outputs are made available as native JavaScript or Python values (not pre-serialized strings), so you can filter arrays, reduce objects, or merge multiple upstream outputs before passing the result on. The block's result field becomes the new output other blocks reference.
Connection tags are text substitutions in every other block type. In a numeric field, <api1.data.count> * 2
only works correctly if the resolved value is actually a number — check the source block's real output
before assuming its type.
Conditional Access
Router and Condition blocks let you branch on connected data without a Function block:
- A Condition block evaluates an expression referencing upstream data (
<api1.status> == 200) and activates one edge based on the result. - A Router block uses a model to pick a destination based on connected data plus its own instructions.
Both expose selectedPath in their output, so downstream blocks can confirm which branch ran — see Data Structure for the exact shape.
Handling Missing or Empty Data
If a referenced block did not execute on the current run — for example, it sits behind an unselected Condition branch — its reference resolves to an empty value rather than throwing an error: an empty string in most block types, null inside Function blocks. Design downstream logic to tolerate that rather than assuming every upstream block always ran.