Error Recovery for AI Agents
This package ships error handling and recovery patterns for improved reliability of AI Agents, as a native Pydantic AI 2.0 capability.
Motivation
Agentic tool calling can fail for many reasons, and adding error handling and retries to every tool is cumbersome. For third-party tools and MCPs, it's often impossible. ToolErrorRecovery is a standardized capability for AI agents to recover from errors during tool calls. Similar in spirit to FastAPI's exception handlers, but for agents.
Related Work
This package combines the ideas and vocabulary of pydantic-ai-harness PR #171 with its own mechanics: it uses a classify callable rather than a per-tool strategy map for more flexibility; a single wrap_tool_execute hook rather than two; and does not expose str(error) to the agent by default for added security. It is intended as a stand-alone capability, but also as a proposal of how to make progress on PR #171.
Quick Start
pip install pydantic-ai-error-recovery
from pydantic_ai import Agent
from pydantic_ai_error_recovery import ToolErrorRecovery
agent = Agent('openai:gpt-5', capabilities=[ToolErrorRecovery()])
Out of the box, connection errors are retried, bugs are propagated, and everything else is reported to the model, preventing a crash of the agent run. Continue reading to learn how to customize the capability.
Features
The ToolErrorRecovery capability supports four different recovery outcomes:
| Outcome | Effect |
|---|---|
| retry | Re-attempt the tool call a number of times (invisible to the model) |
| inform | Report a terminal failure to the model via ToolFailed (outcome='failed') |
| fallback | Return a substitute value as the tool result |
| propagate | Re-raise the exception, will crash the run unless caught by another wrapper |
Error Classification
ToolErrorRecovery intercepts tool execution errors and applies a per-error reaction. A classify callable you supply inspects each failure and returns the intended recovery outcome:
def classify(ctx: RunContext[Any], call: ToolCallPart, error: BaseException) -> RecoveryOutcome:
if isinstance(error, SomeException):
return RecoveryOutcome.inform(
label='Tool call ran into SomeException',
expose_message=False,
)
# and so on
Notes:
- You can classify on a tool's name and other properties of the tool call, on the exception type, or both.
- The
ctx: RunContextparameter is included for cases in which your classification logic additionally depends on the run context. - To not interfere with existing error handling, the following exceptions from the Pydantic AI control flow are never classified:
SkipToolExecution,CallDeferred,ApprovalRequired,ModelRetry,ToolRetryError,ToolFailed, andToolFailedError. - Special care must be taken when classifying an exception which is a subclass, be careful about the order of
isinstance(...)calls, or usetype(...) isinstead.
Default Behaviour
As mentioned above, control flow exceptions are never classified. Our default classifier is:
def classify(ctx: RunContext[Any], call: ToolCallPart, error: BaseException) -> RecoveryOutcome:
if isinstance(error, DEFAULT_BUG_TYPES):
return RecoveryOutcome.propagate()
if isinstance(error, HookTimeoutError):
return RecoveryOutcome.inform()
if isinstance(error, DEFAULT_TRANSIENT_TYPES):
return RecoveryOutcome.retry(3)
return RecoveryOutcome.inform()
The classification function is the key piece required to construct your own RecoveryPolicy via RecoveryPolicy(classify=classify). A fully custom example could look like this:
from pydantic_ai import Agent
from pydantic_ai_error_recovery import ToolErrorRecovery
def classify(...):
# your classification logic
agent = Agent('openai:gpt-5', capabilities=[
ToolErrorRecovery(
policy=RecoveryPolicy(
classify=classify,
format_error=my_formatter,
max_message_len=450,
include_traceback=False,
logger=my_logger,
),
max_recoveries=10,
per_tool_recoveries={'my_tool_name': 5},
)
])
Contributing
We welcome community contributions under Apache-2.0. Please create an issue to discuss an improvement, or submit a pull request. Clone the repository, then run:
make install # uv sync --extra dev
make all # lint, format, typecheck, and tests with 100% branch coverage
Please ensure that make all passes before committing. Coding standards, file layout, and testing patterns can be found in AGENTS.md.
License
Metadata
Release files for pydantic-ai-error-recovery 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydantic_ai_error_recovery-0.2.0.tar.gz | 60.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydantic_ai_error_recovery-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.1 kB
Release files / pydantic_ai_error_recovery-0.2.0.tar.gz
| Download URL | pydantic_ai_error_recovery-0.2.0.tar.gz |
|---|---|
| Size | 60.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ad5a5190d232dfe98e811787881cff3a0ce483e2547791e5d8d1290d6a6dd9cd
|
|
BLAKE2b-256 checksum How to use checksums |
b92fc9dc60418ddcd99f31027c553d931a48ff5e20927218193021b8052f6bbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / pydantic_ai_error_recovery-0.2.0-py3-none-any.whl
| Download URL | pydantic_ai_error_recovery-0.2.0-py3-none-any.whl |
|---|---|
| Size | 17.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc0d6be0b6fa2bf481181f05782ca75867bee85dcfd6b192dcbd7a056bbfd58c
|
|
BLAKE2b-256 checksum How to use checksums |
82e86833342f1ef1aa4b0f64135803f5f4733ef6f93ea906b6d889d15ef85c0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log