This reference describes the workflow YAML you see in the YAML tab of the workflow editor. It matches what the canvas saves and what the runtime executes. Read Concepts first for terminology; use this page when you author or edit YAML by hand.
YAML tab showing the full workflow definition — document header, inputs, agents, and steps
Document structure
A workflow file is a single YAML mapping. The editor always includes a document header and a steps mapping. Everything else is optional.
document
Scroll horizontally to compare
Field
Type
Description
dsl
string
DSL version. Use 1.0.0.
name
string
Workflow name (shown in the UI).
version
string
Draft version label; commonly 0.1.0.
Top-level fields
Scroll horizontally to compare
Field
Type
Description
document
mapping
Required. Metadata above.
agents
mapping
Optional. Declares agent names referenced in steps. Values are often empty objects {} or resolved resource URIs after publish.
functions
mapping
Optional. Same pattern for function names used in steps.
Optional. Named results built from expressions (see Workflow output).
Note: Layout and node positions live outside this YAML (the editor stores them separately). The YAML tab shows orchestration only.
Workflow inputs
The input block defines fields your run provides. Each field is either a shorthand string (the type name) or a mapping.
Scroll horizontally to compare
Field
Type
Description
type
string
Field type (for example string, number, boolean).
required
boolean
Default true. Set to false to allow omission.
description
string
Human-readable help.
default
any
Used when the field is missing (if not required).
yaml
document:dsl:"1.0.0"name: Example
version:"0.1.0"input:customer_message:type: string
required:truedescription: Incoming user message
priority:type: string
required:falsedefault:"normal"steps:ready:call: conditional
condition:"${ true }"
The human-readable title is document.name. There is no separate workflow description field in this YAML.
Workflow output
If you omit output, the runtime uses the last step in execution order as the workflow result. To pin a specific shape, set output to a mapping of names → expressions (see Expressions):
yaml
output:result:"${ steps.final_step.output }"
Values are evaluated the same way as step fields using ${ ... } expressions.
Steps
Each key under steps is a step name (use letters, digits, underscores). The value is a step definition: always a call field plus type-specific fields.
Optional. Parameter object; values may contain expressions.
input_template
string
Optional. A single string template (often used for agents and connectors); may contain expressions.
secrets
mapping
Optional. For function steps: maps parameter names to "$secret:<id>" bindings.
output
string
Optional. Canvas node id for this step. If omitted, the step name is used.
after
list of strings
Optional. Explicit dependencies: this step runs after the listed step names.
when
string
Optional. If present, the step runs only when this expression evaluates to true (see Boolean guards).
Dependencies are also inferred from expressions that reference other steps (for example ${ steps.other.output }). The graph must stay acyclic.
agent
Runs a workspace agent with a text prompt built from input_template (and optionally structured input for future or auxiliary use—the runtime primarily sends the evaluated input_template string to the agent).
Scroll horizontally to compare
Field
Type
Description
agent
string
Agent name as shown in the editor. After publishing, the editor resolves this to a res://agents/... URI; when writing YAML by hand, use the plain name.
input_template
string
Prompt text; use ${ ... } to inject input and prior step outputs.
Use this when the step should reason, call tools, or produce natural-language results.
Runs a workspace Python function with a JSON-serializable payload.
Scroll horizontally to compare
Field
Type
Description
function
string
Function name as shown in the editor. After publishing, the editor resolves this to a res://functions/... URI; when writing YAML by hand, use the plain name.
input
mapping
Arguments passed to the function.
input_template
string
Optional. If input is empty, some runners parse this as JSON or wrap it as input.
secrets
mapping
Optional. Merge secret bindings into parameters.
Use this for deterministic code, transforms, or API calls implemented as functions.
yaml
steps:run:call: function
function: echo
input:message:"${ input.name }"
mcp_tool
Calls a tool on an MCP server.
Scroll horizontally to compare
Field
Type
Description
server
string
MCP server name as shown in the editor. After publishing, the editor resolves this to a res://mcp_servers/... URI; when writing YAML by hand, use the plain name.
tool
string
Tool name on that server.
input
mapping
Tool arguments (expressions allowed).
Use this when a step must invoke a specific MCP tool with structured input.
Evaluates an expression and stores the result as this step’s output (often a boolean). Downstream steps can branch using when or read the value via ${ steps.<name>.output }.
Scroll horizontally to compare
Field
Type
Description
condition
string
Expression; if omitted, behaves like true.
Use this to compute a reusable condition result in the graph.
Runs a nested body once per item in a list (or over a single value coerced to a one-element list).
Scroll horizontally to compare
Field
Type
Description
items
string
Expression that yields an iterable (often ${ input.files } or a path like input.items).
as
string
Loop variable name added to the input context (default item).
max_iterations
integer
Optional. Caps iterations (default 50).
parallel
boolean
Optional. Default false. When true, iterations run concurrently instead of sequentially, bounded to at most 10 at a time.
do
mapping
Nested step name → step definition (same shape as top-level steps).
The loop exposes the current item as input.<as> inside the nested steps. Use this to process lists of files, rows, or API results.
Note: With parallel: true, up to 10 iterations run at once (the concurrency cap); any remaining iterations queue until a slot frees up. Use it when each item is independent and the body is I/O-bound (model calls, KB search, HTTP). Leave it false (the default) when later iterations depend on the results of earlier ones.
Repeats nested steps while a condition stays true, up to max_iterations.
Scroll horizontally to compare
Field
Type
Description
condition
string
Boolean expression.
max_iterations
integer
Optional. Default 10.
do
mapping
Nested steps to repeat.
Warning: The first iteration always runs the body. Starting with the second iteration, the condition is evaluated before each new iteration; if it is false, the loop stops. Plan defaults accordingly.
Use this for retry-style or state-driven loops (not unbounded—always set max_iterations sensibly).
yaml
steps:loop:call: while
condition:"${ input.continue_flag }"max_iterations:5do:body:call: function
function: echo
input:message:"tick"
parallel_analyzer
Runs multiple analyst agents in parallel, then an aggregator agent to combine results.
Scroll horizontally to compare
Field
Type
Description
analysts
list of mappings
Each item has agent and role (for example analyst).
aggregator
string
Agent that merges analyst outputs.
input_template
string
Shared prompt template for the pattern.
Use this when you want independent perspectives before a single combined answer.
Runs a multi-agent handoff: one entry agent handles the conversation first and may transfer to specialists by role (similar in spirit to the Support Router template: triage plus focused specialists).
YAML tab showing a handoff_router step with entry_agent, specialists, and expressions
Scroll horizontally to compare
Field
Type
Description
entry_agent
string
Agent that receives the first turn.
specialists
list of mappings
Each item has agent and role (specialist routing labels).
Runs a generate-evaluate-iterate cycle: a generator agent produces output, an evaluator agent scores or critiques it, and the loop repeats until the pass condition is met or max_iterations is reached.
Scroll horizontally to compare
Field
Type
Description
generator
string
Agent that produces each draft.
evaluator
string
Agent that judges the generator's output.
pass_condition
string
Expression; when it evaluates to true the loop exits early.
max_iterations
integer
Optional. Maximum rounds before stopping.
input_template
string
Initial prompt or context for the generator.
Use this when output quality benefits from iterative refinement — for example, having one agent draft a response and another critique it until it meets a quality bar.
If the path lookup fails, the default literal is used. Literals support strings in single or double quotes, numbers, true / false, null, {}, [].
Boolean combinations
AND:${ expr1 && expr2 } — both must be truthy.
OR (coalesce):${ left || right } — if left is truthy (or resolves successfully), it wins; otherwise right is evaluated.
Comparisons
Inside ${ }, you can write comparisons:
Operators:==, !=, <, >, <=, >=
Left side: a dotted path (input.tier, steps.prev.output.count, …).
Right side: a quoted string, a path (steps.other.output.field), or a numeric literal.
Example:
yaml
when:"${ input.region == \"eu\" }"
JSON outputs
If a step returns a JSON string that parses to an object or array, the runtime may normalize it so you can traverse fields (for example ${ steps.parse.output.items.0.id }).
Boolean guards
when uses boolean evaluation: empty string, false, 0, null, and similar are treated as false.
Common patterns
Sequential steps
List steps and use after so each waits on the previous (or rely only on ${ steps... } references, which also create dependencies):
yaml
steps:first:call: function
function: echo
input:message:"one"second:call: function
function: echo
input:message:"${ steps.first.output }"after:[first]
Parallel fan-out, then join
Steps with no ordering dependency between them can run in parallel. Add a join step that lists all branches in after or references their outputs:
yaml
steps:branch_a:call: function
function: echo
input:message:"A"branch_b:call: function
function: echo
input:message:"B"merge:call: function
function: combine
input:a:"${ steps.branch_a.output }"b:"${ steps.branch_b.output }"after:[branch_a, branch_b]
Conditional branching
Use a conditional step or attach when to a step so it only runs if a guard expression is true:
yaml
steps:maybe_extra:call: function
function: echo
input:message:"only if"after:[first]when:"${ input.include_extra == true }"
Loop over files
Point items at any expression that evaluates to a list (workflow input array, a prior step’s structured output, and so on). Bind each element with as: