Skip to main content
Structured output forces the agent to produce validated JSON conforming to a schema you provide. The extraction runs as a separate turn after agentic work completes, with automatic retry on validation failure. Schemas are normalized across providers — the same schema works with Anthropic, OpenAI, and Gemini, with provider-specific lowering handled transparently.
This page is the task-first guide. For the low-level schema/type inventory, see Structured output reference.

What this guide is for

Use this guide when you want to:
  • extract validated JSON from an agent run
  • choose schema compatibility behavior
  • understand retry and warning behavior

How it works

When output_schema is configured on an agent, the execution flow is:
1

Agentic loop runs normally

The agent processes the prompt, calls tools, and iterates until no more tool calls remain.
2

Extraction turn fires

An additional LLM call is made with no tools and a prompt asking for valid JSON matching the schema. Extraction requests temperature 0.0 where the provider/model supports it; lowering may omit unsupported parameters. This does not guarantee deterministic output.
3

Validation

The response is parsed as JSON and validated against the schema using the jsonschema crate’s Validator.
4

On success

RunResult.structured_output contains the parsed serde_json::Value.
5

On failure

Retries validation failures up to structured_output_retries times with error feedback, then returns the completed main run with RunResult.extraction_error.

Event lifecycle

The event stream preserves the boundary between completed agentic work and the post-main extraction phase. After provider schema compilation succeeds and the main turn is accepted, Meerkat emits:
It then emits exactly one extraction terminal:
or:
Extraction attempts do not publish ordinary streamed text or additional turn_completed events. A failed extraction is not a run_failed event: the main agentic run completed, and RunResult.extraction_error carries the post-main failure. Provider schema compilation is a fallible setup boundary. If it fails before the main turn can be accepted, Meerkat emits extraction_failed without first emitting success-shaped turn_completed or run_completed events. This keeps an invalid provider lowering from being advertised as a completed run.

Schema types

OutputSchema

The primary schema type:

Construction methods

Builder methods

OutputSchema supports a wrapper format for explicit configuration. If the JSON object contains a schema key and either a format: "meerkat_v1" marker or only wrapper keys (schema, name, strict, compat, format), it is parsed as a wrapper:
Otherwise, the entire JSON value is treated as a raw schema.

MeerkatSchema

Newtype around serde_json::Value with normalization:
  • Constructed via MeerkatSchema::new(Value) which applies normalize_schema().
  • Normalization: ensures all object-typed nodes have properties and required keys (inserting empty defaults if missing). This prevents provider-specific compilation issues.
  • Returns SchemaError::InvalidRoot if the root is not a JSON object.

SchemaFormat

Schema format versions:

SchemaCompat

Compatibility mode for provider-specific schema lowering:

SchemaWarning

Warnings emitted during schema compilation:

CompiledSchema

Provider-compiled schema output:

SchemaError

Schema errors:

Extraction turn details

The extraction turn logic:

Attempt flow

  1. Max attempts = structured_output_retries + 1 (default: 2 + 1 = 3 attempts).
  2. First attempt prompt: "Provide the final output as valid JSON matching the required schema. Output ONLY the JSON, no additional text or markdown formatting." (overridable via the extraction_prompt config field)
  3. Retry prompt (on validation failure): "The previous output was invalid: {error}. Please provide valid JSON matching the schema. Output ONLY the JSON, no additional text."
  4. LLM is called with no tools. Core requests temperature 0.0; provider lowering may omit it when unsupported by the model. Output is not guaranteed to be deterministic.
  5. Response text is trimmed, then markdown code fences are stripped (handles ```json and ``` wrappers).
  6. Parsed as JSON via serde_json::from_str.
  7. Validated against the compiled schema via jsonschema::Validator.
If Meerkat is built without the jsonschema feature, configuring an output_schema fails closed: extraction surfaces a typed InvalidOutputSchema error rather than returning unvalidated JSON as if it had passed.

On success

Returns RunResult with:
  • text: the committed main-turn assistant output
  • structured_output: Some(parsed_value) — the validated JSON
  • schema_warnings: any warnings from schema compilation
  • turns: includes extraction attempts in the count

On failure

Returns Ok(RunResult) for the completed main run with structured_output: None and extraction_error: Some(error):
Extraction failure can come from validation exhaustion, provider errors, hook or budget denial, schema compilation failure, or tool-call-shaped output during the post-main-turn extraction phase.

Provider schema compilation

The AgentLlmClient trait includes a compile_schema() method:
The default implementation passes through the normalized schema without provider-specific lowering. Provider adapters override this to apply transformations:
  • Anthropic: may add additionalProperties: false to object nodes
  • Gemini: may strip unsupported JSON Schema keywords
  • OpenAI: may apply strict-mode transformations
Schema warnings are collected during compilation and included in RunResult.schema_warnings.

Configuration

Agent config fields

Usage

The --schema flag accepts either a file path or inline JSON. The CLI detects files by checking if the value is an existing path.

Wire parameters

Structured output is passed directly on the normal per-request session surfaces:

RunResult fields

When structured output extraction succeeds, the RunResult contains:
The structured_output field is Some(value) when extraction succeeds and None when no schema was configured or extraction failed. The text field remains the committed main-turn assistant output.

SDK usage

Basic structured output

Using from_type with schemars

Handling the result

See also