langchain-tool-recover
A tiny LangChain middleware that stops agents from looping, failing silently, or retrying tools stupidly.
langchain-tool-recover is not another retry library. LangChain already has ToolRetryMiddleware, ToolCallLimitMiddleware, and create_agent middleware. This package fills the smaller wedge around tool-call recovery UX: duplicate-call loop detection, structured failure messages, empty-result recovery, and sane LangChain tool defaults.
Install
pip install langchain-tool-recover
For local development:
pip install -e ".[dev]"
Use With create_agent
from langchain.agents import create_agent
from langchain_tool_recover import ToolRecoverMiddleware
agent = create_agent(
model=model,
tools=tools,
middleware=[
ToolRecoverMiddleware(),
],
)
When a tool fails or returns an empty result, the agent receives compact JSON it can reason over:
{"status":"needs_replan","tool":"search_docs","failure_class":"empty_result","message":"The tool returned no results.","suggestion":"Try broadening the query or removing exact-match terms.","action":"return_to_agent","attempt":1}
Use As A Tool Wrapper
from langchain_tool_recover import recover_tool
safe_search = recover_tool(search_tool)
The wrapper preserves the tool name, description, argument schema, and async support where LangChain exposes it.
Before And After
Without this library:
Agent calls search_docs("foo")
No results.
Agent calls search_docs("foo")
No results.
Agent calls search_docs("foo")
No results.
With this library:
Agent calls search_docs("foo")
No results.
[tool-recover] search_docs attempt=1 status=empty_result
[tool-recover] suggestion=Try broadening the query or removing exact-match terms.
[tool-recover] action=returned_recovery_message
Suggestion sent to agent: broaden the query or try another tool.
Duplicate calls are tracked per run. The first duplicate logs a warning and executes. The second duplicate returns a needs_replan message. The third and later duplicates are blocked for that run.
Default Policy
| Failure class | Default action |
|---|---|
timeout |
retry_with_backoff |
rate_limit |
retry_with_backoff |
validation_error |
return_to_agent |
auth_error |
fail_fast |
empty_result |
return_to_agent |
duplicate_call |
block after duplicate limit |
unsafe_command |
block |
unknown_error |
fail_fast |
Override policies by passing a mapping:
from langchain_tool_recover import FailureClass, RecoveryAction, ToolRecoverMiddleware
middleware = ToolRecoverMiddleware(
policies={
FailureClass.UNKNOWN_ERROR: RecoveryAction.RETURN_TO_AGENT,
}
)
What It Classifies
The classifier is deterministic and conservative:
- Exceptions: timeout, rate limit, validation error, auth error, unsafe command, unknown error.
- Empty results:
None, blank strings, empty collections, and explicit empty sentinels such as{"empty": true}or{"results": []}. - LangChain
ToolMessage(status="error")content is reclassified when the tool node converts invocation errors into messages.
It intentionally does not try to infer complex semantic failure from arbitrary prose in v1.
Examples
examples/basic_agent.pyexamples/duplicate_tool_loop.pyexamples/empty_search_recovery.py
Development
pip install -e ".[dev]"
pytest
python -m build
ruff check .
License
MIT
Release files for langchain-tool-recover 0.1.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 | |
|---|---|---|---|
| langchain_tool_recover-0.1.0.tar.gz | 14.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langchain_tool_recover-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.2 kB
Release files / langchain_tool_recover-0.1.0.tar.gz
| Download URL | langchain_tool_recover-0.1.0.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c98789473a8b2c65a08766d093bdda37dacaa8612d92a7b749bc3cf6c9323de0
|
|
BLAKE2b-256 checksum How to use checksums |
28f053289d5db0a367b58d3af960384c55654105eb4bf2cf9ae67c3e03a98aef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 25, 2026.
Transparency logRelease files / langchain_tool_recover-0.1.0-py3-none-any.whl
| Download URL | langchain_tool_recover-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1809bf80bcd9ceb9964a6f42ecbfd3cded93f655a38f73f97719b789f0c9a9d3
|
|
BLAKE2b-256 checksum How to use checksums |
8d7a664afcf5bd229e4a151843348e2277e42e92b840b4dde28457e59d10fcef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 25, 2026.
Transparency log