Structured Outputs
Most APIs treat "respond in JSON" as a polite request the model usually honors. This server enforces it: a declared schema is compiled into a grammar that constrains decoding token by token, so the completion cannot be anything but a valid instance of the shape you asked for. No retry loops, no "extract the JSON from the reply" post-processing, no 99%-of-the-time parsers in production code.
1Where it is served#
| Surface | The declaration |
|---|---|
POST /v1/chat/completions |
response_format with type json_object (any valid JSON) or json_schema (your schema, enforced) |
POST /v1/responses |
text.format with the same two types, same enforcement (Responses and Vector Stores) |
| Documents | Structured Extraction is the document-native surface, with confidence, coordinates, and review flags on top of the same guarantee |
A response_format the server cannot honor is refused up front as a fast, OpenAI-shaped
400 naming the field, before any device work: the guarantee holds by construction or the
request does not run.
2How the guarantee works#
The schema compiles to a grammar; during generation, every candidate token that would leave the grammar is masked before sampling. The model is not being asked and checked, it is physically unable to emit an invalid byte sequence. Consequences worth internalizing:
- Validity is not quality. The shape is guaranteed; the VALUES are still the model's judgment. A weak model produces well-formed nonsense. Structure solves parsing, your evaluation solves truth (Measuring What Matters).
- Constrained decoding pairs with clear prompting. The grammar forces the format; the prompt still owes the model an explanation of what the fields mean. Field names and descriptions in the schema are read by the model and are worth writing well.
json_objectis the loose mode: valid JSON, shape unspecified. Use it only when any object will do;json_schemais the one that removes classes of bugs.
3The schema dialect#
The enforced subset of JSON Schema is the same dialect, compiled by the same engine, as Structured Extraction uses; the complete keyword-by-keyword reference, including enums, arrays, nesting, and the enforcement layers, is The Extraction Schema Reference. Write the schema once and it means the same thing on chat, on Responses, and on documents.
4Choosing between chat schemas and document extraction#
Both end in validated JSON; they answer different questions:
| You have | Use |
|---|---|
| A conversation, an instruction, free text you composed into the prompt | response_format / text.format on the chat surfaces |
| A document (PDF, image, Office file) whose fields you want out | Structured Extraction: it adds per-field confidence, page coordinates, validation, and review flags the chat surfaces do not have |
The tell: if you would benefit from "where on the page did this value come from" or "should a human check this one", you wanted extraction, not a chat schema.
5Streaming, usage, and tools#
Structured output composes with the rest of the contract: streaming delivers the constrained completion as ordinary deltas (the guarantee applies to what streams, not only to a final buffer), non-streaming responses carry the usage block (with a reasoning-token breakdown on reasoning models), and function calling is its own structured channel: tool ARGUMENTS follow the tool's parameter schema through the same kind of constraint, which is why tool calls parse too.
6Stated plainly#
json_schemahere is enforcement, not encouragement: invalid output is impossible, and an unservable format refuses up front by name.- One schema dialect across chat, Responses, and document extraction, documented once in the schema reference.
- Guaranteed shape is not guaranteed truth: keep evaluating values, stop parsing defensively.
- For document fields, prefer Structured Extraction; it adds the evidence trail a schema alone cannot carry.