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[DeepAgentDeps]
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[DeepAgentDeps]
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[DeepAgentDeps]
Capability providing persistent agent memory across sessions.
Provides read_memory, write_memory, update_memory tools and injects existing memory into the system prompt.
Example
BrowserCapability¶
pydantic_deep.capabilities.BrowserCapability
dataclass
¶
Bases: AbstractCapability[DeepAgentDeps]
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.features.browser.capability 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[DeepAgentDeps]
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
|
Literal['warn', 'error']
|
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.features.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[DeepAgentDeps]
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.features.eviction.EvictionCapability
dataclass
¶
Bases: AbstractCapability[DeepAgentDeps]
Capability that intercepts large tool outputs via after_tool_execute.
The oversized result is saved to a file via the backend and replaced with a
compact preview plus a file reference, so the large output never enters the
message list. For ToolReturn values only return_value is size-checked;
multimodal content (e.g. BinaryContent screenshots) is preserved.
Multimodal binary parts accumulating across messages are bounded by
max_binary_content in before_model_request: older binaries are written to
the backend and replaced with a retrievable text reference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
AsyncBackendProtocol | 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.
|
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.
before_model_request(ctx, request_context)
async
¶
Bound the number of multimodal binary parts in message history.
Walks messages newest-to-oldest, keeps the most recent
max_binary_content BinaryContent parts, and replaces older ones with
a retrievable text reference. Binaries are left untouched when no backend
is available or a write fails.
PatchToolCallsCapability¶
pydantic_deep.features.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.