SKILL.md
$27
Quick-Start Patterns
Create a Basic Agent
from pydantic_ai import Agent
agent = Agent(
'anthropic:claude-sonnet-4-6',
instructions='Be concise, reply with one sentence.',
)
result = agent.run_sync('Where does "hello world" come from?')
print(result.output)
"""
The first known use of "hello, world" was in a 1974 textbook about the C programming language.
"""
Add Tools to an Agent
import random
from pydantic_ai import Agent, RunContext
agent = Agent(
'google:gemini-3-flash-preview',
deps_type=str,
instructions=(
"You're a dice game, you should roll the die and see if the number "
"you get back matches the user's guess. If so, tell them they're a winner. "
"Use the player's name in the response."
),
)
@agent.tool_plain
def roll_dice() -> str:
"""Roll a six-sided die and return the result."""
return str(random.randint(1, 6))
@agent.tool
def get_player_name(ctx: RunContext[str]) -> str:
"""Get the player's name."""
return ctx.deps
dice_result = agent.run_sync('My guess is 4', deps='Anne')
print(dice_result.output)
#> Congratulations Anne, you guessed correctly! You're a winner!
Structured Output with Pydantic Models
from pydantic import BaseModel
from pydantic_ai import Agent
class CityLocation(BaseModel):
city: str
country: str
agent = Agent('google:gemini-3-flash-preview', output_type=CityLocation)
result = agent.run_sync('Where were the olympics held in 2012?')
print(result.output)
#> city='London' country='United Kingdom'
print(result.usage)
#> RunUsage(input_tokens=57, output_tokens=8, requests=1)
Dependency Injection
from datetime import date
from pydantic_ai import Agent, RunContext
agent = Agent(
'openai:gpt-5.2',
deps_type=str,
instructions="Use the customer's name while replying to them.",
)
@agent.instructions
def add_the_users_name(ctx: RunContext[str]) -> str:
return f"The user's name is {ctx.deps}."
@agent.instructions
def add_the_date() -> str:
return f'The date is {date.today()}.'
result = agent.run_sync('What is the date?', deps='Frank')
print(result.output)
#> Hello Frank, the date today is 2032-01-02.
Testing with TestModel
from pydantic_ai import Agent
from pydantic_ai.models.test import TestModel
my_agent = Agent('openai:gpt-5.2', instructions='...')
async def test_my_agent():
"""Unit test for my_agent, to be run by pytest."""
m = TestModel()
with my_agent.override(model=m):
result = await my_agent.run('Testing my agent...')
assert result.output == 'success (no tool calls)'
assert m.last_model_request_parameters.function_tools == []
Use Capabilities
Capabilities are reusable, composable units of agent behavior — bundling tools, hooks, instructions, and model settings.
from pydantic_ai import Agent
from pydantic_ai.capabilities import Thinking, WebSearch
agent = Agent(
'anthropic:claude-opus-4-6',
instructions='You are a research assistant. Be thorough and cite sources.',
capabilities=[
Thinking(effort='high'),
WebSearch(),
],
)
Add Lifecycle Hooks
Use Hooks to intercept model requests, tool calls, and runs with decorators — no subclassing needed.
from pydantic_ai import Agent, RunContext
from pydantic_ai.capabilities.hooks import Hooks
from pydantic_ai.models import ModelRequestContext
hooks = Hooks()
@hooks.on.before_model_request
async def log_request(ctx: RunContext[None], request_context: ModelRequestContext) -> ModelRequestContext:
print(f'Sending {len(request_context.messages)} messages')
return request_context
agent = Agent('openai:gpt-5.2', capabilities=[hooks])
Define Agent from YAML Spec
Use Agent.from_file to load agents from YAML or JSON — no Python agent construction code needed.
from pydantic_ai import Agent
# agent.yaml:
# model: anthropic:claude-opus-4-6
# instructions: You are a helpful research assistant.
# capabilities:
# - WebSearch
# - Thinking:
# effort: high
agent = Agent.from_file('agent.yaml')
Task Routing Table
Load only the most relevant reference first. Read additional references only if the task spans multiple areas.
I want to...
Reference
Create/configure agents, choose output types, use deps, define specs, or pick run methods
Bundle reusable behavior or intercept lifecycle events
Add function tools, toolsets, MCP servers, or explicit search tools
Use provider-native web search, web fetch, or code execution
Use advanced tool features such as approval, retries, ToolReturn, validators, timeouts, or tool search
Work with multimodal input, message history, or context trimming
Test or debug agent behavior
Coordinate multiple agents or build graph workflows
Orchestration and Integrations
Call the model directly, expose A2A, use durable execution, embeddings, evals, or third-party integrations
Orchestration and Integrations
Compare abstractions, output modes, decorators, or model-string patterns
Architecture and Decision Guide
Follow an older link into COMMON-TASKS.md
Architecture and Decisions
Load Architecture and Decision Guide only when the user is choosing between abstractions or wants comparison tables and decision trees:
Topic
What it covers
Decision Trees
Tool registration, output modes, multi-agent patterns, capabilities, testing approaches, extensibility
Comparison Tables
Output modes, model provider prefixes, tool decorators, built-in capabilities, agent methods
Architecture Overview
Execution flow, generic types, construction patterns, lifecycle hooks, model string format
Quick reference — model string format: "provider:model-name" (e.g., "openai:gpt-5.2", "anthropic:claude-sonnet-4-6", "google:gemini-3-pro-preview")
Quick reference — key agent methods: run(), run_sync(), run_stream(), run_stream_sync(), run_stream_events(), iter()
Key Practices
- Python 3.10+ compatibility required
- Observability: Pydantic AI has first-class integration with Logfire for tracing agent runs, tool calls, and model requests. Add it with
logfire.instrument_pydantic_ai(). For deeper HTTP-level visibility,logfire.instrument_httpx(capture_all=True)captures the exact payloads sent to model providers.
- Testing: Use
TestModelfor deterministic tests,FunctionModelfor custom logic
Common Gotchas
These are mistakes agents commonly make with Pydantic AI. Getting these wrong produces silent failures or confusing errors.
- **
@agent.toolrequiresRunContextas first param**;@agent.tool_plainmust not have it. Mixing these up causes runtime errors. Usetool_plainwhen you don't need deps, usage, or messages.
- Model strings need the provider prefix:
'openai:gpt-5.2'not'gpt-5.2'. Without the prefix, Pydantic AI can't resolve the provider.
- **
TestModelrequiresagent.override()**: Don't setagent.modeldirectly. Always use the context manager:with agent.override(model=TestModel()):.
- **
strin output_type allows plain text to end the run**: If your union includesstr(or nooutput_typeis set), the model can return plain text instead of structured output. Omitstrfrom the union to force tool-based output.
- **Hook decorator names on
.ondon't repeaton_**: Usehooks.on.run_errorandhooks.on.model_request_error— nothooks.on.on_run_error.
- **
history_processorsis deprecated; usecapabilities=[ProcessHistory(p), ...]**, or hookbefore_model_requestdirectly viacapabilities=[Hooks(before_model_request=fn)].ProcessHistoryis a thin wrapper around that hook — the hook itself is the underlying primitive. The kwarg still works in 1.x but emits aPydanticAIDeprecationWarningand will be removed in v2.
Task-Family References
Load exactly one of these unless the task clearly spans multiple families:
Task family
Reference
Core agent setup, output, deps, specs, models, run methods
Capabilities, hooks, and reusable behavior
Function tools, toolsets, MCP, explicit search tools
Provider-native tools
Approval, retries, validators, timeouts, rich tool returns, deferred loading
Multimodal input, message history, history processors
Testing, request inspection, and Logfire debugging
Multi-agent patterns, graphs, direct API, A2A, durable execution, embeddings, evals, third-party integrations
Orchestration and Integrations
Use Task Reference Map only for compatibility with older links or when you need a pointer from an old section name to the new file.