Design for reliability
Use structured outputs
Forcing the model to return validated, schema-constrained data removes an entire class of parsing and formatting failures before they can happen.
Why free text is fragile
If your agent returns prose that your code then parses, every small change in wording can break the parse. Structured outputs flip this around: you define a schema, and the model is constrained to fill it. The response is either valid against the schema or rejected, so malformed output never reaches your logic.
How to do it
- Define the shape you want with a schema. Structured Outputs guide and equivalents enforce it at decode time.
- Validate the result against a model such as Pydantic, and reject then retry on anything invalid.
- Libraries like Instructor wire this loop together so you get typed objects back instead of strings.
pythonfrom pydantic import BaseModel, ValidationError
class Refund(BaseModel):
order_id: str
amount_cents: int
reason: str
def parse_refund(raw_json):
# Return a typed object, or None so the caller retries instead of
# acting on malformed output.
try:
return Refund.model_validate_json(raw_json)
except ValidationError:
return None
Validate, do not trust
Schema-valid is not the same as correct. A field can be well-formed and still wrong. Structured outputs remove the format failures so you can spend your reliability budget on the failures that actually require judgment.
Key takeaways
- Constrain the model to a schema instead of parsing free text.
- Validate every response and retry on anything that does not conform.
- Remember valid structure still needs a correctness check on the values.
Further reading
- Structured Outputs guide OpenAIShows how to constrain a model to a schema so its output is always valid and parseable.
- Instructor useinstructor.comWraps the model call so you get back typed, validated objects instead of raw strings to parse.
- Pydantic docs.pydantic.devDefine and validate the data shapes your agent produces, and reject anything malformed.