Agent Steps
Steps are the building blocks of an agent workflow. Each agent contains an ordered list of steps that execute sequentially — the output of one step becomes the input to the next. Steps can also reference outputs from any earlier step using substitution variables.
Step Types
Agent steps are organized into seven categories, matching the step selector in the editor:
| Category | Steps | Description |
|---|---|---|
| Core Actions | Text, Regex Replace, Filter, Content Input, Extract Content, Extract Data, Evaluate Step, Compact Input | The fundamental building blocks: compose text, transform, extract, evaluate, compact |
| AI & Generation | Prompt Call, Generate Image, Generate Audio, Generate Video | Model-powered steps: call an LLM (optionally with tools and structured output), or generate images, audio, and video with dedicated generation models |
| Control | Gate, Merge, Retry, Wait, For Each, If / Else, Switch, Human-in-the-Loop | Branch, merge, iterate, retry, pause, and route the workflow |
| Content Actions | Retrieval, Write Metadata, Write/Load Content Attachment, Load Content, Publish Content | Read, enrich, and publish knowledge base content |
| Memory | Write Memory, Append Chat Turn, Search Memory, Load Memory, Load Chat History | Persistent agent memory across runs |
| Integration | Webhook Call, MCP Client Call, Web Fetch, Web Search, Write to S3, Send Email, Call Agent, List Cloud Drive Folder, Read / Write Cloud Drive File | Connect to external systems, APIs, cloud drives, and other agents |
| Output | Display Result, Item Value, Streaming Result | Deliver the final result to users |
Common Fields
Every step type shares these base fields:
| Field | Type | Required | Description |
|---|---|---|---|
step_type | enum | Yes | The type of step (see sections below) |
id | string | Auto | A unique identifier for the step. Must match ^[a-zA-Z0-9_-]+$. Auto-generated if not provided. Used to reference this step's output from other steps via {{step.id.output}}. |
name | string | No | A human-readable label for the step, shown in the UI |
purpose | string | No | A description of what this step does. Used by the AI assistant to understand context. |
Child Steps (Composite Steps)
Most step types are composite — they can contain nested child steps. Child steps execute after their parent and receive the parent's output as input.
| Field | Type | Default | Description |
|---|---|---|---|
child_steps | array | [] | Ordered list of child steps to execute after this step |
Nearly every step type is composite and supports child_steps. The only step types that do not support child steps are the terminal / non-composite ones: Display Result, Streaming Result, Item Value, and Retry.
For Each is different from other composite steps: its children are a body template that runs once per iteration of a runtime-resolved list, not a one-shot sequence. See the For Each Step reference for iteration variables, slicing, parallelism, and trace behavior. Also note: display_result, streaming_result, human_in_the_loop, and wait are not allowed inside a For Each body — multiple iterations would produce ambiguous UI output (and, for the parking steps, ambiguous resumption).
If / Else and Switch also dispatch into named subtrees (then_steps / else_steps for If / Else; per-case steps plus else_steps for Switch). Each invocation runs one branch (or no branch when nothing matches and there is no else). After the chosen branch completes, the branch's output flows into the If / Else or Switch step's own child_steps — the post-branch continuation chain that always runs. display_result and streaming_result are not allowed inside any branch subtree (then_steps / else_steps / cases[].steps) because they are terminal output sinks; place them in the branching step's child_steps instead, with each branch ending in a content-producing step (text / prompt_call). See the If / Else and Switch references for branch markers and trace behavior.
Human-in-the-Loop pauses the run, asks one or more humans to pick from a choice list, and resumes with the chosen outcome as the step's output. Downstream if_else / switch / gate steps route on {{step.<hitl_id>.output}}. See the Human-in-the-Loop concept page for the lifecycle / quorum / billing overview and the Human-in-the-Loop Step reference for the field-level configuration.
String Substitutions
Most step fields support dynamic variable substitution using {{placeholder}} syntax. This lets steps reference agent input, other steps' outputs, metadata, and runtime values.
Available Variables
| Variable | Description |
|---|---|
{{input}} | The current step's input (output of the previous step, or agent input for the first step) |
{{agent.input}} | The original agent input (always the initial input, regardless of step position) |
{{agent.name}} | The agent's name |
{{agent.id}} | The agent's unique ID |
{{agent.run_id}} | The current run's unique ID |
{{agent_step.id}} | The current step's ID |
{{agent_step.name}} | The current step's name |
{{step.<step_id>.output}} | Output from a previous step with the given ID |
{{step.<step_id>.input}} | Input to a previous step with the given ID |
{{attachments}} | File attachments on the current step's input (see File Attachments) |
{{attachments[N]}} | Single attachment at zero-based index N |
{{attachments[pattern]}} | Attachments whose filename matches the glob pattern (*, ?) |
{{agent.attachments}} | All attachments from the original trigger uploads |
{{agent.attachments[…]}} | Trigger uploads narrowed by index or filename pattern |
{{step.<id>.attachments[…]}} | Attachments emitted by a prior step's output manifest (e.g. generated images) |
{{metadata.<field>}} | A metadata field value from the trigger |
{{knowledge_base.name}} | Knowledge base name (in retrieval context) |
{{knowledge_base.description}} | Knowledge base description (in retrieval context) |
{{organization.name}} | Organization name (falls back to user name) |
{{organization.description}} | Organization description |
{{user.name}} | Name of the user who initiated the run |
Date & Time Variables
Date and time variables accept an IANA timezone and an optional locale code. Currently, the locale code selects the format pattern (for example, ordering and separators), but month and day names are rendered in English by the backend implementation.
| Variable | Format / Behavior | Example Output |
|---|---|---|
{{date UTC}} | YYYY-MM-DD | 2026-02-17 |
{{date America/New_York}} | YYYY-MM-DD | 2026-02-17 |
{{date Europe/London en}} | Locale-specific date pattern (English month/day names) | February 17, 2026 |
{{date Asia/Tokyo ja}} | Locale-specific date pattern (English month/day names) | February 17, 2026 |
{{time UTC}} | HH:MM:SS | 14:30:00 |
{{time America/New_York}} | HH:MM:SS | 09:30:00 |
{{datetime UTC}} | YYYY-MM-DD HH:MM:SS | 2026-02-17 14:30:00 |
{{datetime Europe/Paris fr}} | Locale-specific datetime pattern (English month/day names) | February 17, 2026 03:30:00 PM |
Function-style syntax is also supported: {{datetime(UTC)}} or {{datetime(UTC, es)}}. As with the inline syntax, the locale argument currently affects only the pattern, not the language of month or day names.
Unrecognized placeholders are left unchanged in the output, making it safe to include template syntax that should not be resolved.
File Attachments
For a high-level introduction with worked examples (uploads, generated images, per-file fan-out), see the Attachments guide. The section below is the grammar and routing reference.
Agents accept file attachments alongside text input. When you trigger a run with one or more uploaded files (image, audio, video, PDF, document), each file flows through the agent in two parallel channels:
- Native binary — capable LLMs (Claude, Gemini, Nova, GPT-4o-class) receive the raw bytes as a media content block.
- Extracted text — every file is also OCR'd / transcribed; that text is what the LLM sees when the configured model is text-only, and what governance evaluators and the prompt scanner inspect.
A step "sees" attachments only when its template declares the dependency. This narrow-visibility rule prevents trigger uploads from leaking into intermediate steps that don't actually want them.
How to reference attachments
Two declaration forms drive routing:
- Implicit — referencing
{{input}},{{agent.input}}, or{{step.<id>.input|output}}brings in all attachments carried on that source. Templates that already use these placeholders keep working unchanged. - Explicit — the
{{attachments[…]}}family narrows the set. When any explicit selector targets a source, the implicit "all" is replaced by the narrowed subset.
Selector syntax
| Form | Meaning |
|---|---|
{{attachments}} | All attachments from the current step's input manifest |
{{attachments[0]}} | The attachment at zero-based index 0 (out-of-range matches nothing) |
{{attachments[*.pdf]}} | All PDFs — filename glob via fnmatch (* matches any run of chars, ? matches one) |
{{attachments[invoice.pdf]}} | Literal filename — no globs ⇒ exact match |
{{agent.attachments}} | All attachments from the trigger uploads (always available regardless of step position) |
{{agent.attachments[*.png]}} | Trigger uploads narrowed by glob |
{{step.gen-image.attachments[0]}} | The first attachment emitted by a prior step's output manifest (e.g. a generated image) |
Multi-match is allowed — a glob that matches three files surfaces three media blocks. Zero-match is a no-op (logged at INFO).
In the resolved prompt text, each placeholder expands to [attachment: <filename>] markers so the LLM sees a textual anchor; the binary flows out-of-band as a native media block (or, when the model is text-only, as the OCR/transcript text under an --- attachment text --- separator).
Per-step attachments config field
attachments config fieldSteps that consume a manifest (send_email, write_aws_s3_object, webhook_call, call_agent, publish_content, write_content_attachment, for_each, display_result, streaming_result, add_chat_turn) expose an Attachments config field — a list of {{…}} reference expressions that together narrow which manifest entries the step ingests. Each expression selects attachments from one source — this step's input ({{attachments[…]}}), the trigger uploads ({{agent.attachments[…]}}), or a specific upstream step's output files ({{step.<id>.attachments[…]}}) — by index, filename glob, or all:
[
"{{attachments[*.png]}}",
"{{agent.attachments[invoice.pdf]}}",
"{{step.gen-image.attachments[0]}}"
]
Expressions union their matches in list order; duplicates (same (source, step_id, storage_key)) are pruned with first-seen winning. On consumer steps (send_email, write_aws_s3_object, webhook_call, call_agent, publish_content, write_content_attachment, for_each), null / empty list defaults to "every attachment on the step's input manifest". On the result steps (display_result, streaming_result) and add_chat_turn the default is text only — they surface/persist attachments only when at least one reference is set; leaving the list empty attaches nothing.
The step editor's Attachments widget builds the reference list row-by-row with a live match-count preview. See Attachments references field for the full reference.
Multi-modal routing
For each attachment a prompt_call step receives, the runtime picks one of three paths based on the configured model's capabilities:
- Native — when the model declares support for the attachment's MIME (e.g. Claude Haiku 4.5 +
image/png), the binary is sent as a media content block. - OCR / transcript demotion — when the model can't handle the MIME, the extracted-text counterpart is stitched onto the prompt body so the LLM still sees the content.
- Dropped — no text counterpart available; an INFO log records the attachment, model, and reason.
Each prompt-call step emits a routing summary: Attachment routing for step <id> on model <name>: considered=N native=N demoted=N dropped=N — the forensic anchor when "the model didn't see my image" comes up.
See Send a file for the UI / MCP / API flow that uploads a file and attaches it to a run.
Metadata Filters
The Retrieval step supports MongoDB-style metadata filters to narrow results based on document metadata fields. Any step that accepts a filter field uses this same syntax.
Filter Operators
| Operator | Description | Example |
|---|---|---|
$eq | Equals | {"category": {"$eq": "news"}} |
$ne | Not equals | {"status": {"$ne": "draft"}} |
$lt | Less than | {"score": {"$lt": 0.5}} |
$lte | Less than or equal | {"priority": {"$lte": 3}} |
$gt | Greater than | {"word_count": {"$gt": 100}} |
$gte | Greater than or equal | {"published_date": {"$gte": "2026-01-01"}} |
$in | Value in list | {"category": {"$in": ["news", "blog"]}} |
$nin | Value not in list | {"status": {"$nin": ["draft", "archived"]}} |
$exists | Field exists | {"author": {"$exists": true}} |
$regex | Matches regex | {"title": {"$regex": "^Breaking"}} |
$not | Negation | {"status": {"$not": {"$eq": "draft"}}} |
Logical Operators
| Operator | Description |
|---|---|
$and | All conditions must match |
$or | At least one condition must match |
Filter Examples
Simple field match (implicit AND):
{
"category": { "$eq": "technology" },
"status": { "$ne": "draft" }
}
Using $or:
{
"$or": [
{ "category": { "$eq": "technology" } },
{ "category": { "$eq": "science" } }
]
}
Complex nested filter:
{
"$and": [
{ "published_date": { "$gte": "2026-01-01" } },
{
"$or": [
{ "category": { "$in": ["news", "analysis"] } },
{ "priority": { "$gt": 5 } }
]
},
{ "author": { "$exists": true } }
]
}
With substitution variables:
{
"category": { "$eq": "{{metadata.category}}" },
"published_date": { "$gte": "{{metadata.start_date}}" }
}
Step Execution Order
Steps execute as a directed acyclic graph (DAG). In the simplest case, steps run sequentially top-to-bottom. With child steps and parallel branches (via merge wait_for), the execution order follows these rules:
- Root steps execute first, in order
- Child steps execute after their parent completes, receiving the parent's output as input
- Merge steps wait for every sibling step named in their
wait_forlist before executing - Awaited branches may continue running in parallel after the merge fires
- A step only executes after all its dependencies have completed
Step Caching
The Prompt Call and Retrieval steps support result caching to reduce costs and improve performance:
| Field | Description |
|---|---|
extended_caching_days | Cache results for N days. Identical inputs return cached results. |
cache_all_minutes | Cache ALL requests (regardless of input) for N minutes (1–60). Useful for time-insensitive batch operations. |
Caching is particularly useful for:
- Retrieval steps that run on the same knowledge base frequently
- Prompt calls with deterministic outputs (e.g., classification tasks with
temperature: 0) - Reducing credit usage for repeated operations
AI Assistant
The AI assistant helps you configure steps by generating configurations from natural language descriptions. It understands your full agent workflow — including all steps and their relationships — and can suggest appropriate values.
Supported step types:
| Step Type | What the AI Assistant Generates |
|---|---|
| Prompt Call | Model, prompts, temperature, tools, JSON template, formatting — full prompt call configuration |
| Retrieval | Knowledge base, query, filters, reranker, time range, content type — full retrieval configuration |
| Regex Replace | Regex patterns, substitutions, and comments for each rule |
| Gate | Conditions with targets, operators, values, match mode, and on_match |
| Merge | Output template with step references, and content type |
| For Each | Input template, offset, limit, parallel, fail_fast, and fail_on_empty |
| If / Else | Conditions (target, operator, value), match mode, and optional input template for the discriminator |
| Switch | Discriminator template, value type, case names with single-value or list ($in) match patterns |
| Text | Template with substitution variables, and content type |
| Call Agent | Target agent, pass-through settings for input/metadata, and content version |
| Write Memory | Key, speaker, content, and metadata — full write memory configuration |
| Search Memory | Key, query, filters, time range, top_n — full search memory configuration |
| Load Memory | Key, order, limit, and content type — full load memory configuration |
| Extract Data | Prompt, output format, output schema, model, temperature, max tokens — full extract data configuration |
| Write Metadata | Metadata key, content, and content version — full write metadata configuration |
| Write Attachment | Attachment key, content type, content, indexed flag, and content version |
| Load Attachment | Attachment key and content version |
| Load Content | Content version selection |
| Publish Content | Target source, identifier mode, content type, title, content, metadata, suppress triggers |
To use the AI assistant, open a supported step and click the AI Assistant button. Describe what you want in natural language, and the assistant will generate or refine the configuration.
Next Steps
- Agent Triggers — Configure when and how agents run
- Agents Overview — Back to the agents overview
- Knowledge Bases — Connect data sources for retrieval steps
- Content Sources — Understand how content flows into knowledge bases
- Memory Banks — Create and manage persistent memory for your agents
- API Examples — Code samples for working with agents