Pydantic AI reached version 2 on June 23, 2026, and the headline change is structural: every extension point an agent needs — tools, instructions, lifecycle hooks, model settings — now collapses into one primitive called a capability. A new first-party package, the Harness, ships the pre-built capabilities on top of it: memory, guardrails, sandboxed code execution, and more, kept separate so the framework’s core stays small. This guide covers what actually changed, how capabilities and the Harness compose, Pydantic AI’s real two-way MCP support, and where it sits next to LangGraph and CrewAI.
Pydantic AI is a Python agent framework from the Pydantic team that applies FastAPI-style type safety and validation to LLM agent code. Version 2, released June 23, 2026, reorganizes every extension point — tools, system prompt text, model settings, lifecycle hooks — around one primitive called a capability: a reusable, composable unit of agent behavior you attach to an Agent via a single capabilities=[...] list.
Capability replaces four separate constructor arguments (tools, instructions, hooks, model settings) with one object that can provide any combination of them.
Pydantic AI Harness is a new, separate package — “the batteries for your agent” — shipping pre-built capabilities: memory, guardrails, sandboxed code execution, file system and shell access, and more.
MCP support runs both directions: agents can call out to MCP servers, and Pydantic AI agents can themselves be exposed inside an MCP server — confirmed directly against Pydantic’s docs below.
The announcement came from the framework’s own account, and it is worth reading in full because the phrasing is precise about what changed and what didn’t:
𝗣𝘆𝗱𝗮𝗻𝘁𝗶𝗰 𝗔𝗜 𝘃𝟮 𝗶𝘀 𝗵𝗲𝗿𝗲, and your agents have never been more capable. The inner loop of an agent is settled, the leverage is in the layer around it, and v2 turns that whole layer into one thing you compose: the capability.
It bundles instructions, tools, hooks, and model settings into a single unit. Plus a leaner core and the Pydantic AI Harness.
Per Pydantic’s own docs, Pydantic AI is designed “to help you quickly, confidently, and painlessly build production grade applications and workflows with Generative AI,” bringing “that FastAPI feeling to GenAI app and agent development.” The pitch: nearly every Python LLM library already leans on Pydantic Validation for structured output, but before this framework, none of them wrapped that validation in FastAPI’s ergonomics — decorators, type hints, validation as the default path, not an afterthought. You write typed Python functions; the framework turns them into tool schemas; swapping model providers (OpenAI, Anthropic, Gemini, and others) leaves your business logic untouched.
Before v2, extending an agent meant threading more arguments through the Agent constructor: a tools list here, a system-prompt string there, model settings somewhere else, an event hook bolted on last. Nothing forced those four things to travel together, so a reusable extension — a memory system, a guardrail — meant wiring up several disconnected pieces by hand, every time you wanted to reuse it. That is the gap the capability closes.
Takeaway: if you have used Pydantic (the validation library) or FastAPI before, the pitch will land in one sentence — this is the same ergonomics bet, applied one layer up, to the agent itself rather than the API route.
Core, capability, Harness — the three pieces
Three named pieces do all the work in v2, and the boundary between them is deliberate:
Core (pydantic-ai-slim) — the agent loop, the model-provider adapters, and the Capability API itself. Small and stable by design.
Capability — the composable unit. Anything that bundles tools, instructions, hooks, or model settings, attached via capabilities=[...].
Harness (pydantic-ai-harness) — a separate, official package of pre-built capabilities that don’t (yet) belong in core.
Core — pydantic-ai-slim
agent loop · provider adapters · Capability API
↓ capabilities=[...] ↓
Core capability
Thinking, WebSearch, MCP, ToolSearch…
Harness capability
CodeMode, Memory, Guardrails, FileSystem…
Your capability
Custom AbstractCapability subclass
Takeaway: the split is not arbitrary. Core keeps only what needs deep provider integration or is load-bearing for nearly every agent (Thinking, WebSearch, MCP); everything else moves at Harness speed and can “graduate” into core once it proves broadly essential — Pydantic’s own docs name Code Mode as an early candidate for exactly that move.
Smallest end-to-end example
Install core plus the Harness (the extras in brackets pull in the model provider, MCP support, a local search fallback, Logfire tracing, and Code Mode):
Then stack three capabilities on one agent — this example is reproduced from the Harness’ own README:
from pydantic_ai import Agent
from pydantic_ai_harness import CodeMode, WebSearch
from pydantic_ai.capabilities import MCP
agent = Agent(
'anthropic:claude-opus-4-7',
capabilities=[
CodeMode(),
WebSearch(native=False),
MCP('https://hn.caseyjhand.com/mcp', native=False),
],
)
Three extensions, one line each: sandboxed code execution, web search with a local fallback, and a live MCP connection to a Hacker News server. No separate tool registration step, no separate hook wiring for the sandbox — each capability owns its own tools, instructions, and lifecycle behavior internally.
Takeaway: however many extensions you stack, the constructor signature never grows past capabilities=[...]. That uniformity is the actual product, not a syntax nicety.
Capabilities: the primitive, deep dive
A capability is “a reusable, composable unit of agent behavior,” per Pydantic’s core-concepts docs — the primary extension point for the whole framework. Custom capabilities subclass AbstractCapability, which exposes configuration methods (get_toolset, get_native_tools, get_instructions, get_model_settings) called once at construction, and lifecycle hooks (like before_tool_execute) that fire on every run:
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
from pydantic_ai.capabilities import AbstractCapability
@dataclass
class ApprovalGate(AbstractCapability[None]):
id: str = 'approval'
description: str = 'Confirms destructive actions.'
def get_instructions(self) -> str:
return 'Seek approval before deleting data.'
async def before_tool_execute(self, ctx, *, call, tool_def, args):
if 'delete' in tool_def.name:
# Custom approval logic
pass
return args
agent = Agent('openai:gpt-5.2', capabilities=[ApprovalGate()])
For simpler cases, the Capability() helper skips the subclass entirely. Its most consequential field is defer_loading: set it True and the capability collapses to a one-line catalog entry until the model explicitly calls a framework-managed load_capability tool, at which point its instructions activate, its tools register, and it stays active — including across history replay on a resumed conversation:
from pydantic_ai import Agent
from pydantic_ai.capabilities import Capability
refunds = Capability(
id='refunds',
description='Use for refund eligibility and status.',
instructions='Always confirm order ID before processing.',
defer_loading=True,
)
@refunds.tool_plain
def refund_status(order_id: str) -> str:
"""Look up refund status."""
return f'Order {order_id}: refund issued 2026-05-01.'
agent = Agent('openai-responses:gpt-5.4', capabilities=[refunds])
Without defer_loading
Every workflow’s instructions and tool schemas ride along on every single turn. Past roughly 30 –50 visible tools, model performance measurably degrades and every call burns tokens on capabilities you are not using this turn.
With defer_loading
Only a one-line catalog entry shows up until the model asks for it by name. A multi-workflow support agent can carry a dozen capabilities and still send a short, focused prompt on any given turn.
Takeaway: capabilities are more than syntactic sugar over tool registration — the lifecycle hooks and defer_loading give you levers (approval gates, progressive tool disclosure) that a flat list of functions passed to tools=[...] cannot express on its own.
The Harness: batteries, not bloat
pydantic-ai-harness first shipped on PyPI in April 2026, roughly two months before v2 core went stable — the Harness was already proving itself as a fast-moving package before the core it plugs into froze around the capability primitive. Install it with uv add pydantic-ai-harness, or with extras for Code Mode, Logfire, or ACP support.
The repo’s own capability matrix lists more than 40 features across nine categories. The shape of that list says as much as any individual entry:
Input/output guardrails, cost and token budgets, secret masking, approval workflows
Reliability
Stuck-loop detection, tool error recovery
Two entries are worth calling out. First, ACP (Agent Client Protocol) support puts the Harness in the same conversation as editor integrations — if you have not run into ACP before, our ACP vs MCP explainer covers how it differs from MCP (one wires an agent into an editor’s UI, the other wires an agent into external tools and data). Second, “Skills” appears as its own orchestration capability, the same name Anthropic uses for Claude’s packaged instruction-and-tool bundles — convergent naming, not a shared implementation.
Takeaway: the Harness is not a grab-bag of examples. It is a versioned, installable package with its own release cadence, and the matrix reads like a checklist for “what does a production coding or research agent actually need” — because that is exactly what Pydantic built it to answer.
The headless coding agent Pydantic dogfoods on itself
The v2 announcement is specific about one more thing shipping alongside the Harness: “a headless coding agent built on Pydantic AI that we are dogfooding across Pydantic’s own repositories.” That is the whole public description — as of this writing, Pydantic has not given it a standalone product name or a public release, in the article, the Harness README, or anywhere else we could verify. Treat it as an internal proof point, not a tool you can install today.
What it is built from is verifiable, though: the exact Harness capabilities that make a coding agent possible — Code Mode for sandboxed execution, file system and shell access, repo-context auto-loading, sub-agents, and tool-error recovery. Code Mode is the load-bearing piece, and Douwe Maan, Pydantic AI’s lead engineer (the same byline on the v2 article), explained the reasoning on Hacker News when the feature first shipped: it lets “the LLM chain tool calls, pull out specific fields, and run entire algorithms using tools with only the necessary parts of the result (or errors) going back to the LLM,” instead of round-tripping every intermediate value through a new model turn. It runs by default on Monty, a sandboxed Python runtime.
If you have used Claude Code or a similar terminal coding agent, the shape will feel familiar: a loop that reads files, edits them, runs commands, and checks its own work. The difference here is that every piece of that loop is an off-the-shelf Harness capability rather than bespoke glue code, which is the whole argument for capabilities existing in the first place.
Takeaway: the interesting story is not “Pydantic shipped a coding agent” — it’s that the Harness is complete enough to build one from off-the-shelf capabilities and have Pydantic trust it on their own codebase before productizing it.
MCP support: client and server, both real
The Model Context Protocol is the open standard for connecting AI applications to external tools and data sources. We checked Pydantic AI’s MCP docs directly rather than take the “MCP” mention in the README at face value, and the support is genuinely bidirectional:
As a client — “agents can connect to MCP servers and use their tools,” via the MCP capability or the lower-level MCPToolset for direct lifecycle management.
As a server — “agents can be used within MCP servers,” documented separately in Pydantic’s MCP server guide. Most Python agent frameworks only do the first half.
from pydantic_ai import Agent
from pydantic_ai.capabilities import MCP
agent = Agent(
'openai:gpt-5.2',
capabilities=[
MCP(url='https://mcp.example.com/api'),
MCP(url='https://mcp.example.com/other', native=True),
],
)
One v2-specific change matters here: MCP connections now run locally by default, which Pydantic’s docs frame as “keeping credentials, hooks, and tracing under your control.” Set native=True to hand the connection to the model provider’s own infrastructure instead, with automatic fallback to local execution if the provider doesn’t support it for that call. MCPToolset goes further and accepts a URL, a FastMCP transport, a prebuilt fastmcp.Client, an in-process FastMCP server, or a local script path — useful if you are already building your MCP server in Python with FastMCP, FastAPI-MCP, or the official SDK and want to wire it straight into a Pydantic AI agent without leaving the process.
Takeaway: for a directory built around MCP, this is the detail worth underlining — Pydantic AI is one of the few mainstream Python agent frameworks that treats “be an MCP server” as a first-class, documented capability rather than something you bolt on with a separate library.
Pydantic AI vs LangGraph and CrewAI
We already cover LangGraph, CrewAI, Letta, and AutoGen in depth in our Python agent framework comparison, and Pydantic AI deliberately sits outside that lineup — it is the type-safe entrant, built around validation rather than orchestration graphs or role play. The distinction is not cosmetic; it changes what “composing an agent” means in each framework:
Pydantic AI
LangGraph
CrewAI
Unit you compose
Capability
Graph node / edge
Agent role + task
State model
Linear run, explicit deps per capability
Explicit state machine, resumable
Task delegation, less explicit state
Type safety default
Built in — Pydantic validation end to end
Opt in, your node code
Opt in
MCP client
Yes
Yes
Yes
MCP server
Yes
No
No
If you have already read our LangGraph vs CrewAI vs Letta vs AutoGen guide and picked LangGraph for its durable, resumable state machine, nothing here should change that — Pydantic AI’s capability model is linear, not graph-based, and does not compete on that axis. If you picked CrewAI for the fastest path to a working demo, same story: Pydantic AI asks for more upfront type discipline in exchange for catching bad tool-call shapes before they hit an LLM turn. The real evidence this decision is genuinely unsettled: a 34-comment r/LangChain thread titled “LangGraph, ADK, Strands, PydanticAI: how do you actually choose in 2026?” is sitting at 26 upvotes with no consensus answer.
Takeaway: pick Pydantic AI when the agent’s output feeding into other systems matters more than the orchestration logic’s visual shape — validated output is the load-bearing feature, not a side benefit.
What we got wrong
Researching this from the outside, in the order the documentation corrected us:
We assumed the Harness was a cookbook, not a package. The name suggested a docs section or a set of recipe snippets. It is a versioned pip/uv-installable package with its own PyPI release history, its own extras, and its own changelog, separate from pydantic-ai-slim.
We assumed defer_loading was the default for every capability. Given how central the token-bloat problem is to the framework’s pitch, it would be reasonable to guess deferred loading is automatic. It is opt-in per capability — you set defer_loading=True explicitly, or every capability’s instructions and tools ship on every turn by default.
We assumed “MCP support” meant client-only, like most frameworks. Every other Python agent framework we cover in our LangGraph/CrewAI/Letta/AutoGen comparison connects to MCP servers but is not one. Pydantic AI does both, and it is documented as a first-class path, not an experimental flag.
Common mistakes
Letting an AI coding assistant write v1-shaped v2 code. Root cause: most coding models’ training data predates the June 23, 2026 release, so they confidently generate the old multi-argument Agent() pattern instead of capabilities=[...]. One developer’s workaround, shared on r/PydanticAI, was blunt about the problem:
“Pydantic AI is great and it's even better with the newly released version 2! But unfortunately LLMs don't know anything about this new 2.0 version. Luckily, there is a way to work around that...”
u/skvark, r/PydanticAI · Reddit
Migrating to Pydantic AI v2 — the fix was feeding the agent a migration-plan tool before letting it touch v2 code.
Expecting Code Mode’s sandbox to have full PyPI access. Root cause: Monty intentionally restricts the runtime — that is the security/capability tradeoff the sandbox exists to make. It surfaced as a real technical debate on Hacker News when Code Mode first shipped:
“Why do you think python without access to the library ecosystem is a good approach? I think you will end up with small tool call subgraphs (i.e. more round trips) or having to generate substantially more utility code.”
solidasparagus, Hacker News · Hacker News
Reply to Pydantic AI lead Douwe Maan's Code Mode announcement.
SourceIt is a fair tradeoff to weigh, not a bug — decide whether your use case needs arbitrary third-party packages inside the sandbox before you build around Code Mode.
Treating every capability’s tools as always visible. Root cause: without defer_loading=True, stacking many capabilities on one agent means every tool schema and every instruction block rides along on every turn, which is exactly the token-bloat problem the flag exists to solve.
Assuming MCP(url=...) always calls out to the model provider. Root cause: it runs locally by default in v2. native=True is opt-in, with local fallback when the provider does not support native MCP for that call — the opposite assumption of what the flag name implies at a glance.
Who it’s for, who it isn’t
Good fit if you already think in typed Python and want that discipline to extend into agent code; if you need fine control over what enters the model’s context on a given turn (defer_loading); if you are building a coding or research agent and want the Harness’s pre-built capabilities instead of reimplementing memory and guardrails; or if you need an agent that is also reachable as an MCP server, not only a client.
Look elsewhere if you want an out-of-the-box visual, resumable state machine — LangGraph’s explicit graph model fits that better, per our framework comparison. If you want the fastest possible path to a working demo with minimal type discipline, CrewAI’s role-and-task model gets there in fewer lines. And if your project leans on a large existing ecosystem of prebuilt integrations today, LangChain/LangGraph’s is larger, if only because it has been around longer.
Reaction to the underlying Code Mode capability (now folded into the Harness) has been more substantive than the usual launch-day noise, because it touches a real architectural question: how much should an LLM round-trip through the model versus execute locally. Praise leaned toward the specific problem it solves:
“Just want to say Kudos to you and the team. This is a brilliantly conceived chunk of functionality that IMHO hits exactly a sweet spot I didn't realize was missing. I'm working on a chat bot system now and definitely plan to incorporate Monty into it for all the reasons y'all foresaw.”
The skepticism in the same thread (quoted in Common Mistakes above) was not about whether Code Mode works — it was about the tradeoff of a restricted sandbox versus full library access, which is the correct question to ask before adopting it. On the MCP side, one commenter summed up why Pydantic AI treats MCP as load-bearing rather than optional: “MCP makes tools uniform” — a one-line case for why a typed framework would want a typed, uniform tool interface as its default integration surface.
The verdict
Our take
Adopt Pydantic AI v2 if you want typed, validated agent code with a FastAPI feel and you would rather compose capabilities off a shelf than glue together ad hoc middleware — and add the Harness the moment you need memory, guardrails, or sandboxed code execution, since reimplementing those by hand is exactly the work the package exists to remove. Skip it if you need LangGraph’s explicit, resumable state machine for genuinely long-running workflows, or CrewAI’s fastest-to-demo role model, or a large prebuilt integration ecosystem today rather than a well-designed primitive to build on.
The Harness shipping two months ahead of a stable v2 core, and graduating capabilities like Code Mode back into core once they prove out, is the detail we would watch. It is a credible answer to the tension every agent framework faces — move fast on features without breaking the API surface production code depends on — and it is testable: watch which Harness capabilities move into core over the next few releases.
Frequently Asked Questions
What's new in Pydantic AI v2?
One primitive: the capability, which bundles instructions, tools, lifecycle hooks, and model settings into a single composable unit. Core got leaner, MCP connections now run locally by default, openai: model names moved to the Responses API, and a separate Harness package ships pre-built capabilities — memory, guardrails, code execution — that don't live in core.
What exactly is a capability in Pydantic AI?
A reusable unit of agent behavior. Instead of passing tools, a system prompt, model settings, and hooks as four separate Agent arguments, you define one object that provides all four, then attach it via capabilities=[...]. Custom ones subclass AbstractCapability; simple ones use the Capability() helper directly, with an optional defer_loading flag.
What is the Pydantic AI Harness, and why isn't it part of core?
Harness is a separate, official package of pre-built capabilities — memory, guardrails, sandboxed code execution, file system and shell access, and more — installed with uv add pydantic-ai-harness. It's split from core so it can iterate fast without core's backward-compatibility guarantees; capabilities can graduate into core once they prove broadly essential, the way Code Mode is already positioned to.
Does Pydantic AI support MCP?
Yes, in both directions. As a client, agents connect to MCP servers through the MCP capability or the lower-level MCPToolset, running locally by default so credentials, hooks, and tracing stay under your control. As a server, Pydantic AI agents can themselves be exposed inside MCP servers — documented separately in Pydantic's MCP server guide.
Is there an official Pydantic AI coding agent?
Pydantic has built a headless coding agent on Pydantic AI and the Harness, which it dogfoods across its own repositories, per the v2 launch article. As of this writing it has no standalone product name or public release — it's an internal proof point for the Harness's coding-agent capabilities, not a shipped tool you can install.
How do I migrate from Pydantic AI v1 to v2?
Pydantic's own guidance: upgrade to the latest v1 release first and clear every deprecation warning it prints — that covers most of the migration before v2 enters the picture. From there, expect to move any code using the old multi-argument Agent constructor pattern onto the new capabilities=[...] list.
Pydantic AI vs LangGraph — which should I use?
Pick LangGraph if you think in explicit state machines and want durable execution that resumes after a crash. Pick Pydantic AI if you want typed, validated agent code with a FastAPI feel and capabilities you compose rather than middleware you glue together. Our full framework comparison breaks LangGraph, CrewAI, Letta, and AutoGen down by problem shape.
Glossary
Capability
A reusable, composable unit of agent behavior bundling tools, instructions, lifecycle hooks, and model settings.
Harness
Pydantic AI’s official, separately installed package of pre-built capabilities: memory, guardrails, code execution, and more.
Core (pydantic-ai-slim)
The small, stable package shipping the agent loop, provider adapters, and the Capability API itself.
AbstractCapability
The base class custom capabilities subclass to hook into tool registration, instructions, settings, and per-step lifecycle events.
defer_loading
A capability flag that hides its tools and instructions behind a one-line catalog entry until the model requests it.
load_capability
The framework-managed tool the model calls to activate a deferred capability mid-run.
Code Mode
A Harness capability letting the model write and run Python that chains tool calls, instead of round-tripping every intermediate result.
Monty
The sandboxed Python runtime Code Mode uses by default to run model-generated code safely.
MCP
Model Context Protocol — the open standard for connecting AI applications to external tools and data. See our MCP primer.
MCPToolset
The lower-level Pydantic AI class for managing an MCP server connection’s lifecycle directly.
Native / provider-native MCP
Running an MCP connection through the model provider’s own infrastructure instead of locally, via native=True.
ACP (Agent Client Protocol)
The editor-integration protocol the Harness supports for wiring an agent into IDEs; distinct from MCP.
Logfire
Pydantic’s observability platform for tracing, evals, and cost tracking, integrated directly into Pydantic AI.
Toolset
A group of related tools registered together; the building block a capability wraps alongside instructions and hooks.
If something in this guide is out of date — the headless coding agent getting a public name, a Harness capability graduating into core, a new MCP flag — email [email protected] or read more on our about page. We keep these guides current.