# pydantic\_ai.capabilities

### Toolset

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that provides a toolset.

### Thinking

**Bases:** `AbstractCapability[Any]`

Enables and configures model thinking/reasoning.

Uses the unified `thinking` setting in [`ModelSettings`](/docs/ai/api/pydantic-ai/settings/#pydantic_ai.settings.ModelSettings) to work portably across providers. Provider-specific thinking settings (e.g., `anthropic_thinking`, `openai_reasoning_effort`) take precedence when both are set.

#### Attributes

##### effort

The thinking effort level.

-   `True`: Enable thinking with the provider's default effort.
-   `False`: Disable thinking (silently ignored on always-on models).
-   `'minimal'`/`'low'`/`'medium'`/`'high'`/`'xhigh'`: Enable thinking at a specific effort level.

**Type:** `ThinkingLevel` **Default:** `True`

### PrepareTools

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that filters or modifies function tool definitions using a callable.

Wraps a [`ToolsPrepareFunc`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.ToolsPrepareFunc) as a capability. Filters/modifies **function** tools only; for output tools use [`PrepareOutputTools`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.PrepareOutputTools).

```python
from pydantic_ai import Agent, RunContext
from pydantic_ai.capabilities import PrepareTools
from pydantic_ai.tools import ToolDefinition


async def hide_admin_tools(
    ctx: RunContext[None], tool_defs: list[ToolDefinition]
) -> list[ToolDefinition] | None:
    return [td for td in tool_defs if not td.name.startswith('admin_')]


agent = Agent('openai:gpt-5', capabilities=[PrepareTools(hide_admin_tools)])
```

### HandleDeferredToolCalls

**Bases:** `AbstractCapability[AgentDepsT]`

Resolves deferred tool calls inline during an agent run using a handler function.

When tools require approval or external execution, the agent normally pauses the run and returns [`DeferredToolRequests`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolRequests) as output. This capability intercepts deferred tool calls, calls the provided handler to resolve them, and continues the agent run automatically.

The handler receives the [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext) and the [`DeferredToolRequests`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolRequests). It may return [`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) with results for some or all pending calls, or return `None` to decline handling (the next capability in the chain gets a chance, otherwise the calls bubble up as `DeferredToolRequests` output).

#### Attributes

##### handler

The handler function that resolves deferred tool requests.

Receives the run context and the deferred tool requests, and returns [`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) with results for some or all pending calls, or `None` to decline handling. Can be sync or async.

**Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext)\[`AgentDepsT`\], [`DeferredToolRequests`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolRequests)\], [`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) | [`None`](https://docs.python.org/3/library/constants.html#None) | [`Awaitable`](https://docs.python.org/3/library/typing.html#typing.Awaitable)\[[`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) | [`None`](https://docs.python.org/3/library/constants.html#None)\]\]

### IncludeToolReturnSchemas

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that includes return schemas for selected tools.

When added to an agent's capabilities, this sets [`include_return_schema`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.ToolDefinition.include_return_schema) to `True` on matching tool definitions, causing the model to receive return type information for those tools.

For models that natively support return schemas (e.g. Google Gemini), the schema is passed as a structured field. For other models, it is injected into the tool description as JSON text.

Per-tool overrides (`Tool(..., include_return_schema=False)`) take precedence -- this capability only sets the flag on tools that haven't explicitly opted out.

```python
from pydantic_ai import Agent
from pydantic_ai.capabilities import IncludeToolReturnSchemas

agent = Agent('openai:gpt-5', capabilities=[IncludeToolReturnSchemas()])
```

#### Attributes

##### tools

Which tools should have their return schemas included.

-   `'all'` (default): every tool gets its return schema included.
-   `Sequence[str]`: only tools whose names are listed.
-   `dict[str, Any]`: matches tools whose metadata deeply includes the specified key-value pairs.
-   Callable `(ctx, tool_def) -> bool`: custom sync or async predicate.

**Type:** `ToolSelector`\[`AgentDepsT`\] **Default:** `'all'`

### PrefixTools

**Bases:** `WrapperCapability[AgentDepsT]`

A capability that wraps another capability and prefixes its tool names.

Only the wrapped capability's tools are prefixed; other agent tools are unaffected.

```python
from pydantic_ai import Agent
from pydantic_ai.capabilities import PrefixTools, Toolset
from pydantic_ai.toolsets import FunctionToolset

toolset = FunctionToolset()

agent = Agent(
    'openai:gpt-5',
    capabilities=[
        PrefixTools(
            wrapped=Toolset(toolset),
            prefix='ns',
        ),
    ],
)
```

#### Methods

##### from\_spec

`@classmethod`

```python
def from_spec(cls, prefix: str, capability: CapabilitySpec) -> PrefixTools[Any]
```

Create from spec with a nested capability specification.

###### Returns

`PrefixTools`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

###### Parameters

**`prefix`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The prefix to add to tool names (e.g. `'mcp'` turns `'search'` into `'mcp_search'`).

**`capability`** : `CapabilitySpec`

A capability spec (same format as entries in the `capabilities` list).

### SetToolMetadata

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that merges metadata key-value pairs onto selected tools.

```python
from pydantic_ai import Agent
from pydantic_ai.capabilities import SetToolMetadata

agent = Agent('openai:gpt-5', capabilities=[SetToolMetadata(code_mode=True)])
```

### ThreadExecutor

**Bases:** `AbstractCapability[Any]`

Use a custom executor for running sync functions in threads.

By default, sync tool functions and other sync callbacks are run in threads using `anyio.to_thread.run_sync`, which creates ephemeral threads. In long-running servers (e.g. FastAPI), this can lead to thread accumulation under sustained load.

This capability provides a bounded [`ThreadPoolExecutor`](https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor) (or any [`Executor`](https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor)) to use instead, scoped to agent runs:

```python
from concurrent.futures import ThreadPoolExecutor

from pydantic_ai import Agent
from pydantic_ai.capabilities import ThreadExecutor

executor = ThreadPoolExecutor(max_workers=16, thread_name_prefix='agent-worker')
agent = Agent('openai:gpt-5.2', capabilities=[ThreadExecutor(executor)])
```

To set an executor for all agents globally, use [`Agent.using_thread_executor()`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.AbstractAgent.using_thread_executor).

#### Attributes

##### executor

The executor to use for running sync functions.

**Type:** `Executor`

### NativeTool

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that registers a native tool with the agent.

Wraps a single [`AgentNativeTool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.AgentNativeTool) -- either a static [`AbstractNativeTool`](/docs/ai/api/pydantic-ai/native_tools/#pydantic_ai.native_tools.AbstractNativeTool) instance or a callable that dynamically produces one.

Equivalent to passing the tool through `Agent(capabilities=[NativeTool(my_tool)])`. For provider-adaptive use (with a local fallback), see [`NativeOrLocalTool`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.NativeOrLocalTool) or its subclasses like [`WebSearch`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.WebSearch).

#### Methods

##### from\_spec

`@classmethod`

```python
def from_spec(
    cls,
    tool: AbstractNativeTool | None = None,
    kwargs: Any = {},
) -> NativeTool[Any]
```

Create from spec.

Supports two YAML forms:

-   Flat: `{NativeTool: {kind: web_search, search_context_size: high}}`
-   Explicit: `{NativeTool: {tool: {kind: web_search}}}`

###### Returns

`NativeTool`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

### WebFetch

**Bases:** `NativeOrLocalTool[AgentDepsT]`

URL fetching capability.

Uses the model's native URL fetching when available, falling back to a local function tool (markdownify-based fetch by default) when it isn't.

The local fallback requires the `web-fetch` optional group:

Terminal

```bash
pip install "pydantic-ai-slim[web-fetch]"
```

#### Attributes

##### allowed\_domains

Only fetch from these domains. Enforced locally when native is unavailable.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `allowed_domains`

##### blocked\_domains

Never fetch from these domains. Enforced locally when native is unavailable.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `blocked_domains`

##### max\_uses

Maximum number of fetches per run. Requires native support.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `max_uses`

##### enable\_citations

Enable citations for fetched content. Native-only; ignored by local tools.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `enable_citations`

##### max\_content\_tokens

Maximum content length in tokens. Native-only; ignored by local tools.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `max_content_tokens`

### DynamicCapability

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that builds another capability dynamically using a function that takes the run context.

The factory is called once per agent run from [`for_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.for_run). The returned capability replaces this wrapper for the rest of the run, so its instructions, model settings, toolset, native tools, and hooks all flow through normally.

Pass a [`CapabilityFunc`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CapabilityFunc) directly to `Agent(capabilities=[...])` or `agent.run(capabilities=[...])` and it will be wrapped in a `DynamicCapability` automatically.

`defer_loading` on the wrapper itself is rejected because `for_run` replaces the wrapper with the factory's return value. Set it on the returned capability instead. For history replay, set a stable `id` on the capability the factory returns rather than on the wrapper.

#### Attributes

##### capability\_func

The function that takes the run context and returns a capability or `None`.

**Type:** [`CapabilityFunc`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CapabilityFunc)\[`AgentDepsT`\]

### ImageGeneration

**Bases:** `NativeOrLocalTool[AgentDepsT]`

Image generation capability.

Uses the model's native image generation when available. When the model doesn't support it and `fallback_model` is provided, falls back to a local tool that delegates to a subagent running the specified image-capable model.

Image generation settings (`quality`, `size`, etc.) are forwarded to the [`ImageGenerationTool`](/docs/ai/api/pydantic-ai/native_tools/#pydantic_ai.native_tools.ImageGenerationTool) used by both the native and the local fallback subagent. When passing a custom `native` instance, its settings are also used for the fallback subagent; capability-level fields override any `native` instance settings.

#### Attributes

##### fallback\_model

Model to use for image generation when the agent's model doesn't support it natively.

Must be a model that supports image generation via the [`ImageGenerationTool`](/docs/ai/api/pydantic-ai/native_tools/#pydantic_ai.native_tools.ImageGenerationTool) native tool. This requires a conversational model with image generation support, not a dedicated image-only API. Examples:

-   `'openai-responses:gpt-5.4'` -- OpenAI model with image generation support
-   `'google:gemini-3-pro-image-preview'` -- Google image generation model

Can be a model name string, `Model` instance, or a callable taking `RunContext` that returns a `Model` instance.

**Type:** `ImageGenerationFallbackModel` **Default:** `fallback_model`

##### action

Whether to generate a new image or edit an existing image.

Supported by: OpenAI Responses. Default: `'auto'`.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['generate', 'edit', 'auto'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `action`

##### background

Background type for the generated image.

Supported by: OpenAI Responses. `'transparent'` only supported for `'png'` and `'webp'`.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['transparent', 'opaque', 'auto'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `background`

##### input\_fidelity

Input fidelity for matching style/features of input images.

Supported by: OpenAI Responses. Default: `'low'`.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['high', 'low'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `input_fidelity`

##### moderation

Moderation level for the generated image.

Supported by: OpenAI Responses.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['auto', 'low'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `moderation`

##### image\_model

The image generation model to use.

Supported by: OpenAI Responses.

**Type:** `ImageGenerationModelName` | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `image_model`

##### output\_compression

Compression level for the output image.

Supported by: OpenAI Responses (jpeg/webp, default: 100), Google Cloud (jpeg, default: 75).

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `output_compression`

##### output\_format

Output format of the generated image.

Supported by: OpenAI Responses (default: `'png'`), Google Cloud.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['png', 'webp', 'jpeg'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `output_format`

##### quality

Quality of the generated image.

Supported by: OpenAI Responses.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['low', 'medium', 'high', 'auto'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `quality`

##### size

Size of the generated image.

Supported by: OpenAI Responses (`'auto'`, `'1024x1024'`, `'1024x1536'`, `'1536x1024'`), Google (`'512'`, `'1K'`, `'2K'`, `'4K'`).

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['auto', '1024x1024', '1024x1536', '1536x1024', '512', '1K', '2K', '4K'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `size`

##### aspect\_ratio

Aspect ratio for generated images.

Supported by: Google (Gemini), OpenAI Responses (maps `'1:1'`, `'2:3'`, `'3:2'` to sizes).

**Type:** `ImageAspectRatio` | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `aspect_ratio`

### NativeOrLocalTool

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that pairs a provider-native tool with a local fallback.

When the model supports the native tool, the local fallback is removed. When the model doesn't support the native tool, it is removed and the local tool stays.

Can be used directly:

```python
from pydantic_ai.capabilities import NativeOrLocalTool

cap = NativeOrLocalTool(native=WebSearchTool(), local=my_search_func)
```

Or subclassed to set defaults by overriding `_default_native`, `_default_local`, and `_requires_native`. The built-in [`WebSearch`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.WebSearch), [`WebFetch`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.WebFetch), and [`ImageGeneration`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.ImageGeneration) capabilities are all subclasses.

#### Attributes

##### native

Configure the provider-native tool.

-   `True` (default): use the default native tool configuration (subclasses only).
-   `False`: disable the native tool; always use the local tool.
-   An `AbstractNativeTool` instance: use this specific configuration.
-   A callable (`NativeToolFunc`): dynamically create the native tool per-run via `RunContext`.

**Type:** [`AgentNativeTool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.AgentNativeTool)\[`AgentDepsT`\] | [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `native`

##### local

Configure the local fallback tool.

-   `None` (default): auto-detect a local fallback via `_default_local`.
-   `True`: opt in to the default local fallback (resolved via `_resolve_local_strategy`).
-   `False`: disable the local fallback; only use the native tool.
-   A named strategy (e.g. `'duckduckgo'`): resolved via `_resolve_local_strategy` in subclasses.
-   A `Tool` or `AbstractToolset` instance: use this specific local tool.
-   A bare callable: automatically wrapped in a `Tool`.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[`AgentDepsT`\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`AbstractToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.AbstractToolset)\[`AgentDepsT`\] | [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `local`

### ProcessEventStream

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that forwards the agent's event stream to a user-provided async handler.

The handler receives the stream of [`AgentStreamEvent`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.AgentStreamEvent)s emitted during model streaming and tool execution for each `ModelRequestNode` and `CallToolsNode`. Two forms are supported:

-   An [`EventStreamHandler`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.EventStreamHandler) -- an `async def` returning `None`. Events are forwarded to the handler while also being passed through unchanged to the rest of the capability chain, so multiple handlers (and the top-level `event_stream_handler` argument) can all see the same stream without changing each other's view. A handler that returns early stops receiving events but does not affect downstream consumers; a handler that raises propagates the exception to the rest of the run. Events are delivered synchronously, so a slow handler back-pressures the rest of the stream.
-   An `EventStreamProcessor` -- an async generator yielding [`AgentStreamEvent`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.AgentStreamEvent)s. The events it yields replace the inner stream for downstream wrappers and consumers, so it can modify, drop, or add events.

When this capability is registered, `agent.run()` automatically enables streaming so the handler fires without requiring an explicit `event_stream_handler` argument.

Durable execution

Under the current durable-execution integrations ([Temporal](/docs/ai/api/pydantic-ai/durable_exec/#pydantic_ai.durable_exec.temporal.TemporalAgent), [DBOS](/docs/ai/api/pydantic-ai/durable_exec/#pydantic_ai.durable_exec.dbos.DBOSAgent), [Prefect](/docs/ai/api/pydantic-ai/durable_exec/#pydantic_ai.durable_exec.prefect.PrefectAgent)), model streaming happens inside an activity/step rather than in the outer agent loop. This capability's `wrap_run_event_stream` hook fires for tool-call events and the final post-streaming batch, but it does **not** see individual model-response events live -- the underlying durable model consumes those inside the activity before returning. The in-flight `event_stream_handler` parameter does still observe the live events; a future refactor threading the capability chain through the activity boundary is being explored in [#4977](https://github.com/pydantic/pydantic-ai/pull/4977).

### WebSearch

**Bases:** `NativeOrLocalTool[AgentDepsT]`

Web search capability.

Uses the model's native web search when available, falling back to a local function tool (DuckDuckGo by default) when it isn't.

#### Attributes

##### search\_context\_size

Controls how much context is retrieved from the web. Native-only; ignored by local tools.

**Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['low', 'medium', 'high'\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `search_context_size`

##### user\_location

Localize search results based on user location. Native-only; ignored by local tools.

**Type:** [`WebSearchUserLocation`](/docs/ai/api/pydantic-ai/native_tools/#pydantic_ai.native_tools.WebSearchUserLocation) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `user_location`

##### blocked\_domains

Domains to exclude from results. Requires native support.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `blocked_domains`

##### allowed\_domains

Only include results from these domains. Requires native support.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `allowed_domains`

##### max\_uses

Maximum number of web searches per run. Requires native support.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `max_uses`

### XSearch

**Bases:** `NativeOrLocalTool[AgentDepsT]`

X (Twitter) search capability.

On xAI models, uses the native X search directly with no extra configuration.

On non-xAI models, you must explicitly set `fallback_model` to an xAI model (e.g. `'xai:grok-4.3'`) to enable a subagent-based fallback. There is no default fallback model -- attempting to use `XSearch` on a non-xAI model without `fallback_model` will error.

#### Attributes

##### fallback\_model

Model to use for X search when the agent's model doesn't support it natively.

Required for non-xAI models; leave as `None` (the default) when running on an xAI model. Must be a model that supports X search via the [`XSearchTool`](/docs/ai/api/pydantic-ai/native_tools/#pydantic_ai.native_tools.XSearchTool) native tool (i.e. an xAI model), for example `'xai:grok-4.3'`.

Can be a model name string, `Model` instance, or a callable taking `RunContext` that returns a `Model` instance.

**Type:** `XSearchFallbackModel` **Default:** `fallback_model`

##### allowed\_x\_handles

If provided, only posts from these X handles will be included (max 10).

Honored by the native X search tool, whether used directly on an xAI model or via the `fallback_model` subagent.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `allowed_x_handles`

##### excluded\_x\_handles

If provided, posts from these X handles will be excluded (max 10).

Honored by the native X search tool, whether used directly on an xAI model or via the `fallback_model` subagent.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `excluded_x_handles`

##### from\_date

If provided, only posts created on or after this datetime will be included.

**Type:** [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `from_date`

##### to\_date

If provided, only posts created on or before this datetime will be included.

**Type:** [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `to_date`

##### enable\_image\_understanding

Enable image analysis from X posts. When unset, inherits the native tool's default (`False`).

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `enable_image_understanding`

##### enable\_video\_understanding

Enable video analysis from X content. When unset, inherits the native tool's default (`False`).

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `enable_video_understanding`

##### include\_output

Include raw X search results in the response as [`NativeToolReturnPart`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.NativeToolReturnPart).

When unset, inherits the native tool's default (`False`).

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `include_output`

### ReinjectSystemPrompt

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that reinjects the agent's configured `system_prompt` when missing from history.

Ensures the agent's configured `system_prompt` is present at the head of the first `ModelRequest` on every model request.

Intended for callers that reconstruct a `message_history` from a source that doesn't round-trip system prompts -- UI frontends, database persistence layers, conversation compaction pipelines. By default, if any `SystemPromptPart` is already present anywhere in the history (for example, preserved from a prior run or handed off from another agent), this capability leaves the messages untouched so that existing system prompts remain authoritative. Set `replace_existing=True` to instead strip any existing `SystemPromptPart`s before prepending the agent's configured prompt -- useful when the history comes from an untrusted source (such as a UI frontend) and the server's prompt must win.

The UI adapters automatically add this capability in `manage_system_prompt='server'` mode with `replace_existing=True`. Add it explicitly with `Agent(..., capabilities=[ReinjectSystemPrompt()])` or per-run via the `capabilities=` argument on [`Agent.run`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.AbstractAgent.run) to get the same behavior anywhere.

#### Attributes

##### replace\_existing

If `True`, strip any existing `SystemPromptPart`s from the history before prepending the agent's configured prompt. If `False` (the default), the capability is a no-op when any `SystemPromptPart` is already present.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `False`

### ProcessHistory

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that processes message history before model requests.

### Capability

**Bases:** `AbstractCapability[AgentDepsT]`

Convenience capability for bundling instructions, tools, and toolsets without subclassing.

This groups related instructions, descriptions, function tools, and toolsets under a capability identity. Instructions passed via `instructions=` are available through `get_instructions()`; [`instructions`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.Capability.instructions) is the decorator for registering instruction functions. The constructor accepts static or callable `description=` values. For model settings, lifecycle hooks, native tools, wrapper toolsets, or custom per-run logic, subclass [`AbstractCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability).

#### Attributes

##### description

Static description mirrored on the instance.

The constructor also accepts callable descriptions, stored internally and returned from `get_description()`.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `description if isinstance(description, str) else None`

##### toolsets

Toolsets to register with the agent. Combined via [`CombinedToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.CombinedToolset) when more than one is provided.

**Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[`AgentToolset`\[`AgentDepsT`\]\] **Default:** `resolved_toolsets`

##### tools

Function tools to register with the agent.

**Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[`AgentDepsT`\] | `ToolFuncEither`\[`AgentDepsT`, ...\]\] **Default:** `tools`

#### Methods

##### \_\_init\_\_

```python
def __init__(
    instructions: AgentInstructions[AgentDepsT] | None = None,
    toolsets: Sequence[AgentToolset[AgentDepsT]] | None = None,
    tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] = (),
    id: str | None = None,
    description: CapabilityDescription[AgentDepsT] | None = None,
    defer_loading: bool = False,
) -> None
```

Build a capability from instructions, tools, toolsets, and an optional description.

###### Returns

[`None`](https://docs.python.org/3/library/constants.html#None)

###### Parameters

**`instructions`** : `AgentInstructions`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Static instructions and/or instruction function(s), available via `get_instructions()`. Register more with the [`instructions`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.Capability.instructions) decorator.

**`toolsets`** : [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[`AgentToolset`\[`AgentDepsT`\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Toolsets to register with the agent.

**`tools`** : [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[`AgentDepsT`\] | `ToolFuncEither`\[`AgentDepsT`, ...\]\] _Default:_ `()`

Function tools to register with the agent.

**`id`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Stable identifier for the capability. Required when `defer_loading=True`, so the model's `load_capability` call can reference it.

**`description`** : `CapabilityDescription`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Static string or callable description, returned from `get_description()`. For a deferred capability it is shown to the model so it can decide whether to load it.

**`defer_loading`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False`

When `True`, the capability's tools and instructions stay hidden until the model loads it on demand via the `load_capability` tool; requires `id`.

##### tool\_plain

```python
def tool_plain(func: ToolFuncPlain[ToolParams]) -> ToolFuncPlain[ToolParams]
def tool_plain(
    name: str | None = None,
    description: str | None = None,
    retries: int | None = None,
    prepare: ToolPrepareFunc[AgentDepsT] | None = None,
    args_validator: ArgsValidatorFunc[AgentDepsT, ToolParams] | None = None,
    docstring_format: DocstringFormat = 'auto',
    require_parameter_descriptions: bool = False,
    schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
    strict: bool | None = None,
    sequential: bool = False,
    requires_approval: bool = False,
    metadata: dict[str, Any] | None = None,
    timeout: float | None = None,
    defer_loading: bool = False,
    include_return_schema: bool | None = None,
) -> Callable[[ToolFuncPlain[ToolParams]], ToolFuncPlain[ToolParams]]
```

Decorator to register a plain (no-[`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext)) function tool on this capability.

Mirrors [`Agent.tool_plain`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.Agent.tool_plain): the tool is added to this capability's function toolset and registered with the agent whenever the capability is active.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### tool

```python
def tool(
    func: ToolFuncContext[AgentDepsT, ToolParams],
) -> ToolFuncContext[AgentDepsT, ToolParams]
def tool(
    name: str | None = None,
    description: str | None = None,
    retries: int | None = None,
    prepare: ToolPrepareFunc[AgentDepsT] | None = None,
    args_validator: ArgsValidatorFunc[AgentDepsT, ToolParams] | None = None,
    docstring_format: DocstringFormat = 'auto',
    require_parameter_descriptions: bool = False,
    schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
    strict: bool | None = None,
    sequential: bool = False,
    requires_approval: bool = False,
    metadata: dict[str, Any] | None = None,
    timeout: float | None = None,
    defer_loading: bool = False,
    include_return_schema: bool | None = None,
) -> Callable[[ToolFuncContext[AgentDepsT, ToolParams]], ToolFuncContext[AgentDepsT, ToolParams]]
```

Decorator to register a function tool (taking [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext)) on this capability.

Mirrors [`Agent.tool`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.Agent.tool): the tool is added to this capability's function toolset and registered with the agent whenever the capability is active.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### instructions

```python
def instructions(
    func: Callable[[RunContext[AgentDepsT]], str | None],
) -> Callable[[RunContext[AgentDepsT]], str | None]
def instructions(
    func: Callable[[RunContext[AgentDepsT]], Awaitable[str | None]],
) -> Callable[[RunContext[AgentDepsT]], Awaitable[str | None]]
def instructions(func: Callable[[], str | None]) -> Callable[[], str | None]
def instructions(
    func: Callable[[], Awaitable[str | None]],
) -> Callable[[], Awaitable[str | None]]
def instructions(

) -> Callable[[SystemPromptFunc[AgentDepsT]], SystemPromptFunc[AgentDepsT]]
```

Decorator to register an instructions function on this capability.

Mirrors `Agent.instructions`: the function may take [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext) (or no arguments), may be sync or async, and is appended to any instructions provided via the `instructions=` field.

Example:

```python
from pydantic_ai import RunContext
from pydantic_ai.capabilities import Capability

cap = Capability[str](instructions='base instructions')

@cap.instructions
async def dynamic(ctx: RunContext[str]) -> str:
    return f'extra: {ctx.deps}'
```

###### Returns

[`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`SystemPromptFunc`\[`AgentDepsT`\]\], `SystemPromptFunc`\[`AgentDepsT`\]\] | `SystemPromptFunc`\[`AgentDepsT`\]

### ToolSearch

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that provides tool discovery for large toolsets.

Tools marked with `defer_loading=True` are hidden from the model until discovered. Auto-injected into every agent -- zero overhead when no deferred tools exist.

When the model supports native tool search (Anthropic BM25/regex, OpenAI Responses), discovery is handled by the provider: the deferred tools are sent with `defer_loading` on the wire and the provider exposes them once they've been discovered. Otherwise, discovery happens locally via a `search_tools` function that the model can call.

On providers that support a native "client-executed" surface (Anthropic, OpenAI), the discovery message is delivered append-only -- prompt cache is preserved across discovery turns, so growing the message history with discovered-tool results does not invalidate the cached prefix.

```python
from collections.abc import Sequence

from pydantic_ai import Agent, RunContext, Tool
from pydantic_ai.capabilities import ToolSearch
from pydantic_ai.tools import ToolDefinition


# Tools become deferred via `defer_loading=True`. They stay hidden from the model
# until tool search discovers them.
def get_weather(city: str) -> str:
    ...


weather_tool = Tool(get_weather, defer_loading=True)

# Default: native search on supporting providers, local keyword matching elsewhere.
agent = Agent('anthropic:claude-sonnet-4-6', tools=[weather_tool], capabilities=[ToolSearch()])

# Force a specific Anthropic native strategy; errors on providers that can't honor it.
agent = Agent(
    'anthropic:claude-sonnet-4-6',
    tools=[weather_tool],
    capabilities=[ToolSearch(strategy='regex')],
)

# Always run the local keyword-overlap algorithm, regardless of provider.
agent = Agent(
    'anthropic:claude-sonnet-4-6',
    tools=[weather_tool],
    capabilities=[ToolSearch(strategy='keywords')],
)

# Custom search function -- used locally, and by provider-native "client-executed"
# modes when supported.
def my_search(
    ctx: RunContext[None], queries: Sequence[str], tools: Sequence[ToolDefinition]
) -> list[str]:
    return [
        t.name
        for t in tools
        if any(q.lower() in (t.description or '').lower() for q in queries)
    ]

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    tools=[weather_tool],
    capabilities=[ToolSearch(strategy=my_search)],
)
```

#### Attributes

##### strategy

The search strategy to use.

-   `None` (default): let Pydantic AI pick the best strategy for the current provider -- native on supporting models (Anthropic BM25, OpenAI server-executed tool search), local keyword matching elsewhere. The choice may change in future versions.
-   `'keywords'`: always use the local keyword-overlap algorithm. Still prompt-cache compatible on providers that expose a "client-executed" native surface (Anthropic, OpenAI): the algorithm rides the same `defer_loading` wire as a custom callable, so the tool list stays stable across discovery rounds and the cached prefix is preserved.
-   `'bm25'` / `'regex'`: force a specific Anthropic native strategy. Raises on providers that can't honor the choice (including OpenAI, which has no named native strategies).
-   Callable `(ctx, queries, tools) -> names`: custom search function (sync or async). Used locally, and by the native "client-executed" surface on providers that support it (Anthropic custom tool-reference blocks, OpenAI `execution='client'`).

**Type:** `ToolSearchStrategy`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### max\_results

Maximum number of matches returned by the local search algorithm.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) **Default:** `10`

##### tool\_description

Custom description for the model-facing search tool when search runs on our side.

Used for the local `search_tools` fallback and for providers with client-executed native tool search.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### parameter\_description

Custom description for the `queries` parameter when search runs on our side.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

#### Methods

##### before\_model\_request

`@async`

```python
def before_model_request(
    ctx: RunContext[AgentDepsT],
    request_context: ModelRequestContext,
) -> ModelRequestContext
```

Append a synthetic tool-search exchange for tools unlocked by a capability load.

###### Returns

`ModelRequestContext`

### CombinedCapability

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that combines multiple capabilities.

### MCP

**Bases:** `NativeOrLocalTool[AgentDepsT]`

MCP server capability.

Uses the model's native MCP server support when available, connecting directly via HTTP when it isn't.

#### Attributes

##### description

Description of the MCP server. Native-only; ignored by local tools.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `description`

##### url

The URL of the MCP server.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) **Default:** `url`

##### authorization\_token

Authorization header value for MCP server requests. Passed to both native and local.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `authorization_token`

##### headers

HTTP headers for MCP server requests. Passed to both native and local.

**Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `headers`

##### allowed\_tools

Filter to only these tools. Applied to both native and local.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `allowed_tools`

#### Methods

##### from\_spec

`@classmethod`

```python
def from_spec(
    cls,
    url: str,
    native: MCPServerTool | bool = True,
    local: str | bool | None = None,
    id: str | None = None,
    authorization_token: str | None = None,
    headers: dict[str, str] | None = None,
    allowed_tools: list[str] | None = None,
    description: str | None = None,
    defer_loading: bool = False,
) -> MCP[AgentDepsT]
```

Construct an `MCP` capability from spec-serializable args.

Restricts the runtime-wide `local=` union to the JSON/YAML-serializable subset (`str | bool | None`) so `AgentSpec` schema generation works. Non-serializable runtime values like `fastmcp.Client`, `ClientTransport`, or pre-built `MCPToolset` instances can still be passed to `MCP(...)` directly -- they just can't roundtrip through a spec file.

###### Returns

`MCP`\[`AgentDepsT`\]

### WrapperCapability

**Bases:** `AbstractCapability[AgentDepsT]`

A capability that wraps another capability and delegates all methods.

Analogous to [`WrapperToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.WrapperToolset) for toolsets. Subclass and override specific methods to modify behavior while delegating the rest.

### PrepareOutputTools

**Bases:** `AbstractCapability[AgentDepsT]`

Capability that filters or modifies output tool definitions using a callable.

Mirrors [`PrepareTools`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.PrepareTools) for [output tools](/docs/ai/api/pydantic-ai/output/#pydantic_ai.output.ToolOutput). `ctx.retry`/`ctx.max_retries` reflect the **output** retry budget (`max_output_retries`), matching the output hook lifecycle.

```python
from pydantic_ai import Agent, RunContext
from pydantic_ai.capabilities import PrepareOutputTools
from pydantic_ai.output import ToolOutput
from pydantic_ai.tools import ToolDefinition


async def only_after_first_step(
    ctx: RunContext[None], tool_defs: list[ToolDefinition]
) -> list[ToolDefinition] | None:
    return tool_defs if ctx.run_step > 0 else []


agent = Agent(
    'openai:gpt-5',
    output_type=ToolOutput(str),
    capabilities=[PrepareOutputTools(only_after_first_step)],
)
```

### HistoryProcessor

**Bases:** `ProcessHistory[AgentDepsT]`

Deprecated alias for [`ProcessHistory`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.ProcessHistory).

### Instrumentation

**Bases:** `AbstractCapability[Any]`

Capability that instruments agent runs with OpenTelemetry/Logfire tracing.

When added to an agent via `capabilities=[Instrumentation(...)]`, this capability creates OpenTelemetry spans for the agent run, model requests, and tool executions.

Other capabilities can add attributes to these spans using the OpenTelemetry API (`opentelemetry.trace.get_current_span().set_attribute(key, value)`).

#### Attributes

##### settings

OTel/Logfire instrumentation settings. Defaults to `InstrumentationSettings()`, which uses the global `TracerProvider`/`LoggerProvider` (typically configured by `logfire.configure()`).

**Type:** [`InstrumentationSettings`](/docs/ai/api/models/instrumented/#pydantic_ai.models.instrumented.InstrumentationSettings) **Default:** `field(default_factory=(lambda: _default_settings()))`

#### Methods

##### from\_spec

`@classmethod`

```python
def from_spec(cls, kwargs: Any = {}) -> Instrumentation
```

Build an `Instrumentation` capability from a YAML/JSON spec.

Accepts the serializable subset of [`InstrumentationSettings`](/docs/ai/api/models/instrumented/#pydantic_ai.models.instrumented.InstrumentationSettings) kwargs (`include_binary_content`, `include_content`, `version`, `event_mode`, `use_aggregated_usage_attribute_names`). The OTel `tracer_provider`, `meter_provider`, and `logger_provider` fields can't be expressed in YAML and default to the global providers (typically configured via `logfire.configure()`).

YAML form:

capabilities:

-   Instrumentation: {} # default settings
-   Instrumentation: version: 2 include\_content: false

###### Returns

`Instrumentation`

##### for\_run

`@async`

```python
def for_run(ctx: RunContext[Any]) -> Instrumentation
```

Return a fresh copy for per-run state isolation.

###### Returns

`Instrumentation`

##### wrap\_output\_process

`@async`

```python
def wrap_output_process(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
    handler: WrapOutputProcessHandler,
) -> Any
```

Emit a span for output-function execution.

Output processing for plain validation (no function) is not span-worthy -- the validated value is the model's response itself, no user code ran. We open a span only when an output function will execute, regardless of whether the output arrived via a tool call. The span name reflects the function (or tool name when the function name is unavailable, e.g. union processors).

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

### HookTimeoutError

**Bases:** [`TimeoutError`](https://docs.python.org/3/library/exceptions.html#TimeoutError)

Raised when a hook function exceeds its configured timeout.

### CapabilityOrdering

Ordering constraints for a capability within a combined capability chain.

Capabilities follow middleware semantics: the first capability in the list is the **outermost** layer, wrapping all others. Declare ordering constraints via [`get_ordering`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_ordering) to control a capability's position in the chain regardless of how the user lists them.

When a [`CombinedCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CombinedCapability) is constructed, it topologically sorts its children to satisfy these constraints, preserving user-provided order as a tiebreaker.

#### Attributes

##### position

Fixed position in the chain, or `None` for user-provided order.

**Type:** `CapabilityPosition` | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### wraps

This capability wraps around (is outside of) these capabilities in the middleware chain.

Each entry can be a capability **type** (matches all instances of that type via `issubclass`) or a specific capability **instance** (matches by identity via `is`).

Note: instance refs use identity (`is`) matching, so if a capability's [`for_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.for_run) returns a new instance, refs to the original will no longer match. Use type refs when the target capability uses per-run state isolation.

**Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[`CapabilityRef`\] **Default:** `()`

##### wrapped\_by

This capability is wrapped by (is inside of) these capabilities in the middleware chain.

Each entry can be a capability **type** (matches all instances of that type via `issubclass`) or a specific capability **instance** (matches by identity via `is`).

Note: instance refs use identity (`is`) matching, so if a capability's [`for_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.for_run) returns a new instance, refs to the original will no longer match. Use type refs when the target capability uses per-run state isolation.

**Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[`CapabilityRef`\] **Default:** `()`

##### requires

These types must be present in the chain (no ordering implied).

**Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[`AbstractCapability`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\]\] **Default:** `()`

### AbstractCapability

**Bases:** `ABC`, `Generic[AgentDepsT]`

Abstract base class for agent capabilities.

A capability is a reusable, composable unit of agent behavior that can provide instructions, model settings, tools, and request/response hooks.

Lifecycle: capabilities are passed to an [`Agent`](/docs/ai/api/pydantic-ai/agent/#pydantic_ai.agent.Agent) at construction time, where most `get_*` methods are called to collect static configuration (instructions, model settings, toolsets, native tools). The exception is [`get_wrapper_toolset`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_wrapper_toolset), which is called per-run during toolset assembly. Then, on each model request during a run, the [`before_model_request`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.before_model_request) and [`after_model_request`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_model_request) hooks are called to allow dynamic adjustments.

See the [capabilities documentation](/docs/ai/api/pydantic-ai/capabilities) for built-in capabilities.

[`get_serialization_name`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_serialization_name) and [`from_spec`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.from_spec) support YAML/JSON specs (via `Agent.from_spec`); they have sensible defaults and typically don't need to be overridden.

#### Attributes

##### id

Optional identifier used to reference this capability within a run.

Must be unique within a run, not per instance: it identifies the capability across the run -- including the fresh instance a [`for_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.for_run) override may return -- rather than a specific object.

Required when `defer_loading=True`. If omitted for an always-available capability, the run derives a local id from the class name.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### description

Description of the capability.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### defer\_loading

If True, model-facing tools and instructions are hidden until the model explicitly loads the capability via the `load_capability` tool.

Model settings and lifecycle hooks are registered during run setup, but only apply or fire once the capability is loaded.

Requires a stable [`id`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.id) so message history can identify the capability. A [`description`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.description) or [`get_description`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_description) override is optional and only adds routing context to the load catalog.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `False`

##### has\_wrap\_node\_run

Whether this capability (or any sub-capability) overrides wrap\_node\_run.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool)

##### has\_wrap\_run\_event\_stream

Whether this capability (or any sub-capability) overrides wrap\_run\_event\_stream.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool)

#### Methods

##### apply

```python
def apply(visitor: Callable[[AbstractCapability[AgentDepsT]], None]) -> None
```

Run a visitor function on all leaf capabilities in this tree.

For a single capability, calls the visitor on itself. Overridden by [`CombinedCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CombinedCapability) to recursively visit all child capabilities.

###### Returns

[`None`](https://docs.python.org/3/library/constants.html#None)

##### get\_serialization\_name

`@classmethod`

```python
def get_serialization_name(cls) -> str | None
```

Return the name used for spec serialization (CamelCase class name by default).

Return None to opt out of spec-based construction.

###### Returns

[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)

##### from\_spec

`@classmethod`

```python
def from_spec(cls, args: Any = (), kwargs: Any = {}) -> AbstractCapability[Any]
```

Create from spec arguments. Default: `cls(*args, **kwargs)`.

Override when `__init__` takes non-serializable types.

###### Returns

`AbstractCapability`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

##### get\_ordering

```python
def get_ordering() -> CapabilityOrdering | None
```

Return ordering constraints for this capability, or `None` for default behavior.

Override to declare a fixed position (`'outermost'` / `'innermost'`), relative ordering (`wraps` / `wrapped_by` other capability types or instances), or dependency requirements (`requires`).

[`CombinedCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CombinedCapability) uses these to topologically sort its children at construction time.

###### Returns

`CapabilityOrdering` | [`None`](https://docs.python.org/3/library/constants.html#None)

##### for\_run

`@async`

```python
def for_run(ctx: RunContext[AgentDepsT]) -> AbstractCapability[AgentDepsT]
```

Return the capability instance to use for this agent run.

Called once per run, before `get_*()` re-extraction and before any hooks fire. Override to return a fresh instance for per-run state isolation. Default: return `self` (shared across runs).

###### Returns

`AbstractCapability`\[`AgentDepsT`\]

##### get\_instructions

```python
def get_instructions() -> AgentInstructions[AgentDepsT] | None
```

Return instructions to include in the system prompt, or None.

Return static instruction text, a dynamic instruction callable, or a sequence containing either. For dynamic per-request behavior, return a callable that receives [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext) or a `TemplateStr` -- not a dynamic string.

When [`defer_loading`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.defer_loading) is True, these instructions are resolved only after the model calls the `load_capability` tool for this capability.

###### Returns

`AgentInstructions`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### get\_description

```python
def get_description() -> CapabilityDescription[AgentDepsT] | None
```

Return a human-readable description of this capability, or None.

Surfaced to the model in the catalog shown with the `load_capability` tool when [`defer_loading`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.defer_loading) is True.

Return a static description string or a callable that receives [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext) (or no arguments) when the deferred capability catalog is rendered. Default: return the static `description` field.

###### Returns

`CapabilityDescription`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### get\_model\_settings

```python
def get_model_settings() -> AgentModelSettings[AgentDepsT] | None
```

Return model settings to merge into the agent's defaults, or None.

Return a static `ModelSettings` dict when the settings don't change between requests. Return a callable that receives [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext) when settings need to vary per step (e.g. based on `ctx.run_step` or `ctx.deps`).

When the callable is invoked, `ctx.model_settings` contains the merged result of all layers resolved before this capability (model defaults and agent-level settings). The returned dict is merged on top of that.

When [`defer_loading`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.defer_loading) is True, these settings are registered up front but merge as an empty dict until the model calls the `load_capability` tool for this capability.

###### Returns

`AgentModelSettings`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### get\_toolset

```python
def get_toolset() -> AgentToolset[AgentDepsT] | None
```

Return a toolset to register with the agent, or None.

###### Returns

`AgentToolset`\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### get\_native\_tools

```python
def get_native_tools() -> Sequence[AgentNativeTool[AgentDepsT]]
```

Return native tools to register with the agent.

###### Returns

[`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`AgentNativeTool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.AgentNativeTool)\[`AgentDepsT`\]\]

##### get\_builtin\_tools

```python
def get_builtin_tools() -> Sequence[AgentNativeTool[AgentDepsT]]
```

Deprecated: use [`get_native_tools`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_native_tools) instead.

###### Returns

[`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`AgentNativeTool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.AgentNativeTool)\[`AgentDepsT`\]\]

##### get\_wrapper\_toolset

```python
def get_wrapper_toolset(
    toolset: AbstractToolset[AgentDepsT],
) -> AbstractToolset[AgentDepsT] | None
```

Wrap the agent's assembled toolset, or return None to leave it unchanged.

Called per-run with the combined non-output toolset (after the [`prepare_tools`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.prepare_tools) hook has already wrapped it). Output tools are added separately and are not included.

Unlike value-contribution methods such as [`get_instructions`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_instructions), this receives the already assembled toolset and is called each run (after [`for_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.for_run)). When multiple capabilities provide wrappers, they follow middleware semantics: the first capability in the list wraps outermost (matching `wrap_*` hooks).

Use this to apply cross-cutting toolset wrappers like [`PreparedToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.PreparedToolset), [`FilteredToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.FilteredToolset), or custom [`WrapperToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.WrapperToolset) subclasses.

###### Returns

[`AbstractToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.AbstractToolset)\[`AgentDepsT`\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### prepare\_tools

`@async`

```python
def prepare_tools(
    ctx: RunContext[AgentDepsT],
    tool_defs: list[ToolDefinition],
) -> list[ToolDefinition]
```

Filter or modify function tool definitions for this step.

Receives **function** tools only. For [output tools](/docs/ai/api/pydantic-ai/output/#pydantic_ai.output.ToolOutput), override [`prepare_output_tools`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.prepare_output_tools) -- it runs separately, with `ctx.retry`/`ctx.max_retries` reflecting the **output** retry budget instead of the function-tool budget.

Return a filtered or modified list. The result flows into both the model's request parameters and `ToolManager.tools`, so filtering also blocks tool execution.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`ToolDefinition`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.ToolDefinition)\]

##### prepare\_output\_tools

`@async`

```python
def prepare_output_tools(
    ctx: RunContext[AgentDepsT],
    tool_defs: list[ToolDefinition],
) -> list[ToolDefinition]
```

Filter or modify output tool definitions for this step.

Receives only [output tools](/docs/ai/api/pydantic-ai/output/#pydantic_ai.output.ToolOutput). `ctx.retry` and `ctx.max_retries` reflect the **output** retry budget (agent-level `max_output_retries`), matching the output hook lifecycle.

Return a filtered or modified list. The result flows into both the model's request parameters and `ToolManager.tools`, so filtering also blocks tool execution.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`ToolDefinition`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.ToolDefinition)\]

##### before\_run

`@async`

```python
def before_run(ctx: RunContext[AgentDepsT]) -> None
```

Called before the agent run starts. Observe-only; use wrap\_run for modification.

###### Returns

[`None`](https://docs.python.org/3/library/constants.html#None)

##### after\_run

`@async`

```python
def after_run(
    ctx: RunContext[AgentDepsT],
    result: AgentRunResult[Any],
) -> AgentRunResult[Any]
```

Called after the agent run completes. Can modify the result.

###### Returns

[`AgentRunResult`](/docs/ai/api/pydantic-ai/run/#pydantic_ai.run.AgentRunResult)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

##### wrap\_run

`@async`

```python
def wrap_run(
    ctx: RunContext[AgentDepsT],
    handler: WrapRunHandler,
) -> AgentRunResult[Any]
```

Wraps the entire agent run. `handler()` executes the run.

If `handler()` raises and this method catches the exception and returns a result instead, the error is suppressed and the recovery result is used.

If this method does not call `handler()` (short-circuit), the run is skipped and the returned result is used directly.

Note: if the caller cancels the run (e.g. by breaking out of an `iter()` loop), this method receives an `asyncio.CancelledError`. Implementations that hold resources should handle cleanup accordingly.

###### Returns

[`AgentRunResult`](/docs/ai/api/pydantic-ai/run/#pydantic_ai.run.AgentRunResult)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

##### on\_run\_error

`@async`

```python
def on_run_error(
    ctx: RunContext[AgentDepsT],
    error: BaseException,
) -> AgentRunResult[Any]
```

Called when the agent run fails with an exception.

This is the error counterpart to [`after_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_run): while `after_run` is called on success, `on_run_error` is called on failure (after [`wrap_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_run) has had its chance to recover).

**Raise** the original `error` (or a different exception) to propagate it. **Return** an [`AgentRunResult`](/docs/ai/api/pydantic-ai/run/#pydantic_ai.run.AgentRunResult) to suppress the error and recover the run.

Not called for `GeneratorExit` or `KeyboardInterrupt`.

###### Returns

[`AgentRunResult`](/docs/ai/api/pydantic-ai/run/#pydantic_ai.run.AgentRunResult)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

##### before\_node\_run

`@async`

```python
def before_node_run(
    ctx: RunContext[AgentDepsT],
    node: AgentNode[AgentDepsT],
) -> AgentNode[AgentDepsT]
```

Called before each graph node executes. Can observe or replace the node.

###### Returns

`AgentNode`\[`AgentDepsT`\]

##### after\_node\_run

`@async`

```python
def after_node_run(
    ctx: RunContext[AgentDepsT],
    node: AgentNode[AgentDepsT],
    result: NodeResult[AgentDepsT],
) -> NodeResult[AgentDepsT]
```

Called after each graph node succeeds. Can modify the result (next node or `End`).

###### Returns

`NodeResult`\[`AgentDepsT`\]

##### wrap\_node\_run

`@async`

```python
def wrap_node_run(
    ctx: RunContext[AgentDepsT],
    node: AgentNode[AgentDepsT],
    handler: WrapNodeRunHandler[AgentDepsT],
) -> NodeResult[AgentDepsT]
```

Wraps execution of each agent graph node (run step).

Called for every node in the agent graph (`UserPromptNode`, `ModelRequestNode`, `CallToolsNode`). `handler(node)` executes the node and returns the next node (or `End`).

Override to inspect or modify nodes before execution, inspect or modify the returned next node, call `handler` multiple times (retry), or return a different node to redirect graph progression.

Note: this hook fires when using `agent.run()`, `agent.run_stream()`, and when manually driving an `agent.iter()` run with `agent_run.next()`, but it does **not** fire when iterating over the run with bare `async for` (which yields stream events, not node results).

When using `agent.run()` with `event_stream_handler`, the handler wraps both streaming and graph advancement (i.e. the model call happens inside the wrapper). When using `agent.run_stream()`, the handler wraps only graph advancement -- streaming happens before the wrapper because `run_stream()` must yield the stream to the caller while the stream context is still open, which cannot happen from inside a callback.

###### Returns

`NodeResult`\[`AgentDepsT`\]

##### on\_node\_run\_error

`@async`

```python
def on_node_run_error(
    ctx: RunContext[AgentDepsT],
    node: AgentNode[AgentDepsT],
    error: Exception,
) -> NodeResult[AgentDepsT]
```

Called when a graph node fails with an exception.

This is the error counterpart to [`after_node_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_node_run).

**Raise** the original `error` (or a different exception) to propagate it. **Return** a next node or `End` to recover and continue the graph.

Useful for recovering from [`UnexpectedModelBehavior`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.UnexpectedModelBehavior) by redirecting to a different node (e.g. retry with different model settings).

###### Returns

`NodeResult`\[`AgentDepsT`\]

##### wrap\_run\_event\_stream

`@async`

```python
def wrap_run_event_stream(
    ctx: RunContext[AgentDepsT],
    stream: AsyncIterable[AgentStreamEvent],
) -> AsyncIterable[AgentStreamEvent]
```

Wraps the event stream for a streamed node. Can observe or transform events.

Note: when this method is overridden (or [`Hooks.on.event`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.Hooks.on) / [`Hooks.on.run_event_stream`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.Hooks.on) are registered), `agent.run()` automatically enables streaming mode so this hook fires even without an explicit `event_stream_handler`.

###### Returns

[`AsyncIterable`](https://docs.python.org/3/library/typing.html#typing.AsyncIterable)\[[`AgentStreamEvent`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.AgentStreamEvent)\]

##### before\_model\_request

`@async`

```python
def before_model_request(
    ctx: RunContext[AgentDepsT],
    request_context: ModelRequestContext,
) -> ModelRequestContext
```

Called before each model request. Can modify messages, settings, and parameters.

###### Returns

`ModelRequestContext`

##### after\_model\_request

`@async`

```python
def after_model_request(
    ctx: RunContext[AgentDepsT],
    request_context: ModelRequestContext,
    response: ModelResponse,
) -> ModelResponse
```

Called after each model response. Can modify the response before further processing.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to reject the response and ask the model to try again. The original response is still appended to message history so the model can see what it said. Retries count against the output side of the agent's retry budget.

###### Returns

[`ModelResponse`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.ModelResponse)

##### wrap\_model\_request

`@async`

```python
def wrap_model_request(
    ctx: RunContext[AgentDepsT],
    request_context: ModelRequestContext,
    handler: WrapModelRequestHandler,
) -> ModelResponse
```

Wraps the model request. handler() calls the model.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to skip `on_model_request_error` and directly retry the model request with a retry prompt. If the handler was called, the model response is preserved in history for context (same as `after_model_request`).

###### Returns

[`ModelResponse`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.ModelResponse)

##### on\_model\_request\_error

`@async`

```python
def on_model_request_error(
    ctx: RunContext[AgentDepsT],
    request_context: ModelRequestContext,
    error: Exception,
) -> ModelResponse
```

Called when a model request fails with an exception.

This is the error counterpart to [`after_model_request`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_model_request).

**Raise** the original `error` (or a different exception) to propagate it. **Return** a [`ModelResponse`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.ModelResponse) to suppress the error and use the response as if the model call succeeded. **Raise** [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to retry the model request with a retry prompt instead of recovering or propagating.

Not called for [`SkipModelRequest`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.SkipModelRequest) or [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry).

###### Returns

[`ModelResponse`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.ModelResponse)

##### before\_tool\_validate

`@async`

```python
def before_tool_validate(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: RawToolArgs,
) -> RawToolArgs
```

Modify raw args before validation.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to skip validation and ask the model to redo the tool call.

###### Returns

`RawToolArgs`

##### after\_tool\_validate

`@async`

```python
def after_tool_validate(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: ValidatedToolArgs,
) -> ValidatedToolArgs
```

Modify validated args. Called only on successful validation.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to reject the validated args and ask the model to redo the tool call.

###### Returns

`ValidatedToolArgs`

##### wrap\_tool\_validate

`@async`

```python
def wrap_tool_validate(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: RawToolArgs,
    handler: WrapToolValidateHandler,
) -> ValidatedToolArgs
```

Wraps tool argument validation. handler() runs the validation.

###### Returns

`ValidatedToolArgs`

##### on\_tool\_validate\_error

`@async`

```python
def on_tool_validate_error(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: RawToolArgs,
    error: ValidationError | ModelRetry,
) -> ValidatedToolArgs
```

Called when tool argument validation fails.

This is the error counterpart to [`after_tool_validate`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_tool_validate). Fires for `ValidationError` (schema mismatch) and [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) (custom validator rejection).

**Raise** the original `error` (or a different exception) to propagate it. **Return** validated args to suppress the error and continue as if validation passed.

Not called for [`SkipToolValidation`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.SkipToolValidation).

###### Returns

`ValidatedToolArgs`

##### before\_tool\_execute

`@async`

```python
def before_tool_execute(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: ValidatedToolArgs,
) -> ValidatedToolArgs
```

Modify validated args before execution.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to skip execution and ask the model to redo the tool call.

###### Returns

`ValidatedToolArgs`

##### after\_tool\_execute

`@async`

```python
def after_tool_execute(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: ValidatedToolArgs,
    result: Any,
) -> Any
```

Modify result after execution.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to reject the tool result and ask the model to redo the tool call.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### wrap\_tool\_execute

`@async`

```python
def wrap_tool_execute(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: ValidatedToolArgs,
    handler: WrapToolExecuteHandler,
) -> Any
```

Wraps tool execution. handler() runs the tool.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### on\_tool\_execute\_error

`@async`

```python
def on_tool_execute_error(
    ctx: RunContext[AgentDepsT],
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: ValidatedToolArgs,
    error: Exception,
) -> Any
```

Called when tool execution fails with an exception.

This is the error counterpart to [`after_tool_execute`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_tool_execute).

**Raise** the original `error` (or a different exception) to propagate it. **Return** any value to suppress the error and use it as the tool result. **Raise** [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to ask the model to redo the tool call instead of recovering or propagating.

Not called for control flow exceptions ([`SkipToolExecution`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.SkipToolExecution), [`CallDeferred`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.CallDeferred), [`ApprovalRequired`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ApprovalRequired)) or retry signals ([`ToolRetryError`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ToolRetryError) from [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry)). Use [`wrap_tool_execute`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_tool_execute) to intercept retries.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### before\_output\_validate

`@async`

```python
def before_output_validate(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: RawOutput,
) -> RawOutput
```

Modify raw model output before validation/parsing.

The primary hook for pre-parse repair and normalization of model output. Fires only for structured output that requires parsing: prompted, native, tool, and union output. Does **not** fire for plain text or image output.

For structured text output, `output` is the raw text string from the model. For tool output, `output` is the raw tool arguments (string or dict).

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to skip validation and ask the model to try again with a custom message.

During streaming, this hook fires on every partial validation attempt as well as the final result. Check `ctx.partial_output` to distinguish and avoid expensive work on partial results.

###### Returns

`RawOutput`

##### after\_output\_validate

`@async`

```python
def after_output_validate(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
) -> Any
```

Modify validated output after successful parsing. Called only on success.

`output` is the **semantic value** the model was asked to produce -- e.g., a `MyModel` instance for `output_type=MyModel`, or `42` for `output_type=int`, or the input to a single-arg output function. For multi-arg output functions, this is the `dict` of arguments (the genuine multi-value input).

Note: this differs from _tool_ hooks (`after_tool_validate`), which always see `dict[str, Any]` -- tool args follow the schema contract. Output hooks see the semantic output value, regardless of how it's internally represented during validation.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to reject the validated output and ask the model to try again.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### wrap\_output\_validate

`@async`

```python
def wrap_output_validate(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: RawOutput,
    handler: WrapOutputValidateHandler,
) -> Any
```

Wraps output validation. handler(output) performs the validation.

[`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) from within the handler goes to [`on_output_validate_error`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.on_output_validate_error). `ModelRetry` raised directly (not from the handler) bypasses the error hook.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### on\_output\_validate\_error

`@async`

```python
def on_output_validate_error(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: RawOutput,
    error: ValidationError | ModelRetry,
) -> Any
```

Called when output validation fails.

This is the error counterpart to [`after_output_validate`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_output_validate).

**Raise** the original `error` (or a different exception) to propagate it. **Return** validated output to suppress the error and continue.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### before\_output\_process

`@async`

```python
def before_output_process(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
) -> Any
```

Modify validated output before processing (extraction, output function call).

`output` is the **semantic value** -- e.g., a `MyModel` instance or `42`, matching `after_output_validate`. For multi-arg output functions, it's the `dict` of args. See [`after_output_validate`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_output_validate) for a full explanation of the semantic-value contract.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to skip processing and ask the model to try again.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### after\_output\_process

`@async`

```python
def after_output_process(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
) -> Any
```

Modify result after output processing.

Raise [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) to reject the result and ask the model to try again.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### wrap\_output\_process

`@async`

```python
def wrap_output_process(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
    handler: WrapOutputProcessHandler,
) -> Any
```

Wraps output processing. handler(output) runs extraction + output function call.

[`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry) bypasses [`on_output_process_error`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.on_output_process_error) (treated as control flow, not an error).

During streaming, this fires only when partial validation succeeds, and on the final result. Check `ctx.partial_output` to skip expensive work on partial results.

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### on\_output\_process\_error

`@async`

```python
def on_output_process_error(
    ctx: RunContext[AgentDepsT],
    output_context: OutputContext,
    output: Any,
    error: Exception,
) -> Any
```

Called when output processing fails with an exception.

This is the error counterpart to [`after_output_process`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.after_output_process).

**Raise** the original `error` (or a different exception) to propagate it. **Return** any value to suppress the error and use it as the output.

Not called for retry signals ([`ToolRetryError`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ToolRetryError) from [`ModelRetry`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ModelRetry)).

###### Returns

[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)

##### handle\_deferred\_tool\_calls

`@async`

```python
def handle_deferred_tool_calls(
    ctx: RunContext[AgentDepsT],
    requests: DeferredToolRequests,
) -> DeferredToolResults | None
```

Handle deferred tool calls (approval-required or externally-executed) inline during an agent run.

Called by `ToolManager` when:

-   a tool raises [`ApprovalRequired`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.ApprovalRequired) or [`CallDeferred`](/docs/ai/api/pydantic-ai/exceptions/#pydantic_ai.exceptions.CallDeferred) during execution, or
-   the model calls a tool registered with `requires_approval=True` (see [Human-in-the-Loop Tool Approval](/docs/ai/tools-toolsets/deferred-tools#human-in-the-loop-tool-approval)) or a tool backed by [external execution](/docs/ai/tools-toolsets/deferred-tools#external-tool-execution).

Uses accumulation dispatch: each capability in the chain receives remaining unresolved requests and can resolve some or all of them. Results are merged and unresolved calls are passed to the next capability.

**Return** a [`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) to resolve some or all calls. **Return** `None` to leave all calls unresolved.

###### Returns

[`DeferredToolResults`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.DeferredToolResults) | [`None`](https://docs.python.org/3/library/constants.html#None)

##### prefix\_tools

```python
def prefix_tools(prefix: str) -> PrefixTools[AgentDepsT]
```

Returns a new capability that wraps this one and prefixes its tool names.

Only this capability's tools are prefixed; other agent tools are unaffected.

###### Returns

`PrefixTools`\[`AgentDepsT`\]

### OutputContext

Context about the output being processed, passed to output hooks.

#### Attributes

##### mode

The schema's output mode ('text', 'native', 'prompted', 'tool', 'image', 'auto').

This reflects the configured schema, not the format of this particular response. For example, a `ToolOutputSchema` with a `text_processor` (hybrid mode) reports `'tool'` even if the model returned text -- check [`tool_call`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.OutputContext.tool_call) to distinguish.

**Type:** `OutputMode`

##### output\_type

The resolved output type (e.g. MyModel, str). For output functions, the function's input type (what the model produces).

**Type:** [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None)

##### object\_def

The output object definition (schema, name, description), if structured output.

**Type:** `OutputObjectDefinition` | [`None`](https://docs.python.org/3/library/constants.html#None)

##### has\_function

Whether there's an output function to call in the execute step.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool)

##### function\_name

Name of the output function that will run, when known. `None` for union processors that dispatch by output subtype, or when the schema has no function.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### tool\_call

The tool call part, for tool-based output. `None` when the current output did not arrive via a tool call (text or image).

**Type:** [`ToolCallPart`](/docs/ai/api/pydantic-ai/messages/#pydantic_ai.messages.ToolCallPart) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### tool\_def

The tool definition, for tool-based output. `None` when the current output did not arrive via a tool call.

**Type:** [`ToolDefinition`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.ToolDefinition) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

##### allows\_text

Whether the schema accepts text output (including via a `text_processor` on a `ToolOutputSchema`).

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `False`

##### allows\_image

Whether the schema accepts image output.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `False`

##### allows\_deferred\_tools

Whether the schema accepts deferred tool requests as output.

**Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `False`

### Hooks

**Bases:** `AbstractCapability[AgentDepsT]`

Register hook functions via decorators or constructor kwargs.

For extension developers building reusable capabilities, subclass [`AbstractCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability) directly. For application code that needs a few hooks without the ceremony of a subclass, use `Hooks`.

Example using decorators:

```python
hooks = Hooks()

@hooks.on.before_model_request
async def log_request(ctx, request_context):
    print(f'Request: {request_context}')
    return request_context

agent = Agent('openai:gpt-5', capabilities=[hooks])
```

Example using constructor kwargs:

```python
agent = Agent('openai:gpt-5', capabilities=[
    Hooks(before_model_request=log_request)
])
```

#### Attributes

##### on

Decorator namespace for registering hook functions.

**Type:** `_HookRegistration`\[`AgentDepsT`\]

### CapabilityFunc

A sync/async function which takes a run context and returns a capability.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[RunContext[AgentDepsT]], AbstractCapability[AgentDepsT] | None | Awaitable[AbstractCapability[AgentDepsT] | None]]`

### AgentNode

Type alias for an agent graph node (`UserPromptNode`, `ModelRequestNode`, `CallToolsNode`).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'_agent_graph.AgentNode[AgentDepsT, Any]'`

### NodeResult

Type alias for the result of executing an agent graph node: either the next node or `End`.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'_agent_graph.AgentNode[AgentDepsT, Any] | End[FinalResult[Any]]'`

### WrapRunHandler

Handler type for [`wrap_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_run).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'Callable[[], Awaitable[AgentRunResult[Any]]]'`

### ToolSearchNativeStrategy

Named provider-native tool search strategy.

`'bm25'` and `'regex'` correspond to Anthropic's server-side tool search variants. OpenAI's Responses API does not expose distinct named native strategies, so these values are rejected by the OpenAI adapter.

**Default:** `Literal['bm25', 'regex']`

### WrapNodeRunHandler

Handler type for [`wrap_node_run`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_node_run).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'Callable[[_agent_graph.AgentNode[AgentDepsT, Any]], Awaitable[_agent_graph.AgentNode[AgentDepsT, Any] | End[FinalResult[Any]]]]'`

### WrapModelRequestHandler

Handler type for [`wrap_model_request`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_model_request).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'Callable[[ModelRequestContext], Awaitable[ModelResponse]]'`

### ToolSearchLocalStrategy

Named local tool search strategy.

`'keywords'` opts into the built-in keyword-overlap algorithm explicitly -- use this to lock in the current local algorithm rather than the `None` default (which lets Pydantic AI pick the best algorithm per provider and may change over time).

Future local strategies (e.g. local BM25, TF-IDF, regex) will join this Literal as they're added; the single-member shape today is forward-compat scaffolding.

**Default:** `Literal['keywords']`

### RawToolArgs

Type alias for raw (pre-validation) tool arguments.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `str | dict[str, Any]`

### ValidatedToolArgs

Type alias for validated tool arguments.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `dict[str, Any]`

### WrapToolValidateHandler

Handler type for [`wrap_tool_validate`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_tool_validate).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[RawToolArgs], Awaitable[ValidatedToolArgs]]`

### AgentCapability

A capability or a [`CapabilityFunc`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.CapabilityFunc) that takes a run context and returns one.

Use as the item type for `Agent(capabilities=[...])` and `agent.run(capabilities=[...])`. Functions are wrapped in a [`DynamicCapability`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.DynamicCapability) automatically.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `AbstractCapability[AgentDepsT] | CapabilityFunc[AgentDepsT]`

### WrapToolExecuteHandler

Handler type for [`wrap_tool_execute`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.wrap_tool_execute).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[ValidatedToolArgs], Awaitable[Any]]`

### ToolSearchFunc

Custom search function for [`ToolSearch`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.ToolSearch)'s `strategy` field.

Takes the run context, the list of search queries, and the deferred tool definitions, and returns the matching tool names ordered by relevance. Both sync and async implementations are accepted.

Usage `ToolSearchFunc[AgentDepsT]`.

**Default:** `Callable[[RunContext[AgentDepsT], Sequence[str], Sequence['ToolDefinition']], Sequence[str] | Awaitable[Sequence[str]]]`

### RawOutput

Type alias for raw output data (text or tool args).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `str | dict[str, Any]`

### WrapOutputValidateHandler

Handler type for wrap\_output\_validate.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[RawOutput], Awaitable[Any]]`

### CAPABILITY\_TYPES

Registry of all capability types that have a serialization name, mapping name to class.

**Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`type`](https://docs.python.org/3/glossary.html#term-type)\[`AbstractCapability`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\]\] **Default:** `{name: cls for cls in (NativeTool, ImageGeneration, IncludeToolReturnSchemas, Instrumentation, MCP, PrefixTools, PrepareTools, ProcessHistory, ReinjectSystemPrompt, SetToolMetadata, Thinking, ToolSearch, Toolset, WebFetch, WebSearch, XSearch) if (name := (cls.get_serialization_name())) is not None}`

### WrapOutputProcessHandler

Handler type for wrap\_output\_process.

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[Any], Awaitable[Any]]`

### CapabilityPosition

Position tier for a capability in the middleware chain.

-   `'outermost'`: in the outermost tier, before all non-outermost capabilities. Multiple capabilities can declare `'outermost'`; original list order breaks ties within the tier, and `wraps`/`wrapped_by` edges refine order further.
-   `'innermost'`: in the innermost tier, after all non-innermost capabilities. Same tie-breaking rules apply.

**Default:** `Literal['outermost', 'innermost']`

### ToolSearchStrategy

Strategy value accepted by [`ToolSearch.strategy`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.ToolSearch.strategy).

-   `'keywords'`: force the local keyword-overlap algorithm regardless of provider.
-   `'bm25'` / `'regex'`: force a specific provider-native strategy (Anthropic). The request fails on providers that can't honor the choice.
-   Callable `(ctx, queries, tools) -> names`: custom search function. Used locally, and also by the native "client-executed" surface on providers that support it (Anthropic custom tool-reference blocks, OpenAI `ToolSearchToolParam(execution='client')`).

`None` is not part of the union -- it's accepted as the default on the [`ToolSearch.strategy`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.ToolSearch.strategy) field and means "let Pydantic AI pick"; see that field's docstring for details.

**Default:** `Union[ToolSearchFunc[AgentDepsT], ToolSearchLocalStrategy, ToolSearchNativeStrategy]`

### CapabilityRef

Reference to a capability -- either a type (matches all instances of that type) or a specific instance (matches by identity).

**Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'type[AbstractCapability[Any]] | AbstractCapability[Any]'`

### CapabilityDescription

Capability description: a static string, or a function (sync/async, with or without [`RunContext`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.RunContext)) that returns one.

For dynamic descriptions, return a callable from [`get_description`](/docs/ai/api/pydantic-ai/capabilities/#pydantic_ai.capabilities.AbstractCapability.get_description) rather than having the method itself take `RunContext`.

**Default:** `str | SystemPromptFunc[AgentDepsT]`