Steps
Steps let an agent move through distinct phases of a session while preserving the full conversation history. When the agent transitions from one step to the next, the history carries over but the system prompt effectively changes.
Most agents do not need steps. A single step with well-written instructions handles the overwhelming majority of use cases. Reach for steps when the agent genuinely moves through phases that benefit from different prompts — for example, triage → research → draft → review.
If you want a fresh context rather than a prompt change, use sub-agents instead. Steps preserve history; sub-agents start fresh.
Define steps on the agent
Steps live in the steps map on the agent, keyed by step name. The
agent entry point is named via first_step_name.
AGENT WITH MULTIPLE STEPS
Code example with json syntax.1
Each step carries its own instructions, reminders,
allowed_tools, and allowed_skills — the same building blocks as a
single-step agent, scoped to just that step. Leaving allowed_tools
unset exposes every tool; an empty list exposes none.
Two fields are specific to multi-step agents: next_steps controls
transitions (covered below), and reentry_step picks which step the
session resumes at when a new user message arrives on a later turn.
Without reentry_step, re-entry happens at whichever step the prior
turn ended on — usually fine, but set it explicitly when you want every
new user turn to start from (say) a triage step.
An output_parser of structured tells the step to emit JSON instead
of free-form text. This pairs especially well with next_steps: a
classifier step emits { "intent": "sales" } and a downstream step
routes on get('$.output.intent') without string parsing. See
Structured outputs for the schema
format.
Transitions
The next_steps array on a step is evaluated after the step's LLM
turn completes. Each entry has a step_name and an optional
condition; the first matching condition wins, and a next_steps
entry with no condition is the catch-all. If nothing matches, the
agent ends the turn in the current step.
Conditions are UserFn expressions using the get() function with
JSONPath. The context exposes four top-level keys:
{
"agent": { ... },
"session": { ... },
"tools": { "<tool_config_name>": { "outputs": { "latest": { } } } },
"output": { ... }
}
Agent and session metadata you set elsewhere is reachable under
$.agent.metadata.* and $.session.metadata.*. The most recent call
of any tool the step used lives at $.tools.<name>.outputs.latest.
$.output is the LLM output of the current step — a text field
under the default parser, or your JSON fields directly under $.output
with a structured parser.
get('$.output.intent') == 'sales'
get('$.session.metadata.tier') == 'enterprise' and get('$.output.urgent') == true
next_steps are evaluated once, after the step's final text turn — not
between tool calls within a step.
Session history across steps
When the agent transitions between steps, the session history is preserved in full. The new step sees all prior user messages, agent outputs, tool calls, and tool outputs — it just applies a different system prompt on top of them. This is the main thing that distinguishes steps from sub-agents, which run with a fresh history.
When to reach for steps
Typical uses:
- Classification and routing. A
classifierstep reads the user input, decides which specialist step should handle the rest, and transitions. - Phase-structured workflows. An investigation that genuinely has distinct gather → analyze → report phases, where each phase benefits from different guidance and tool access.
- Gated escalation. A
supportstep that transitions to anescalate_to_humanstep once a condition is met. - Plan-then-execute. See the dedicated section below.
Plan-then-execute
A plan step with read-only tools produces a structured plan and
writes it to an artifact via artifact_create. An execute step with
write access calls artifact_read to load the plan and carries it
out. Front-loading the thinking keeps the implementation turns focused
and leaves a durable plan the agent can re-read on later turns. This
is the same pattern Claude Code's plan mode uses.
{
"first_step_name": "plan",
"steps": {
"plan": {
"instructions": [{ "type": "inline", "template": "Produce a plan. Do not act. Call artifact_create with the plan." }],
"allowed_tools": ["artifact_create", "search"],
"next_steps": [{ "step_name": "execute" }]
},
"execute": {
"instructions": [{ "type": "inline", "template": "Call artifact_read to load the plan, then carry it out." }],
"allowed_tools": ["artifact_read", "write_file"]
}
}
}
When not to use steps:
- If the phases differ only in tone or style, a single step with good instructions is simpler.
- If you want isolated context for a side task, use a sub-agent.
- If you just need to remind the agent of something as the session grows, use a reminder.
Limits
A single session turn can transition between steps at most 500
times before the platform stops execution with a
step_transition_limit_exceeded event. In practice this only triggers
when two steps ping-pong at each other via mis-written conditions — a
real workflow rarely crosses a dozen transitions. Treat the ceiling as
a loop-breaker, not a budget to spend.
Transitions run serially; an agent is never in two steps at once. Use sub-agents when you need parallel work.
Related
- Context engineering overview
- Sub-agents — the alternative when you want a fresh history instead of a new prompt.
- Instructions · Reminders · Skills — all are step-scoped.