Pydantic AI v2 Capabilities and Harness: A Production Python Agent Guide
> A source-backed guide to Pydantic AI v2 capabilities and Harness: typed agents, deferred tools, MCP, coding workflows, observability, security, debugging, and durable execution.
🎧 Listen — ~11 min
Ready · Pydantic AI v2 Capabilities and
Direct answer
Pydantic AI v2 reorganizes Python agent development around a composable capability primitive. A capability can bundle instructions, tools, lifecycle hooks, model settings, and toolsets into one reusable unit. The first-party Pydantic AI Harness builds higher-level behaviors—coding, memory, context management, web research, planning, and durable execution—on top of that same composition model.
The practical change is architectural: instead of hand-wiring every agent’s guardrails, context rules, tool discovery, and observability, a team can assemble a smaller core agent from typed capabilities and keep the model provider replaceable. Pydantic AI v2 became stable on June 23, 2026; the project’s official package and repository records show active 2.x releases, including 2.36.0 on August 29.
For a new production project, start with the smallest capability set that proves the workflow: typed output, explicit tools, bounded context, and instrumentation. Add MCP, deferred tool loading, code mode, subagents, or durable execution only when the workflow requires them.
What changed in Pydantic AI v2
The Pydantic team’s v2 announcement describes a deliberate split between a leaner core and the Harness. Core contains the agent loop, model providers, the capability and hooks API, and capabilities that need deep provider integration or are broadly useful. The Harness supplies faster-moving batteries and complete agent compositions.
A capability is more than a bag of tools. It can influence the agent at several points in a run:
- instructions can be added or rewritten;
- tools can be exposed, filtered, or deferred;
- lifecycle hooks can inspect or alter a run;
- model settings can be attached to a reusable behavior;
- toolsets such as MCP can be packaged with the instructions that explain when to use them.
That gives teams one extension boundary for concerns that are otherwise scattered across prompt strings, decorators, middleware, provider-specific settings, and bespoke run callbacks.
The change is especially relevant when an agent must operate for a long time. Context limits, tool-result growth, retries, steering, approval, and recovery matter more than the first model call. A capability-based design makes those concerns explicit and composable rather than hiding them in one oversized agent class.
The architecture: core loop, capabilities, and Harness
The following is an original conceptual diagram based on the official Pydantic AI v2 announcement and documentation. It is not a reproduction of an internal Pydantic diagram.
Figure 1 — Capability-oriented agent architecture. The model remains one participant in a controlled loop; capabilities and the Harness provide the surrounding execution contract. Source basis: Pydantic AI v2 announcement and Pydantic AI documentation.
This design also clarifies what Pydantic AI v2 does not promise. A capability is not an automatic security boundary, and the Harness does not make arbitrary shell commands safe. Authorization, network policy, credential handling, tenant isolation, and human approval still belong in the application and runtime design.
Installation and a minimal typed agent
The official project recommends installing the package with uv for a clean Python environment:
1uv add pydantic-aiA minimal agent can use a typed output model and a function tool. This pattern follows the public documentation’s API shape; provider names and model availability should be checked against the provider documentation used by your deployment.
1from typing import Literal
2
3from pydantic import BaseModel, Field
4from pydantic_ai import Agent, RunContext
5
6
7class ReviewSummary(BaseModel):
8 label: Literal["positive", "negative", "neutral"]
9 score: float = Field(ge=-1, le=1)
10
11
12agent = Agent(
13 "openai:gpt-5.6-sol",
14 output_type=ReviewSummary,
15 instructions="Summarize the review and state uncertainty briefly.",
16)
17
18
19@agent.tool
20def recent_review(ctx: RunContext[None], product: str) -> str:
21 """Return a review excerpt for the requested product."""
22 return f"{product}: The latest release fixed the issue I reported."
23
24
25result = agent.run_sync("How do users feel about Extract?")
26print(result.output)The important property is not the sample sentiment label. The agent’s returned value is validated against ReviewSummary, and the tool’s signature and docstring become part of its typed contract. In a real service, replace the example tool with a dependency-injected repository or API client, validate authorization before the tool executes, and test both valid and invalid model outputs.
Adding capabilities without creating a framework fork
The v2 model lets a team add behavior without modifying the main agent loop. The official announcement shows capabilities for thinking effort, web search, tool search, code mode, and MCP-backed integrations.
1from pydantic_ai import Agent
2from pydantic_ai.capabilities import Capability, ToolSearch, WebSearch
3from pydantic_ai.mcp import MCPToolset
4
5
6agent = Agent(
7 "anthropic:claude-opus-4-7",
8 instructions="Research carefully and cite source pages.",
9 capabilities=[
10 WebSearch(),
11 ToolSearch(),
12 Capability(
13 id="github",
14 description="Look up repository issues, pull requests, and code.",
15 instructions="Use GitHub tools only for repository questions.",
16 toolset=MCPToolset("https://mcp.example.com/github"),
17 defer_loading=True,
18 ),
19 ],
20)defer_loading=True is a meaningful production control. Instead of placing every GitHub tool definition in the initial prompt, the model sees a compact description and loads the capability when needed. That can reduce prompt pressure and make a large tool catalog easier to govern. It does not remove the need for server-side authorization: the MCP server must still authenticate the caller, validate arguments, enforce tenant scope, and record tool activity.
Treat capability composition as an allowlist, not an automatic permission grant. A customer-support agent may receive a read-only account capability, while a refund capability should be separately gated, audited, and possibly paused for approval.
The Pydantic AI Harness: useful batteries, separate risk
The first-party Harness is where Pydantic AI packages more involved behaviors. The official docs describe capabilities and agents for coding, memory, subagents, context management, file access, shell execution, planning, web research, tool search, code mode, and other runtime concerns.
A complete coding agent can be composed from smaller parts such as:
1from pydantic_ai import Agent
2from pydantic_ai.capabilities import WebSearch
3from pydantic_ai_harness import Advisor, Coder
4
5
6agent = Agent(
7 "anthropic:claude-fable-5",
8 capabilities=[
9 Coder(),
10 WebSearch(),
11 Advisor("openai:gpt-5.6-sol"),
12 ],
13)
14
15agent.to_cli_sync()The Coder composition is valuable because it makes the coding-agent environment inspectable. The docs describe the underlying pieces as workspace-rooted file access, an allowlisted shell, repository orientation, planning, subagents, context management, and output limits. Teams can use the complete capability or assemble a narrower set.
Do not interpret a convenient coding capability as permission to run against a developer laptop or production repository. Start with a disposable workspace, synthetic credentials, an egress policy, command and resource limits, and a human approval step before external side effects. For a broader discussion of the environment around coding agents, see the MCP Apps interactive UI guide and Google ADK’s zero-trust agent security guide.
Capability composition versus hand-wired agents
| Concern | Hand-wired agent | Pydantic AI v2 approach | Production question |
|---|---|---|---|
| Instructions | Large prompt assembled per project | Instructions live in a capability | Which instructions apply to this run? |
| Tools | All tools registered up front | Typed tools or deferred capabilities | Which tools are visible and authorized? |
| Context | Custom trimming and summaries | Context-management capabilities | What is retained, summarized, or discarded? |
| MCP | Separate client glue and prompt rules | Capability can package an MCP toolset | Is the server trusted and tenant-scoped? |
| Guardrails | Ad hoc callbacks | Hooks and reusable capabilities | Can policy failures stop the run cleanly? |
| Observability | Provider-specific logging | Instrumentation and OpenTelemetry paths | Are prompts and tool arguments redacted? |
| Long jobs | Custom queues and checkpoints | Harness and durable-execution integrations | Can a restart resume idempotently? |
| Model changes | Provider-specific agent code | Model string swap where supported | Which provider semantics still differ? |
The table is a practical comparison, not a benchmark. Pydantic AI v2 reduces framework glue; it does not eliminate provider differences or operational work.
Production checklist for Python agent teams
Keep the type boundary honest
Use Pydantic models for outputs that downstream code will act on. Constrain values with enums, ranges, and nested models. Treat validation errors as normal control flow: retry with a bounded budget, repair the prompt or schema, and surface a structured failure when the budget is exhausted.
Separate policy from model instructions
Natural-language instructions can explain a policy, but they should not be the only enforcement point. Check tenant identity, tool authorization, data access, and approval state in application code before side effects. A capability should make the allowed behavior easier to compose—not turn the model into an authorization service.
Control context and tool discovery
Use deferred capabilities for large tool catalogs, cap tool-result sizes, summarize long histories, and make cache behavior explicit. Never return unbounded database rows, logs, or web pages directly into the model context. Record truncation and retrieval decisions so a debugging session can explain what the model actually saw.
Instrument without leaking data
Pydantic’s documentation emphasizes instrumentation and Logfire integration. Whatever OpenTelemetry backend you use, decide whether message-content events are permitted. Prompts, tool arguments, retrieved documents, and outputs may contain secrets or personal data. Redact before export, apply retention limits, and separate developer traces from customer-visible logs.
Make recovery idempotent
For Temporal, DBOS, Prefect, or another durable runtime, persist versioned state and use idempotency keys for external actions. A retry after a worker crash must not create a second refund, duplicate an email, or apply a migration twice. Do not serialize bearer tokens or unrestricted tool results into checkpoints.
Pin and stage upgrades
The official GitHub release page records the project’s rapid 2.x cadence, while PyPI currently lists 2.36.0. Pin the package and provider integrations in production, run a clean-environment install in CI, and stage upgrades against representative model calls, tool calls, streamed events, retries, and cancellation. Read the version-specific upgrade guidance before assuming a minor-looking dependency update is operationally trivial.
Common errors and debugging paths
The model sees too many tools. Move optional tools into a deferred capability or use tool search. Then verify that the server still enforces authorization when the tool is loaded.
A structured response fails validation. Inspect the model output and schema error separately. Tighten field descriptions, add a bounded retry, and test edge cases with the test model before spending provider tokens.
A tool works in development but fails in production. Compare dependency injection, tenant context, provider configuration, and network policy. The capability composition may be identical while the runtime permissions differ.
A long run becomes incoherent. Add context limits, output trimming, summaries, and explicit checkpoints. Measure where context grows instead of simply increasing the model’s context window.
A retry repeats an external side effect. Add an idempotency key and persist the side-effect state before retrying. A model-level “do not repeat” instruction is not sufficient.
MCP calls are difficult to audit. Log the server identity, capability ID, authenticated subject, tool name, argument hash, approval decision, and outcome. Avoid logging raw sensitive arguments.
FAQ
Is Pydantic AI v2 a replacement for every agent framework?
No. It is a typed Python framework with a capability-oriented extension model and provider integrations. It is a strong fit when Python typing, structured outputs, explicit tools, and composable runtime behavior matter. Compare the workflow, observability, deployment, and provider requirements rather than choosing from version numbers alone.
Should a beginner start with the Harness?
A beginner should first build a small typed agent with one or two deterministic tools. Add the Harness when the workflow genuinely needs file access, coding, memory, subagents, or durable execution. Starting small makes failures easier to understand and permissions easier to review.
Does a capability make an MCP server safe?
No. It organizes the client-side behavior and can reduce accidental tool exposure, but the server remains responsible for authentication, authorization, input validation, rate limits, data isolation, and auditability. Treat every remote MCP server as an external privileged integration.
Can the model provider be swapped without code changes?
Pydantic AI exposes a model-string abstraction, and much agent code can remain unchanged when switching providers. Provider-native features, message formats, tool-calling behavior, rate limits, pricing, and safety controls still differ. Test the complete workflow after a provider change.
Conclusion
Pydantic AI v2’s central idea is simple but consequential: the production layer around an agent should be composable. Capabilities give instructions, tools, hooks, settings, and MCP toolsets a common boundary; the Harness turns those pieces into reusable agent behaviors without forcing every project to rebuild context management, coding workflows, and recovery from scratch.
The right adoption path is deliberately boring: pin a version, build a typed agent, isolate tools, instrument safely, add deferred discovery where context requires it, and test recovery before increasing autonomy. For the runtime-design perspective, compare this approach with the site’s Harness Engineering for AI Coding Agents guide, OpenAI Agents SDK sandbox and harness guide, and MCP stateless migration guide. Used that way, Pydantic AI v2 is less a prompt framework and more a typed foundation for Python agent systems that can be inspected, constrained, and evolved.
Sources and visual credits
- Pydantic AI v2: capabilities, a leaner core, and the Harness — official announcement and architecture claims.
- Pydantic AI documentation — official APIs, capabilities, Harness, MCP, testing, and runtime guidance.
- Pydantic AI on PyPI — package metadata, current version, and public examples.
- Pydantic AI GitHub releases — signed release records and version changes.
- Pydantic AI v2 and the road to production-grade agentic AI — independent implementation analysis and production perspective.
- Figure 1: original Mermaid editorial diagram by Essa Mamdani, based on the official Pydantic AI announcement and documentation; no product screenshot or benchmark is implied.
Related reading
Continue exploring related AI engineering and developer tooling topics:
Keep reading
Related reading
⚡ Daily AI Model Drop — Get Kimi K3 benchmarks before Twitter
Join 2,400+ AI engineers. 1 email/day, no spam, unsubscribe anytime