Skip to main content
Version: 2.0

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 classifier step 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 support step that transitions to an escalate_to_human step 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.