Pydantic AI Free code examples in Python
Typed agents where the output is validated against a model, not hoped for.
Try it without writing code: Prompt Testing Kit — free in the browser.
WHAT THIS PAGE COVERS
Structured output with retries when validation fails.
gpt-5.4-mini
pydantic-ai
Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.
One package. The model string carries its provider, so there is no separate client package to install for the common providers.
pip install pydantic-ai
export OPENAI_API_KEY="sk-your-key" # macOS / Linux
setx OPENAI_API_KEY "sk-your-key" # Windows, then open a new shell
output_type IS THE SCHEMA. Pydantic generates it, the model is constrained by it, and the reply is validated before you see it — so `result.output.severity` is an enum member, not a string you hope is one of three values.
from enum import Enum
from pydantic import BaseModel, Field
from pydantic_ai import Agent
class Severity(str, Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class TicketSummary(BaseModel):
summary: str = Field(description="One sentence, no jargon.")
error_code: str | None = None
severity: Severity
agent = Agent(
"openai:gpt-5.4-mini",
output_type=TicketSummary,
instructions="You triage support tickets for industrial pumps.",
)
result = agent.run_sync("The pump stalled and threw code E-4471.")
print(result.output.severity, result.output.error_code)
deps_type gives every tool a typed context. RunContext.deps is your database handle or HTTP client — passed in at run time rather than reached for from a global, which is what makes the agent testable.
from dataclasses import dataclass
from pydantic_ai import RunContext
@dataclass
class Deps:
db: object # a real connection in production, a fake in tests
agent = Agent(
"openai:gpt-5.4-mini",
deps_type=Deps,
output_type=TicketSummary,
)
@agent.tool
def lookup_error(ctx: RunContext[Deps], code: str) -> str:
"""Look up what an error code means in the service manual."""
return ctx.deps.db.fetch_error(code)
result = agent.run_sync(
"The pump stalled and threw code E-4471.",
deps=Deps(db=service_manual),
)
THIS IS THE FEATURE. Raising ModelRetry sends the message back to the model as feedback and lets it try again. An exception would end the run; this turns a wrong tool argument into a self-correction.
from pydantic_ai import ModelRetry
@agent.tool
def lookup_error(ctx: RunContext[Deps], code: str) -> str:
"""Look up what an error code means in the service manual."""
if not code.startswith("E-"):
# Not an exception. The model reads this and calls again.
raise ModelRetry(
f"{code!r} is not an error code. They look like E-4471. "
"Re-read the ticket and extract the code."
)
found = ctx.deps.db.fetch_error(code)
if found is None:
raise ModelRetry(f"No manual entry for {code}. Check for a typo.")
return found
# retries caps the loop — without a cap a stubborn model can spin.
agent = Agent("openai:gpt-5.4-mini", deps_type=Deps,
output_type=TicketSummary, retries=3)
@agent.output_validator runs after the schema check and can raise ModelRetry too. Shape is what Pydantic guarantees; RULES are what this hook is for — and a rule the model broke is worth telling it about.
@agent.output_validator
def severity_needs_a_code(
ctx: RunContext[Deps], output: TicketSummary
) -> TicketSummary:
# The type system cannot express "high severity requires a code".
if output.severity is Severity.HIGH and not output.error_code:
raise ModelRetry(
"A high-severity summary must include the error code. "
"Find it in the ticket or lower the severity."
)
return output
result = agent.run_sync(
"The pump stalled and threw code E-4471.", deps=Deps(db=service_manual))
# By here the output is valid in shape AND in rule.
print(result.output)
QUESTIONS
Which languages are the Pydantic AI examples in?
Python. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.
Which package do I install for Pydantic AI?
The samples use pydantic-ai. The install step on each language tab gives the exact command.
Which Pydantic AI model do these examples use?
gpt-5.4-mini, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.
Where is the official Pydantic AI documentation?
https://ai.pydantic.dev/ — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.
ALSO IN FRAMEWORKS & SDKS
The authority
Official Pydantic AI documentation
Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.
https://ai.pydantic.dev/