agent step runs a bounded tool-calling loop and returns structured JSON conforming to a schema you declare — or says it couldn’t, via final: false. It is a functional component, not a conversation: a prompt goes in, a validated object comes out.
Use it for the one thing plans genuinely can’t express — a task where which tools to call, and how many times, depends on what earlier calls returned. Everything else belongs in ordinary steps, where dataflow is typed and inference-free.
Input
Write
prompt as a plain task description — what to do and what a complete
answer looks like. The built-in system prompt handles how it is being run:
the output_schema it must match, that it should accomplish the task in as few
turns as it can, and that independent tool calls belong in one turn. Repeating
any of that in prompt is redundant; if an agent is misbehaving in a way that
would apply to every agent, that belongs in the harness, not in your plan.
A round is one model call, including the one that produces the final answer — so max_iterations: 1 can answer from the prompt alone but can never call a tool and answer. A malformed answer (schema miss, or no text and no tool call) also costs a round; retries and provider failover do not.
Field names are snake_case, like every other part of a plan file. The camelCase spellings (outputSchema, maxIterations, systemPrompt) still load, but any authoring command that rewrites the file normalizes them.
output_schema’s value is yours: graph never rewrites the property names inside the schema, so an agent can be held to a camelCase contract if that is what its consumer expects.
The whole input is checked at load time, wherever the step appears — top level or inside a decide/map/reduce body: unknown fields, a non-string prompt, output_schema that isn’t valid object-typed JSON Schema, a max_iterations under 1, an empty tools, and template references that point forward or at nothing. A malformed agent step never reaches the run.
Result
{{E1.output.blocked}} — output is the schema-conforming payload; the rest is provenance.
The last round is the answer round
An agent’s final round is handled differently: its tools are withdrawn, the provider is told to forceoutput_schema, and the agent is told plainly that
this is its last turn and it should answer with what it has.
That makes running out of budget degrade instead of collapse. The agent
returns final: true carrying whatever it managed to establish, rather than
throwing the work away — a partial dossier is worth something; an empty object
is worth nothing. It also means the forced round never needs a schema-repair
pass, because the provider guarantees the shape.
So final: false is now rare: it means the final round produced neither
structured output nor usable text. Keep checking it — the guarantee is still
“conforming output, or final: false”, never a fabricated result — but expect
a real answer from a budget that runs out.
One consequence worth planning around: the agent cannot call a tool on its
last round, so a budget of N buys N−1 rounds of tool use.
max_iterations: 1 answers from the prompt alone, as documented above.
The agent is not told how many rounds it has. It is told to accomplish the
task in as few turns as it can, and the forced final round is the backstop.
Naming a number invites a model to treat it as an allowance to spend, and it
competes with whatever your own prompt says about how much ground to cover.
final is false when even the forced final round produced nothing usable. In
that case output is {} and does not conform to output_schema. A later
step reaching into output then fails as a bad path, so check it, or gate
on it:
Tool selection
tools accepts exact names and * wildcards anywhere: linear__*, *__search, linear__list_*, or * for everything.
Patterns are resolved against the catalog at validate time, so a plan naming tools that cannot load fails before it runs — like any other step tool name:
builtin__*, user__*, and plan__* resolve exactly. MCP patterns resolve at the server level only, because listing a server’s tools means connecting to it; the individual tool is still checked at dispatch. A pattern that matches nothing at run time is an error naming that pattern — a typo shrinks the catalogue silently otherwise.
plan_and_execute is never available inside an agent: nested planning loops have no coherent cost boundary. It is not advertised, and a model that asks for it anyway gets a tool error rather than a nested planner run. plan__* tools are available and work normally, so compose with plans instead.
What it costs
An agent step is the most expensive thing in the pipeline: one inference per round, plus its tool calls. Amax_iterations: 8 agent can cost 8 inferences where an ordinary step costs zero. Reach for map with a per-item inference before reaching for an agent — see iteration.
Rounds are not the whole bill. Two multipliers are easy to miss:
- Each round re-sends the conversation so far. Input tokens grow with the square of the round count, not linearly, so a long agent’s cost is dominated by its input. Prompt caching is on by default and takes most of that back — round N reads everything through round N−1 at ~0.1× — but only while the prefix stays byte-stable.
- Schema repair is uncapped. Output that misses
output_schemagets arepair-role fix-up that does not consume a round, so amax_iterations: 8agent can make up to 16 calls. Repairs are attributed to the agent’s step, so the reported figure is the real one. - Inside a
map, multiply by the item count. Six items atmax_iterations: 18is up to 108 rounds.
max_iterations is a ceiling the agent never sees, not a target it aims at —
set it to what the task could plausibly need in the worst case, not to what you
expect it to use. A well-scoped task finishes well inside it.
Don’t estimate any of this — measure it. Every run reports per-step tokens and
cost:
by_step sorts most expensive
first. See what a run spent.
Inside control-step bodies
agent is a legal body step for decide, map, and reduce, and the body scope reaches its prompt:
{{item}}, {{index}}, and {{accumulator}} all resolve. Note the multiplier: this runs one agent per item.
The other control steps (exit, decide, map, reduce) still cannot nest in a body — call a plan__* for that.
Errors
- Tool failures return into the loop as error results, so the agent can explain or route around them. They do not fail the step.
- Reasoning carries across rounds. The model’s own thinking blocks are preserved and replayed, so it builds on what it worked out rather than re-deriving it each round.
- Output that doesn’t match
output_schemagets onerepair-role fix-up pass; if that fails, the error goes back to the agent and consumes a round. - Transient LLM errors retry with backoff and never consume a round.
- A gate abort during an inner tool call is a hard stop, exactly as elsewhere — see errors and replanning.
- Empty data while rendering
promptorsystem_promptdegrades rather than failing, consistent with every other step — at the top level and inside a body alike.
E1/agent.2/linear__list_issues at the top level, E1/do.3/agent.2/linear__list_issues for an agent in a map body — so a breakpoint on the agent step pauses each call it makes, and concurrent map items stay distinguishable.