result.final_output comes back as an instance of that model — already validated, with the right types.
Ask for a shape
json.loads, no prompt asking nicely for JSON. The schema goes to the provider, the provider constrains the model to it, and Agentor validates what comes back before handing it to you.
Nest and make things optional
Models can contain other models, and fields can be optional. Both survive the round trip:An optional field still appears in every response — the model fills it with
null rather than leaving it out. That is what the provider’s strict mode requires, and Pydantic turns it back into None.Open-ended dictionaries are not supported
A field likedict[str, int] accepts any keys at all, and strict structured output has no way to describe that. Agentor rejects it when you build the agent, rather than letting the provider reject it mid-run:
When output does not match
If the model returns something that fails validation, the run raises rather than handing you a half-filled object:instructions line describing what each field means usually fix it.
Tools and structured output together
They compose. The agent calls whatever tools it needs, and shapes only the final answer:Streaming returns text, not the object
stream_chat() yields the model’s raw JSON as it arrives, because there is no object to hand over until the last token lands:
agent.run() or await agent.arun() when you want the parsed object.
Next steps
Durable runs
Save a run so another process can finish it after a crash.
Model providers
Structured output works against any OpenAI-compatible provider.
