Aex Brain
Guides

Structured output

Request a typed answer on an individual send using a Zod schema.

Pass output: { type: schema, maxRetries: 2 } in the second argument to session.send. The SDK adds the schema to the prompt, reads that completed turn's assistant output, parses JSON, and validates it locally with Zod. The returned value has the schema's inferred output type. Omitting output preserves the normal session-state return value.

The executable structured-output example extracts a person's name and age. It uses the same server and compiled Agentloop setup as the other repository examples. Set BRAIN_AGENTLOOP_WASM to a Component that emits assistant output, such as the published Pi or Codex Component.

Validation and corrections

maxRetries counts additional correction turns and defaults to two: one initial answer and at most two corrections. Zero validates only the first answer. Invalid JSON or Zod validation issues cause a follow-up message asking for a complete corrected answer. Fenced JSON and surrounding prose fail JSON parsing.

Normal Zod parsing semantics apply: z.object strips unknown properties, while z.strictObject rejects them. Defaults and transforms apply locally. The prompt describes the schema's input shape; the return value is its parsed output. Async refinements and transforms are supported. Custom refinements run locally and may need descriptions or correction feedback to explain constraints to the model. Schemas whose input shape cannot be converted to JSON Schema fail before sending. Exceptions thrown by custom validation code propagate without correction retries.

Exhaustion throws the exported StructuredOutputError, with attempts, lastOutput, and issues. Provider, transport and unsupported-output failures propagate without automatic retries. No provider-native response format is set; avoid conflicting session-level responseFormat settings.

Session behavior

Each attempt is an ordinary durable turn. Corrections can invoke the session's tools: the SDK asks the agent not to repeat actions but cannot enforce that through a prompt. Model and tool calls inside a turn are additional to the retry count.

The caller runs validation and retries. If the calling process exits, the SDK does not schedule further attempts. Invalid answers and corrective messages remain in history. A locally rejected answer can still belong to a successfully completed server turn. Streams expose raw, provisional output; the returned value is validated.

Use one caller for the session during a structured send. Overlapping sends through the same handle are rejected while it is running; other handles and processes require application coordination. Optional signal stays alongside output and cancels the current turn and stops corrections. An asynchronous custom validator finishes before its result is checked for cancellation.

An explicit idempotencyKey identifies the first turn; correction turns use distinct derived keys. Repeating the same operation reuses completed turns when its prompts and validation feedback are identical. This is not an atomic server operation or a cross-process retry scheduler; nondeterministic validation can conflict on replay.

The loop must emit output_emitted with an Agentloop-origin { type: "assistant_message", message: string } payload. Pi and Codex use this convention; the minimal reference loop does not. The SDK selects the last such message in the exact completed turn and fails clearly if it is absent. It does not scrape internal model calls or classify refusals from arbitrary output text.

On this page