Design your output schemas
A session's schema is a contract: it's the exact JSON shape the model must return, and it's what every downstream session — and your application — reads. A good schema makes the model more accurate (it knows precisely what to produce) and makes the plan's output easy to consume. This guide covers the full syntax and the design habits that keep schemas clean.
Prerequisites
- The Anatomy of a session guide — you should know where the
schemasits in a session.
The basics
A schema block lists fields and their types:
Syntax rules:
- Field names are unquoted identifiers —
summary, not"summary". - Types:
string,int,float,bool, nested{ }objects,Type[]arrays, and$ComponentNamerefs. - Mark a field optional by appending
?:url?: string. Everything else is required.
Comments are instructions, not decoration
This is the highest-leverage habit in the whole language. Inline # comments on schema fields are read by the model and used as field descriptions:
Those comments meaningfully steer the output. Add one to every field unless the name is completely self-explanatory — they're the cheapest quality win available.
Keep the root flat
The session name is already the outer wrapper for its output. A session called overview publishes under context.overview, so wrapping the fields in another overview object just creates redundant nesting:
Nest only when the data genuinely has sub-structure:
Scalar and array shorthand
When a session's whole output is a single value or a flat list, skip the block and declare the type directly:
This pairs naturally with iterate: an iterating session runs once per element and collects the results into an array, so its schema must be an array — either schema type[] or a block with []:
Reuse shapes with components
When the same structure appears in more than one session, define it once in a root-level components block and reference it with $Name:
Component schemas follow the exact same syntax as session schemas — fields, optionals, comments, nesting. Reference one anywhere a type is expected: sources: $SourceRef[] or primary: $SourceRef.
Sessions without a schema
A schema is optional. Omit it and the session still runs — its output is just the model's raw text response instead of a structured object:
The session's result lands in context.search_web (and in the plan output) as a single string — the model's free-form answer verbatim:
Skip the schema when the session's job is to produce prose for a person to read, or when a downstream session will consume the text as free-form input. Add a schema as soon as you need to reference specific fields (context.search_web.answer), enforce a shape, or hand structured data to another tool — a downstream session can't reach into a raw string.
This example uses the built-in web search tool — see Search the web for how use search works.
Common mistakes
| Mistake | Fix |
|---|---|
| Wrapping fields in a top-level object named after the session | Define fields flat at the root — the session name is the wrapper |
| Quoting field names | Use unquoted identifiers: summary: string |
A non-array schema on an iterate session | Use schema type[] or schema { ... }[] |
| Skipping field comments | Add a # description to every non-obvious field — the model reads them |
Referencing $Name with no components block | Define the type in a root-level components { } block |
Next steps
- Feed schema output between sessions in Data flow: params, vars & context.
- Produce one result per item with
iteratein Control the flow of a plan.
Shape a session's typed output — field syntax, comments the model reads as instructions, flat-vs-nested structure, scalar shorthand, and reusable $Component refs.