Skip to content

Overview

A capability is a reusable, composable unit of agent behavior. Instead of threading multiple arguments through your Agent constructor — instructions here, model settings there, a toolset somewhere else, a history processor on yet another parameter — you can bundle related behavior into a single capability and pass it via the capabilities parameter.

Capabilities can provide any combination of:

  • Tools — via toolsets or native tools
  • Lifecycle hooks — intercept and modify model requests, tool calls, and the overall run
  • Instructions — static or dynamic instruction additions
  • Model settings — static or per-step model settings
  • Models — static or adaptive model selection and application-specific model ID resolution

This makes them the primary extension point for Pydantic AI. Whether you’re building a memory system, a guardrail, a cost tracker, or an approval workflow, a capability is the right abstraction.

Capabilities can be always-on or loaded by the model on demand. Pydantic AI ships the built-in capabilities below, Pydantic AI Harness and third-party packages provide many more, and you can define your own — declaratively or by subclassing. To run agents durably across failures, restarts, and long waits, see Durable Execution.

Built-in capabilities

Pydantic AI ships with several capabilities that cover common needs:

CapabilityWhat it providesSpec
ThinkingEnables model thinking/reasoning at configurable effortYes
HooksDecorator-based lifecycle hook registration
InstrumentationOpenTelemetry/Logfire tracing of runs, model requests, and tool callsYes
SelectModelSelects a static or per-step model with a callable
ResolveModelIdResolves custom model IDs with a callable
WebSearchWeb search — native by default, optional local fallback via local='duckduckgo'Yes
WebFetchURL fetching — native by default, optional local fallback via local=TrueYes
ImageGenerationImage generation — native by default, optional subagent fallback via fallback_modelYes
XSearchX search — native on xAI, explicit subagent fallback via fallback_modelYes
MCPMCP server — runs locally by default; native=True opts into the model provider’s native MCP supportYes
ToolSearchDiscovery of deferred tools — native when supported, local search_tools function tool otherwiseYes
PrepareToolsFilters or modifies function tool definitions per step
PrepareOutputToolsFilters or modifies output tool definitions per step
PrefixToolsWraps a capability and prefixes its tool namesYes
NativeToolRegisters a native tool with the agentYes
CapabilityBundles instructions, function tools, and toolsets without subclassing
ToolsetWraps an AbstractToolset
IncludeToolReturnSchemasIncludes return type schemas in tool definitions sent to the modelYes
SetToolMetadataMerges metadata key-value pairs onto selected toolsYes
RaiseContentFilterErrorRaises ContentFilterError whenever a model response has finish_reason='content_filter'Yes
ReinjectSystemPromptReinjects the configured system prompt when the incoming message history is missing oneYes
HandleDeferredToolCallsResolves deferred tool calls inline with a handler function
ProcessHistoryWraps a history processor
ProcessEventStreamForwards agent stream events to a handler function
ThreadExecutorUses a custom thread executor for sync functions

The Spec column indicates whether the capability can be used in agent specs (YAML/JSON). Capabilities marked take non-serializable arguments (callables, toolset objects) and can only be used in Python code.

Provider-specific compaction capabilities (OpenAICompaction, AnthropicCompaction) live in the corresponding model modules. The durable execution integrations also ship as capabilities — TemporalDurability, DBOSDurability, and PrefectDurability — in the pydantic_ai.durable_exec subpackages.

native_capabilities.py
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(local='duckduckgo'),
    ],
)

Instructions and model settings are configured directly via the instructions and model_settings parameters on Agent (or AgentSpec). Capabilities are for behavior that goes beyond simple configuration — tools, lifecycle hooks, and custom extensions. They compose well, especially when you want to reuse the same configuration across multiple agents or load it from a spec file.

Bundling behavior with Capability

You don’t need a subclass to define a capability of your own: Capability bundles instructions, function tools, and toolsets declaratively — think of it as defining a skill:

capability_shorthand.py
from pydantic_ai import Agent
from pydantic_ai.capabilities import Capability

refunds = Capability(
    id='refunds',
    description='Use for refund eligibility and refund status.',
    instructions='Always confirm the order ID before issuing a refund.',
)


@refunds.tool_plain
def refund_status(order_id: str) -> str:
    """Look up the refund status for an order."""
    return f'Order {order_id}: refund issued on 2026-05-01.'


agent = Agent('openai:gpt-5.2', capabilities=[refunds])

Add defer_loading=True and the bundle becomes an on-demand capability that stays collapsed to a one-line catalog entry until the model loads it — the same shape as Agent Skills, which you can wrap in a Capability directly. See The Capability convenience class for the full API. For behavior beyond instructions, tools, and toolsets — lifecycle hooks, model settings, native tools — subclass AbstractCapability as covered in Building Custom Capabilities.

Provider-adaptive tools

WebSearch, WebFetch, ImageGeneration, XSearch, and MCP each cover a single capability (web search, URL fetch, image generation, X search, MCP) across two implementations:

  • Native — invoked by the model provider when the model supports it. The work happens on the provider’s side (e.g. Anthropic’s web search runs server-side, returning results inline).
  • Local — runs in your Python process. Used when the model doesn’t support the native tool; your code does the work (e.g. calling DuckDuckGo directly).
CapabilityLocal fallbackNotes
WebSearchlocal='duckduckgo' or local=True (DuckDuckGo)Requires the duckduckgo optional group
WebFetchlocal=True (markdownify-based fetch)Requires the web-fetch optional group
ImageGenerationSubagent via fallback_model=Delegates to a model that supports native image generation
XSearchSubagent via fallback_model=No default non-xAI fallback; set fallback_model to an xAI model that supports XSearchTool
MCPDirect connection to the MCP server (the default)Accepts any MCPToolset input; transport is auto-detected from a URL

Because these capabilities contribute model-facing tools, their id, description, and defer_loading fields are meaningful: set them when that tool should stay hidden until the model loads the matching workflow with the load_capability tool. This includes ImageGeneration when image generation should only be available for an image-specific workflow, whether it resolves to a native image tool or a fallback subagent tool.

Configure each side via the native= and local= kwargs. native= accepts True (use the capability’s default native tool instance), False (disable native), or an explicit instance like WebSearchTool(...) for fine-grained config. local= accepts True (the bundled local fallback, on capabilities that have one — WebSearch and WebFetch), False (disable local), a named strategy string where supported, or any callable, Tool, or AbstractToolset. Optional installs needed for the local fallback are opt-in — the capability raises a UserError at construction (with an install hint) when you ask for a local strategy whose extra isn’t installed.

provider_adaptive_tools.py
from pydantic_ai import Agent
from pydantic_ai.capabilities import MCP, ImageGeneration, WebFetch, WebSearch, XSearch

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[
        # Native when supported; DuckDuckGo fallback on unsupported models
        WebSearch(local='duckduckgo'),
        # Native when supported; markdownify-based fallback on unsupported models
        WebFetch(local=True),
        # Native when supported; subagent fallback via `fallback_model`
        ImageGeneration(fallback_model='openai-responses:gpt-5.4'),
        # Native on xAI; on other models, explicitly delegate to an xAI model
        XSearch(fallback_model='xai:grok-4.3'),
        # Runs the MCP server locally by default; pass `native=True` to also advertise native MCP
        MCP('https://mcp.example.com/api'),
    ],
)

MCP defaults the other way from the others: because MCP carries credentials, it runs locally by default and you opt into native MCP with native=True. The others default to native and you opt into local with local=.

XSearch is slightly different from WebSearch and WebFetch: there is no default non-xAI fallback. If your agent is not running on an xAI model, set fallback_model explicitly to an xAI model that supports XSearchTool.

Some constraint fields require the native tool (the bundled local fallback can’t enforce them) — passing them locks the capability to the native path. If the model doesn’t support the native tool, the capability raises a UserError.

constraints.py
# Limit to 5 searches per run — requires native (the local fallback can't track call count)
WebSearch(max_uses=5)

# Only fetch example.com — enforced locally when native is unavailable
WebFetch(allowed_domains=['example.com'], local=True)

Building your own

All five capabilities are subclasses of NativeOrLocalTool, which you can use directly or subclass to build your own provider-adaptive tools. For example, to pair CodeExecutionTool with a local fallback:

custom_native_or_local.py
from pydantic_ai.native_tools import CodeExecutionTool
from pydantic_ai.capabilities import NativeOrLocalTool

cap = NativeOrLocalTool(native=CodeExecutionTool(), local=my_local_executor)

Pydantic AI Harness

Pydantic AI Harness is the official capability library for Pydantic AI — standalone capabilities like memory, guardrails, context management, and code mode live there rather than in core. See What goes where? for the full breakdown, or jump to the capability matrix.

Third-party capabilities

Third-party packages publish capabilities of their own — see Third-Party Capabilities for the ecosystem, and Publishing capabilities for making your own capability available to others.