Block Runtime Contract
How each block type executes at runtime — the authoritative reference for LLM authors building flows via MCP tools.
Block Types
llm
Sends a prompt to a language model. The prompt supports template interpolation.
- Input:
pipeline_inputdict from the previous block's output (or flow global input for the first block). - Template variables:
{{fieldName}}references resolve to keys inpipeline_input.{{initial.fieldName}}references the flow's global input. - Output: A dict whose keys match the block's
output_schemafield names.
code
Executes a sandboxed Python function body for data transformation.
- Language: Python only. No other languages are supported.
- What you write: The function body only — the runtime wraps your code in a function definition. Do NOT write
def block(...)ordef _block(...)yourself. - Generated wrapper:
- Parameters:
initial— always present. Contains the flow's global input dict.- One positional parameter per field in the block's
input_schema, in array order.
- Return contract: Must return a
dict. The keys should match the block'soutput_schemafield names. - Call site:
_block(initial=<flow_global_input>, **pipeline_input)wherepipeline_inputis the previous block's output dict.
Sandbox Rules
Allowed builtins: abs, bool, dict, enumerate, float, int, isinstance, len, list, max, min, range, reversed, round, set, sorted, str, sum, tuple, zip, True, False, None
Forbidden:
- No
importstatements - No
eval()orexec() - No file I/O (
open,os,pathlib, etc.) - No
getattr,type,vars,dir(object-model traversal) - No network access
Example
Given input_schema fields: [first_name, last_name, age] and output_schema fields: [full_name, is_adult]:
The runtime generates and executes:
passthrough
Forwards input to output unchanged. Useful as a pipeline junction or for documentation.
- Input:
pipeline_inputdict from the previous block. - Output: Same dict, forwarded unchanged.
Data Flow Between Blocks
Sequential (h-container)
Blocks in an h (horizontal/sequential) container execute left-to-right. Each block receives the previous block's output dict as its pipeline_input.
The first block in a sequence receives either:
- The flow's global input (if it's the root-level first block), or
- The output from the previous sibling of its parent container.
Parallel (v-container)
Blocks in a v (vertical/parallel) container execute concurrently. All children receive the same pipeline_input (from the block/container preceding the v-container).
When all children complete, their outputs are merged into a single dict:
- For block children:
{<step_id>: <block_output>} - For nested container children:
{<index_as_string>: <container_output>}
The downstream block receives this merged dict as its pipeline_input.
Loop
A loop node iterates over an array field in its input. The arrayField property names which key contains the array.
Per-iteration input: Each child receives {...sibling_fields, [arrayField]: single_item} where:
sibling_fields= all keys from the input except the array fieldsingle_item= one element from the array
Example: If the loop's input is {items: ["a", "b", "c"], lang: "en"} and arrayField = "items", each iteration's child gets:
- Iteration 0:
{items: "a", lang: "en"} - Iteration 1:
{items: "b", lang: "en"} - Iteration 2:
{items: "c", lang: "en"}
Loop output: A list (array) of per-iteration results, in order. The downstream block receives this list.
Global Input (initial)
The flow's global input is available to every block:
- LLM blocks: via
{{initial.fieldName}}template syntax - Code blocks: via the
initialparameter (always the first parameter)
Schema Shape
Both input_schema and output_schema follow the SchemaNode structure:
The fields[].name values determine:
- Code block parameter names (in array order)
- LLM template variable names (
{{name}}) - Expected output dict keys