# Structured outputs, defensively

## The steps

1. Define the schema with `type: json_schema` and `strict: true` in the text format. Strict mode constrains the model to your schema; without it you get JSON-ish output that breaks your parser on the tenth call.
2. Keep the schema tight: required fields listed, enums where the values are known, no free-form objects where a typed field works. Every loose field is a future parsing bug.
3. Handle refusals. A model can refuse even with a schema set; the response will carry a refusal instead of your object. Check for it explicitly and route refusals to a fallback path, not into your JSON parser.
4. Validate the parsed object against the schema in your code anyway. Strict mode is strong but your downstream code should never trust a network response blindly.
5. On validation failure, retry with the error fed back: tell the model what failed validation and ask again. One guided retry fixes most malformed outputs; more than two retries means the schema or prompt needs work, not more attempts.
6. Version the schema with the prompt. When the schema changes, the eval for that output changes too.

## The trap

Parsing without checking for refusals, or retrying blindly without telling the model what was wrong. The first crashes; the second burns tokens repeating the same mistake.

## Checklist

- json_schema with strict true on every structured call.
- Refusal checked before parsing.
- Parsed output validated in code.
- Retry feeds the validation error back, capped at two.
- Schema versioned alongside the prompt.