Capabilities API¶
Capabilities hook into the agent lifecycle via pydantic-ai's native
AbstractCapability API. They are registered through
the capabilities parameter of
create_deep_agent, or enabled through
dedicated feature flags. See Capabilities for the
conceptual overview.
SkillsCapability¶
pydantic_deep.capabilities.SkillsCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability providing skill discovery, loading, and execution.
Wraps SkillsToolset as a pydantic-ai capability with automatic
instruction injection listing available skills.
Example
ContextFilesCapability¶
pydantic_deep.capabilities.ContextFilesCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability that injects project context files into the agent's system prompt.
Loads files like AGENTS.md, SOUL.md and injects their content as instructions.
Example
MemoryCapability¶
pydantic_deep.capabilities.MemoryCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability providing persistent agent memory across sessions.
Provides read_memory, write_memory, update_memory tools and injects existing memory into the system prompt.
Example
TeamCapability¶
pydantic_deep.capabilities.TeamCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability for multi-agent team coordination.
When registry and task_fn are provided, team members
are registered as subagents and tasks execute via the subagent engine.
Example
PlanCapability¶
pydantic_deep.capabilities.PlanCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability providing interactive planning tools.
Provides ask_user and save_plan tools for structured planning workflow.
Example
BrowserCapability¶
pydantic_deep.capabilities.BrowserCapability
dataclass
¶
Bases: AbstractCapability[Any]
Provides a real async Playwright browser to the agent.
Manages the full browser lifecycle: Playwright and Chromium are started
lazily on the first browser-tool call and closed in a finally block,
guaranteeing cleanup on both success and failure paths. Runs that never
invoke a browser tool incur zero Playwright overhead.
Requires the browser optional extra::
pip install 'pydantic-deep[browser]'
playwright install chromium
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
headless
|
bool
|
Run the browser without a visible window (default |
True
|
allowed_domains
|
list[str] | None
|
Domain allowlist. |
None
|
screenshot_on_navigate
|
bool
|
Append a base64 screenshot to every |
False
|
max_content_tokens
|
int
|
Maximum estimated tokens for page content
(default |
DEFAULT_MAX_CONTENT_TOKENS
|
timeout_ms
|
int
|
Default Playwright navigation timeout in milliseconds
(default |
DEFAULT_TIMEOUT_MS
|
auto_install
|
bool
|
Automatically run |
True
|
Example::
from pydantic_ai import Agent
from pydantic_deep.capabilities.browser import BrowserCapability
agent = Agent(
"anthropic:claude-sonnet-4-6",
capabilities=[
BrowserCapability(
headless=True,
allowed_domains=["docs.python.org"],
)
],
)
result = await agent.run("What's new in Python 3.13?")
prepare_tools(ctx, tool_defs)
async
¶
Filter browser tools based on availability and approval state.
- When Chromium is not installed (
launch_erroris set), browser tools are hidden from the model entirely - no point offering tools that always return an error. - When the browser is available, any browser tool marked as
unapprovedis reset tofunctionso it never triggers approval dialogs.
wrap_run(ctx, *, handler)
async
¶
Install a lazy browser launcher and clean up after the run.
Both Playwright and Chromium are started only when the first browser tool is actually called. Runs that never use the browser incur zero Playwright overhead - no subprocess is spawned, no browser window appears.
A finally block guarantees cleanup of the browser and the
Playwright driver whether the run succeeds, raises, or is cancelled.
If Chromium is not installed and auto_install is True (the
default), playwright install chromium is run automatically on the
first tool call, and the launch is retried once.
StuckLoopDetection¶
pydantic_deep.capabilities.StuckLoopDetection
dataclass
¶
Bases: AbstractCapability[Any]
Capability that detects and breaks repetitive agent loops.
Tracks tool calls via after_tool_execute and detects three
patterns of stuck behavior. Per-run state isolation via for_run()
ensures concurrent runs don't interfere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_repeated
|
int
|
Number of repetitions before triggering (default 3). |
3
|
action
|
str
|
What to do when stuck - |
'warn'
|
detect_repeated
|
bool
|
Enable repeated identical call detection. |
True
|
detect_alternating
|
bool
|
Enable A-B-A-B pattern detection. |
True
|
detect_noop
|
bool
|
Enable no-op (same result) detection. |
True
|
ignore_tools
|
set[str]
|
Tool names exempt from all stuck-loop checks.
Use for polling primitives that are intentionally called
many times with identical arguments - e.g.
|
set()
|
pydantic_deep.capabilities.stuck_loop.StuckLoopError
¶
Bases: Exception
Raised when the agent is stuck in a loop and action is "error".
Attributes:
| Name | Type | Description |
|---|---|---|
pattern |
The detected pattern type ( |
|
message |
Human-readable description of the stuck loop. |
PeriodicReminderCapability¶
pydantic_deep.capabilities.PeriodicReminderCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability that periodically reminds the agent of its original task.
Uses before_model_request to increment a turn counter and inject a
reminder ModelRequest into the message history every N turns.
Per-run state isolation via for_run() ensures concurrent runs don't
share turn counters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PeriodicReminderConfig
|
:class: |
PeriodicReminderConfig()
|
HooksCapability¶
See the Hooks API for HooksCapability and the related
hook definitions.
EvictionCapability¶
pydantic_deep.processors.eviction.EvictionCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability that intercepts large tool outputs via after_tool_execute.
Unlike :class:EvictionProcessor (a history processor that runs after the
result is already in message history), this capability intercepts the tool
result before it enters the conversation - so the large output never
bloats the message list.
The evicted content is saved to a file via the backend, and the tool result is replaced with a compact preview + file reference.
For tool results that are :class:pydantic_ai.messages.ToolReturn values,
only the return_value is considered for size-based eviction; multimodal
content (such as :class:BinaryContent screenshots) is preserved.
Multimodal binary parts that accumulate across messages are bounded by
max_binary_content via :meth:before_model_request. Older binaries are
written to the backend and replaced with a compact retrievable text
reference, so the agent can still re-read them via read_file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
BackendProtocol | None
|
Fallback backend for writing evicted files. |
None
|
token_limit
|
int
|
Maximum estimated tokens before eviction (default: 20K). |
DEFAULT_TOKEN_LIMIT
|
eviction_path
|
str
|
Directory in the backend for evicted files. |
DEFAULT_EVICTION_PATH
|
head_lines
|
int
|
Lines from start in preview. |
DEFAULT_HEAD_LINES
|
tail_lines
|
int
|
Lines from end in preview. |
DEFAULT_TAIL_LINES
|
max_binary_content
|
int | None
|
Maximum multimodal binary parts to keep in
history. Older binaries are persisted to the backend and replaced
with a text reference. |
DEFAULT_MAX_BINARY_CONTENT
|
on_eviction
|
Callable[[str, str, int, int], Any] | None
|
Optional callback |
None
|
after_tool_execute(ctx, *, call, tool_def, args, result)
async
¶
Intercept large tool results before they enter message history.
ToolReturn results are handled specially: only return_value is
considered for size-based text eviction so multimodal content (e.g.
:class:BinaryContent screenshots) is never collapsed into a string.
before_model_request(ctx, request_context)
async
¶
Bound the number of multimodal binary parts in message history.
Walks request_context.messages newest-to-oldest and keeps the most
recent max_binary_content :class:BinaryContent parts. Older
binaries are written to the runtime backend and replaced with a
compact text reference so the agent can still retrieve them via
read_file. Binaries are left untouched when no backend is
available or when a write fails, to avoid losing data.
PatchToolCallsCapability¶
pydantic_deep.processors.patch.PatchToolCallsCapability
dataclass
¶
Bases: AbstractCapability[Any]
Capability that fixes orphaned tool calls/results via before_model_request.
Repairs two cases before each model request:
- Orphaned tool calls -
ToolCallPartwithout a matchingToolReturnPart→ injects a synthetic return with"Tool call was cancelled.". - Orphaned tool results -
ToolReturnPartwithout a matchingToolCallPart→ removes the orphaned return.
This replaces the patch_tool_calls_processor history processor with a
capability hook that runs at the same lifecycle point but integrates with
the pydantic-ai capabilities system.
before_model_request(ctx, request_context)
async
¶
Patch orphaned tool calls/results before each model request.