Skip to content
/

PydanticAI

pydantic-ai · pydantic/pydantic-ai · ★ 17k · last commit 2026-05-26

Primitive shape
No installable primitives
00

Summary

PydanticAI — Summary

PydanticAI (17k stars, MIT) is a Python agent framework by the Pydantic team that brings FastAPI-style ergonomics to GenAI development: typed dependency injection, Pydantic-validated structured outputs, and full static type checking from IDE to runtime. The Agent[DepsT, OutputT] generic class is parameterized on dependency type and output type, enabling the IDE/pyright to infer the exact output type from the agent definition. Tools are registered via decorators (@agent.tool, @agent.instructions) with RunContext[DepsT] carrying injected dependencies. The library ships 20+ provider adapters (OpenAI, Anthropic, Google, DeepSeek, Grok, Cohere, Mistral, Perplexity, Azure, Bedrock, Ollama, LiteLLM, Groq, OpenRouter, Together, Fireworks, Cerebras, Hugging Face, Vercel, Heroku, SambaNova), a pydantic_graph module for complex state machine workflows, a CLI (pai/clai), an evals system, durable execution, MCP client/server support, A2A protocol, AG-UI streaming event standard, human-in-the-loop deferred tool approval, and 40+ built-in capabilities (Thinking, WebSearch, WebFetch, Hooks, MCP, ToolSearch, Instrumentation). The harness at ai.pydantic.dev/harness/ provides a curated capability library. Compared to seeds, PydanticAI is closest to claude-flow in TypeScript, but as a Python SDK it most resembles the typed-SDK ethos of FastAPI applied to agents — a pattern no seed exhibits.

01

Overview

PydanticAI — Overview

Origin

Built by Samuel Colvin, Marcelo Trylesinski, David Montague, Alex Hall, and Douwe Maan at Pydantic. Released 2024. Used to build Pydantic Logfire (their observability product). The framework is dogfooded by the team building it.

Philosophy

From the README:

"Pydantic AI is a Python agent framework designed to help you quickly, confidently, and painlessly build production grade applications and workflows with Generative AI."

"FastAPI revolutionized web development by offering an innovative and ergonomic design, built on the foundation of Pydantic Validation and modern Python features like type hints. Yet despite virtually every Python agent framework and LLM library using Pydantic Validation, when we began to use LLMs in Pydantic Logfire, we couldn't find anything that gave us the same feeling. We built Pydantic AI with one simple aim: to bring that FastAPI feeling to GenAI app and agent development."

The "FastAPI feeling" is the core promise: type safety, dependency injection, minimal boilerplate, and IDE auto-completion as first-class design goals — not afterthoughts.

Design pillars

  1. Generic typed agents: Agent[DepsT, OutputT] — IDE and pyright infer output type from definition
  2. Dependency injection: RunContext[DepsT] carries injected dependencies to tools and instructions
  3. Pydantic validation on output: output_type=SupportOutput guarantees the output matches the schema; agent re-prompts on validation failure
  4. Model-agnostic: 20+ provider adapters via a unified Model protocol
  5. Capabilities: composable units bundling tools, hooks, instructions, model settings
  6. Durable execution: pause/resume across API failures and restarts without code changes
  7. pydantic_graph: state machine workflows for complex control flow

Key quote

"Why use the derivative when you can go straight to the source? Pydantic Validation is the validation layer of the OpenAI SDK, Google ADK, Anthropic SDK, LangChain, LlamaIndex, AutoGPT, Transformers, CrewAI, Instructor and many more."

This positions PydanticAI as the original source of the type validation that powers all other frameworks.

02

Architecture

PydanticAI — Architecture

Distribution

  • Type: pip-package
  • PyPI name: pydantic-ai (meta-package) + pydantic-ai-slim (core)
  • Install: pip install pydantic-ai
  • Required runtime: Python ≥ 3.10
  • License: MIT

Workspace packages

Package Purpose
pydantic-ai Meta-package with all extras
pydantic-ai-slim Core framework without provider adapters
pydantic-evals Evaluation harness
pydantic-graph State machine workflow engine
pydantic-ai-examples Example applications

CLI scripts

  • pai — legacy CLI (deprecated, maps to clai)
  • clai — current CLI (pydantic_ai._cli:cli_exit)

Source layout (pydantic_ai_slim/pydantic_ai/)

agent/              # Agent class implementation
models/             # 20+ provider adapters
capabilities/       # Composable capability classes
toolsets/           # Tool collection management
durable_exec/       # Durable execution
mcp.py              # MCP client
_a2a.py             # A2A protocol
ag_ui.py            # AG-UI streaming events
_spec.py            # YAML/JSON agent spec
run.py              # Agent run execution
result.py           # Run result types
messages.py         # Message types
output.py           # Output types
_agent_graph.py     # Internal agent graph
pydantic_graph/     # State machine graphs

Provider adapters (models/)

anthropic, openai, gemini, google, bedrock, cohere, groq, mistral, huggingface, ollama, openrouter, cerebras, xai, wrapper (generic), instrumented, test (mock)

Key types (generic)

Agent[DepsT, OutputT]       # parameterized agent
RunContext[DepsT]            # dependency-injected context
AgentRun[DepsT, OutputT]    # agent run context manager
AgentRunResult[OutputT]     # typed result
03

Components

PydanticAI — Components

Core classes

Name Purpose
Agent[DepsT, OutputT] Generic parameterized agent class
RunContext[DepsT] Dependency-injected execution context
AgentRun Context manager for a single agent run
AgentRunResult[OutputT] Typed result with .output property
ModelSettings Per-agent model configuration
ToolManager Tool registration and execution

Built-in capabilities (capabilities/)

Capability Purpose
Thinking Enable chain-of-thought thinking
WebSearch Provider-adaptive web search
WebFetch Fetch and parse web pages
MCP Connect to MCP servers
Hooks Lifecycle event hooks
Instrumentation OpenTelemetry tracing
ToolSearch Dynamic tool discovery
ImageGeneration Image generation tools
ProcessEventStream Event stream processing
ProcessHistory Conversation history management
HandleDeferredToolCalls Human-in-the-loop approval
PrefixTools Add prefix to tool names
PrepareTools Dynamic tool preparation
ReinjectSystemPrompt Re-inject system prompt
NativeTool Provider-native tools
XSearch X (Twitter) search
ThreadExecutor Thread pool execution
Toolset Tool collection
WrapperCapability Capability composition

Provider adapters (20+)

anthropic, openai, gemini (Google), google, bedrock, cohere, groq, mistral, huggingface, ollama, openrouter, cerebras, xai, wrapper, test

Pydantic Harness capability library

Third-party and official capabilities at ai.pydantic.dev/harness/.

pydantic_graph

State machine workflow engine: typed nodes, edges with conditions, cycle detection, visualization. Used for complex agent control flows that would otherwise become "spaghetti code."

Evals (pydantic_evals)

Evaluation harness for offline testing of agent behavior with Pydantic Logfire integration.

05

Prompts

PydanticAI — Prompts

Verbatim: Bank support agent instructions

support_agent = Agent(
    'openai:gpt-5.2',
    deps_type=SupportDependencies,
    output_type=SupportOutput,
    instructions=(
        'You are a support agent in our bank, give the '
        'customer support and judge the risk level of their query.'
    ),
)

Technique: Static string system prompt with output_type=SupportOutput forcing structured output. The Pydantic model's field descriptions (description='Advice returned to the customer') serve as additional implicit prompt context injected into the JSON schema provided to the LLM.

Verbatim: Dynamic instructions via decorator

@support_agent.instructions
async def add_customer_name(ctx: RunContext[SupportDependencies]) -> str:
    customer_name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
    return f"The customer's name is {customer_name!r}"

Technique: Dependency-injected dynamic instruction. The returned string is appended to the static instructions at run time. RunContext[SupportDependencies] provides type-safe access to the injected deps. Type errors in the function signature are caught at write time by pyright/mypy.

Verbatim: Tool docstring as LLM description

@support_agent.tool
async def customer_balance(
    ctx: RunContext[SupportDependencies], include_pending: bool
) -> float:
    """Returns the customer's current account balance."""
    # docstring drives the tool description in LLM API call
    balance = await ctx.deps.db.customer_balance(
        id=ctx.deps.customer_id,
        include_pending=include_pending,
    )
    return balance

Technique: Docstring-as-tool-description (same as PEP 257 convention). Parameter descriptions are extracted from the function signature's type annotations and docstring, building the JSON schema sent to the LLM.

YAML/JSON agent spec

_spec.py implements load_from_registry for defining agents entirely in YAML/JSON — no Python required for simple agents.

09

Uniqueness

PydanticAI — Uniqueness

Differs from seeds

No seed brings FastAPI-style typed dependency injection to agent development. The closest seeds in spirit are spec-kit (both care about type safety and contracts) and claude-flow (both are full-featured Python/TS SDKs), but PydanticAI is uniquely about making the IDE and type checker your co-designer. Agent[SupportDependencies, SupportOutput] means pyright knows the exact output type before the code runs — no seed does this. The 40+ built-in capabilities (Thinking, WebSearch, WebFetch, ToolSearch, etc.) are composable as mix-ins, not hard-coded features. The multi-provider FallbackModel and InstrumentedModel wrappers at the model layer have no equivalent in any seed.

Positioning

PydanticAI occupies the "typed SDK" position: it is the framework for developers who use type checkers and expect IDE auto-completion to work correctly for agent code. It is the only framework in the catalog that explicitly advertises "if it type-checks, it works" as a design goal.

Distinctive features

  1. Generic Agent[DepsT, OutputT]: pyright/mypy infer output types from agent definition — unique in Python agent frameworks
  2. Dependency injection via RunContext[DepsT]: typed injection of databases, services, and context — FastAPI pattern applied to agents
  3. Pydantic validation on output: agent re-prompts on validation failure automatically
  4. pydantic_graph: typed state machine for complex workflows with IDE support
  5. 40+ built-in capabilities: composable mix-in capabilities including ToolSearch (dynamic tool discovery), XSearch, ImageGeneration
  6. YAML/JSON agent spec: define agents without code via _spec.py and registry
  7. FallbackModel: automatic multi-provider failover at the model layer
  8. Multi-IDE instruction files: CLAUDE.md + AGENTS.md + .gemini/ — targets all major AI coding agents

Observable failure modes

  1. Generic complexity: Agent[DepsT, OutputT] with 40+ capabilities requires understanding Python generics and type variance
  2. Logfire coupling: the best observability experience requires Pydantic Logfire (commercial product)
  3. No built-in memory: conversation history is fully user-managed; production memory requires external storage
  4. CLI transition: paiclai rename signals API churn; users must follow deprecation notices
  5. Provider coupling: 20+ provider adapters mean any breaking change in a provider SDK may cascade
04

Workflow

PydanticAI — Workflow

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)  # typed as str
Phase Artifact
1. Define Agent with model + instructions Agent[None, str]
2. agent.run_sync(prompt) AgentRunResult[str]
3. result.output str (Pydantic validated)

Structured output with DI

@dataclass
class SupportDependencies:
    customer_id: int
    db: DatabaseConn

class SupportOutput(BaseModel):
    support_advice: str
    block_card: bool
    risk: int = Field(ge=0, le=10)

support_agent = Agent(
    'openai:gpt-5.2',
    deps_type=SupportDependencies,
    output_type=SupportOutput,
    instructions='You are a bank support agent.',
)

@support_agent.instructions
async def add_customer_name(ctx: RunContext[SupportDependencies]) -> str:
    name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
    return f"The customer's name is {name!r}"

@support_agent.tool
async def customer_balance(ctx: RunContext[SupportDependencies], include_pending: bool) -> float:
    """Returns the customer's current account balance."""
    return await ctx.deps.db.customer_balance(id=ctx.deps.customer_id, include_pending=include_pending)
Phase Artifact
1. Define deps_type, output_type Generic type constraints
2. Register dynamic instructions Callable injected at run time
3. Register tools with RunContext Type-safe tool functions
4. await agent.run(prompt, deps=deps) AgentRunResult[SupportOutput]
5. result.output SupportOutput (Pydantic validated)

Approval gates

HandleDeferredToolCalls capability + deferred_tools=["execute_sql"] — agent pauses for human approval before calling specified tools.

Durable execution

Agents wrapped with durable execution backend (DBOS, Prefect, Temporal) pause/resume across failures without code changes.

06

Memory Context

PydanticAI — Memory & Context

Memory architecture

PydanticAI does not ship a memory system. Message history is managed via capture_run_messages() and passed explicitly to subsequent runs.

with agent.run_context() as ctx:
    result1 = await agent.run("first message", message_history=ctx.messages)
    result2 = await agent.run("follow-up", message_history=result1.new_messages())

State machine (pydantic_graph)

For complex workflows, pydantic_graph provides typed stateful graphs where each node transitions to the next based on output. State is carried through the graph in a typed StateT parameter.

Durable execution state

When using durable execution backends (DBOS, Prefect, Temporal, prefect, outlines), run state is persisted by the backend. PydanticAI's internal _agent_graph.py produces a replayable execution record.

Dependency injection (not memory)

Dependencies (deps) are injected per-run, not persisted. They carry database connections, user contexts, or any runtime data the agent needs. This is stateless injection, not memory.

Pydantic Logfire

Instrumentation capability + Pydantic Logfire integration provides real-time run history, trace viewer, and eval monitoring. This is the primary "memory" for production observability.

State files

No fixed state files. The clai CLI may use ~/.pydantic_ai/ for credentials, but this is not documented in the README.

Cross-session handoff

Not built-in at the SDK level. Durable execution backends provide this when opted in.

07

Orchestration

PydanticAI — Orchestration

Multi-agent

Yes. Agents can call other agents as tools:

research_agent = Agent(...)
writer_agent = Agent(...)

@writer_agent.tool
async def research(ctx: RunContext[Deps], query: str) -> str:
    result = await research_agent.run(query, deps=ctx.deps)
    return result.output

This enables hierarchical composition without a dedicated team class.

Orchestration pattern

sequential (default tool call flow) and hierarchical (agents as tools). pydantic_graph supports task-decomposition-tree for complex workflows.

Max concurrent agents

Unknown. Async Python; no hard cap. ParallelExecutionMode in ToolManager controls concurrent tool execution.

Isolation mechanism

None. Durable execution backends may provide isolation.

Multi-model

Yes. Multiple agents can use different providers:

agent_a = Agent('anthropic:claude-sonnet-4-6')
agent_b = Agent('openai:gpt-4o')

The FallbackModel wraps multiple providers with automatic retry on failure.

Execution mode

one-shot (synchronous: run_sync), interactive-loop (async: await run), or continuous-ralph via run_stream with RetryResultValidator.

Crash recovery

durable_exec/ — optional DBOS, Prefect, Temporal, prefect, outlines backends provide crash recovery.

Context compaction

ProcessHistory capability — handles conversation history management.

Consensus

None.

Prompt chaining

Yes — output_type of one agent can be fed as deps or message_history to the next agent. Explicit Python chaining.

Streaming

Yes — agent.run_stream() with async for event in result.stream_events(). AG-UI protocol for standardized event streams.

MCP

MCP capability class + mcp.py. Agents connect to MCP servers via the same AsyncContextManager pattern as mcp-agent.

A2A

_a2a.py — Agent-to-Agent protocol for interoperability with other A2A-compliant agents.

08

Ui Cli Surface

PydanticAI — UI & CLI Surface

CLI binary

clai — current CLI entry point. pai — deprecated legacy entry (still functional, maps to same entry point).

Entry: pydantic_ai._cli:cli_exit

From pyproject.toml: pai = "pydantic_ai._cli:cli_exit" # TODO remove this when clai has been out for a while

The clai/ directory in the repo root contains the CLI implementation. Subcommands not fully enumerated in README but likely include: run, chat, configure.

Local UI / dashboard

Pydantic Logfire — cloud-hosted observability platform (logfire.pydantic.dev). Features: real-time run trace, tool call history, eval experiments, cost tracking.

OTel-compatible backends also work if Logfire is not desired.

IDE integration

  • CLAUDE.md — instructions for Claude Code working on PydanticAI codebase
  • AGENTS.md — instructions for Codex/OpenAI agents
  • .claude/ and .agents/ directories
  • .gemini/ — Gemini coding agent instructions

The PydanticAI codebase targets multiple AI coding agents with separate instruction files — a noteworthy meta-practice.

Pydantic Harness

ai.pydantic.dev/harness/ — curated library of third-party and official capabilities. Similar to a package registry but for agent capabilities.

Observability

  • Pydantic Logfire (native integration)
  • OpenTelemetry (any OTEL backend)
  • Evals (pydantic_evals) for offline evaluation

AG-UI streaming

ag_ui.py implements the AG-UI streaming event standard — a protocol for standardized event-based communication between agents and frontend UIs.

A2A

_a2a.py — A2A protocol enables interoperability with Google ADK, Agno, and other A2A-compliant frameworks.

Related frameworks

same archetype · same primary tool · same memory type

Claude-Flow / Ruflo ★ 55k

Eliminates single-agent context limits and sequential bottlenecks by orchestrating fault-tolerant swarms of specialized AI agents…

Hermes Agent (NousResearch) ★ 168k

Self-improving personal AI agent with closed learning loop, 7 terminal backends, and messaging gateway — not tied to any AI…

OpenCode ★ 165k

Terminal-first AI coding agent with multi-model routing, native desktop app, and a typed .opencode/ configuration system for…

OpenHands ★ 75k

Open-source AI software development platform (open-source Devin alternative) with Docker sandbox isolation, 77.6% SWE-bench…

DeerFlow ★ 70k

Long-horizon superagent that researches, codes, and creates by orchestrating parallel sub-agents with isolated contexts in Docker…

oh-my-openagent (omo) ★ 60k

Multi-provider AI agent orchestration for OpenCode: escape vendor lock-in by routing Sisyphus (Claude/Kimi/GLM) and Hephaestus…