Structured output
Getting data back instead of prose: a JSON object that matches a schema you defined, so your code can parse it without regex archaeology.
See it
What it is
Structured output means the response comes back as data in a shape you declared: a JSON object matching a schema, ready to hand straight to your code. The real version is enforced by the provider during generation, not requested in the prompt. Strict modes constrain what the model is allowed to emit, often by masking tokens that would break the schema, sometimes by other machinery, and each provider enforces its own supported subset of JSON Schema. However it is implemented, you stop getting a stray 'Sure, here's the JSON:' or an unclosed brace, which is why 'strict' modes are different in kind from asking nicely and hoping. Check which schema features your provider actually enforces before you lean on a regex pattern or a clever union.
Write the schema once in Zod or Pydantic, convert it to JSON Schema, and reuse it to parse the reply so the types match end to end. It is the right tool for extraction, classification, form filling, routing, and anything whose output feeds a function rather than a human. Field names and descriptions do real work here: 'invoice_total_usd' with a description gets filled better than 'amount'.
Gotcha: a valid shape is not a correct answer. The schema guarantees the field exists, never that it is true, and a required field is an order to produce something, which is how you get invented dates. Make anything genuinely optional nullable, give every enum an 'unknown' member, and keep nesting shallow. Twelve levels of nested objects and sixty-value enums measurably degrade quality even when they parse.
Ask AI for it
Convert this extraction call to structured output. Define the shape as a Zod schema, convert it to JSON Schema, and pass it through the provider's strict structured-output setting so decoding is constrained rather than merely requested. Rules for the schema: every field the model might not find is nullable instead of omitted, every closed set is an enum that includes 'unknown', every field carries a one-line description saying what counts, and nesting stops at two levels. Parse the response with the same Zod schema and throw on failure. Do not ask for JSON in the prompt text, do not strip markdown code fences, and do not write a fallback that regexes braces out of prose.