A model that answers well in a chat window is not yet usable in a system. The moment the output feeds a database write, an API call or a decision, it has to arrive in a predictable shape every single time, and prose does not do that. Structured output is what closes that gap.
Getting structured output right is the least glamorous part of building with language models, and it accounts for a large share of the reliability problems that reach production.
Asking politely does not scale
The first approach everyone tries is instructing the model to reply in JSON. It works most of the time, which is the problem. At a few percent failure it is fine in testing and a recurring incident at volume, and the failures are irritating in specific ways: a markdown code fence wrapped around the JSON, a trailing comma, an apologetic sentence before the object, a field renamed slightly.
Parsing defensively around all of that is possible and it is a permanent tax on the codebase, paid every time the prompt or the model changes.
Constrain the format properly
Most providers now support enforcing a schema at generation time, so the output is structurally guaranteed to match. This removes an entire class of failure and it should be the default for anything programmatic.
- Define the schema once and share it between the request and the code that consumes the response, so they cannot drift apart.
- Keep it as flat as the task allows. Deeply nested structures raise the error rate on the content even when the shape is guaranteed.
- Use enums wherever the answer belongs to a known set, which converts an open question into a closed one.
- Include an explicit way to say the answer is unavailable, or the model will invent a plausible value to satisfy the required field.
That final point causes more trouble than the rest combined. A schema that demands a date will get a date, whether or not the source document contained one.
Guaranteeing the shape moves the failure rather than removing it. You stop getting malformed JSON and start getting well-formed JSON with a confidently wrong value in it.
Lena Fischer, Solutions Architect, Engineered With AI
Validate meaning, separately
Schema validation confirms the response is the right shape. It says nothing about whether the content is right, so a second layer is needed and it is ordinary code rather than anything clever.
Check that extracted values actually appear in the source where they should. Check that numbers fall in plausible ranges, that dates sit inside the period the document covers, that totals reconcile with their components, that identifiers match a known list. These checks are cheap, deterministic and catch the errors the schema cannot.
Decide what a failed validation does
Retrying the same prompt after a failure often produces the same failure. Retrying with the validation error included as context works considerably better, because the model is given the specific problem rather than asked again.
Cap the retries, and route anything that fails twice to a person rather than looping. An unbounded retry against a genuinely ambiguous input is how a batch job burns a day of budget overnight.
Version the schema like an interface
The schema is a contract between the model and everything downstream, so it deserves the same discipline as any API. Adding an optional field is safe. Renaming one, changing a type or tightening an enum will break consumers, and the breakage tends to surface somewhere unrelated and days later.
Keep the schema in version control next to the prompt that produces it, and treat a change to either as a change to both. They are one unit and separating them is how a working pipeline quietly stops matching its own tests.
Test the shape and the substance
A small set of held-out examples with known correct answers, run whenever the prompt, schema or model version changes, is the difference between noticing a regression in an afternoon and hearing about it from a customer.
Keep the failures in that set permanently. Every case that went wrong in production and got fixed should become a test, otherwise the same class of problem returns the next time something upstream changes. More on how this fits a wider build is in the integration approach we use.
Fighting unreliable model output?
We will look at where your pipeline breaks and put proper validation between the model and the rest of your system.





