Skip to main content
Each step, the decoder is constrained to emit one JSON object matching your schema, with the tool call as a field inside it, so output is always valid JSON. Read Core concepts first.

Output JSON

string | null
The model’s durable memory: facts from the current screen that later steps need (URLs, IDs, partial answers). null when nothing is new.
string
required
A one-line plan for the next action.
object
required
One variant of your tool union. Flat: tool_name sits next to the arguments, not in a nested args object.

Constrain output to a tool union

Define each tool as a Pydantic model with a Literal tool_name, and use their union as the schema. The decoder emits exactly one variant, and you dispatch on tool_name.
Python
In TypeScript, write the same JSON Schema by hand: a oneOf of tool objects, each with tool_name: { const: "..." }.

Chat layout

Tool results go back as user messages wrapped in <tool_output tool="...">, not as tool messages:

A complete loop

Plug in your own observation() (the <observation> message from Core concepts) and execute(tool_call).
Python

Format-specific pitfalls