WebSearch but your tool is registered as web_search, PraisonAI fixes the name automatically — and when it can’t, it tells the model exactly which tools exist and how to call them.
Quick Start
1
Case and separator drift auto-fixes
web_search. No configuration required.2
Unknown names return a corrective message
3
Bind failures echo the parameters
4
Value errors pass through unchanged
No new API and no new
Agent(...) parameter. Self-repair is a runtime behavior of the existing tool-dispatch path, triggered whenever an LLM tool call arrives.How It Works
Every tool call runs throughAgent.execute_tool; a dispatch miss triggers normalisation, repair, or a corrective error before the result returns to the model.
Normalisation compares str(name).lower().replace('_', '').replace('-', '').replace(' ', ''). Repair fires only when exactly one active tool normalises to the same key — ambiguous matches skip repair and fall through to the corrective error, so there is never an ambiguous dispatch.
Four failure modes, four responses
- Case / separator drift
- Unknown name
- Bind failure
- Runtime error inside the tool
Silent auto-fix. The tool runs and returns its normal result. A debug log records the repair:
Why the hints reach the model
ToolExecutionError preserves only its message through conversion, so the corrective payload is folded into the message string itself.
Corrective inventory in the message
Corrective inventory in the message
The
Did you mean '<nearest>'? hint and the Available tools: [...] list live inside the error string, so the follow-up model turn sees them via the raised ToolExecutionError.message.Parameter hint in the message
Parameter hint in the message
The bind-failure branch appends
Expected parameters for '<tool>' — required: [...], optional: [...]. to the message string. The same names are also returned as a structured expected_parameters dict on the impl-level result.Only true bind failures get the hint
Only true bind failures get the hint
A
TypeError or ValueError raised inside a successfully-bound tool is a value problem, not a parameter problem. The runtime gates the schema hint on inspect.signature(target).bind(**kwargs) — the required/optional names only appear in the error message when the kwargs actually failed to bind. Otherwise the tool’s own error string reaches the model unchanged, so the model fixes the value instead of renaming the parameters.Backward compatible
Backward compatible
No new public API, no new
Agent parameters, and no new environment variables. The prior behavior on unknown tools was a bare Tool 'X' is not callable — not a stable contract, so no valid callers depended on it. When signature introspection itself is impossible (e.g. a C-implemented callable), the gate fails closed — it omits the hint rather than echo a misleading one.MCP tools participate too
MCP-container tools are expanded into their contained tools, so their names appear in the corrective inventory and can be name-repaired — not just the opaqueMCP container.
Available tools: list contains the MCP-provided tool names instead of the container. Only MCP instances that iterate into per-tool callables exposing __name__ or name benefit — the standard praisonaiagents.mcp.MCP satisfies this.
Init-time vs runtime
Two resolvers cover two different moments.
Self-repair complements — it does not replace — init-time Tool Resolution.
Related
Tool Resolution
Init-time typo detection when you pass tool names to
Agent(tools=[...])Error Handling
Catch and act on
ToolExecutionError and other structured errorsMCP
Connect model-context-protocol servers as tools
Allowed Tools
Restrict which tools an agent can call

