Overview

Structured output makes a model return data that matches a schema, usually JSON Schema, so code can parse it without regex extraction. There are three levels. A prompt that asks for a format (a “structured prompt”) is weakest; the model can still deviate. JSON mode guarantees valid JSON but not your schema, and OpenAI recommends structured outputs instead. Schema-constrained decoding guarantees the schema: Claude uses output_config: {format: {...}} (the older top-level output_format is deprecated) and strict: true on a tool definition for schema-valid tool input; OpenAI uses text.format with type: "json_schema" and strict: true. Open-weights runtimes get the same guarantee from grammar-constrained decoding (llama.cpp grammars, Outlines). Use the strongest level whenever a program reads the response.

Validate anyway. A valid schema does not make the values right. Check business rules the schema cannot express (start_date < end_date, quantity > 0) with Pydantic or Zod where the response enters your code, and on failure retry once or log, never silently fill a default. Keep schemas small, with few required fields.

On Claude 4.6 and later models, assistant-message prefill returns a 400, and so does forced tool_choice on Fable 5.1, Opus 5.5, and Sonnet 5.5; use structured outputs instead. Citations cannot be combined with output_config.format.

Example

{
  "type": "object",
  "properties": {
    "priority": { "enum": ["P0", "P1", "P2", "P3"] },
    "needs_human": { "type": "boolean" }
  },
  "required": ["priority", "needs_human"],
  "additionalProperties": false
}
ticket = Ticket.model_validate_json(response.content[0].text)  # Pydantic; raises if invalid