Detecting and Recovering from Tool Errors
When a tool 500s, return the error to the model so it can try a different approach instead of crashing.
Detecting and Recovering from Tool Errors is a free AI Agents lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Agents learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Tools Fail. Plan For It.
Every real tool fails sometimes:
- Network timeouts
- Rate limits
- Bad arguments from the model
- External service downtime
- Invalid auth
Production agents must recover gracefully.
Always Return, Never Raise
Inside the agent loop, catch all tool errors and return them as content. Never let an exception kill the loop:
def safe_dispatch(tool_call):
try:
args = json.loads(tool_call.function.arguments)
return TOOLS[tool_call.function.name](**args)
except json.JSONDecodeError:
return {'error': 'Arguments are not valid JSON.'}
except KeyError:
return {'error': f'Unknown tool: {tool_call.function.name}'}
except Exception as e:
return {'error': f'{type(e).__name__}: {e}'}Structured Error Format
Use a consistent shape so the model recognises errors:
error = {'ok': False, 'error_type': 'TimeoutError', 'error_message': 'Tavily timed out after 10s', 'retryable': True}
print(error)
Distinguish Retryable from Permanent
Some errors warrant a retry (timeout); others do not (404). Tell the model:
if isinstance(e, requests.Timeout):
return {'ok': False, 'retryable': True, 'error': str(e)}
if isinstance(e, ValueError):
return {'ok': False, 'retryable': False, 'error': str(e)}Auto-Retry Transient Errors
For network calls, retry with exponential backoff:
from tenacity import retry, wait_exponential, stop_after_attempt, retry_if_exception_type
@retry(
wait=wait_exponential(multiplier=1, max=10),
stop=stop_after_attempt(3),
retry=retry_if_exception_type((requests.Timeout, requests.ConnectionError))
)
def web_search(query):
return requests.get('https://api.tavily.com/search', ...).json()Argument Validation
Before calling the tool, validate arguments with a Pydantic model:
from pydantic import BaseModel, ValidationError
class SearchArgs(BaseModel):
query: str
k: int = 5
try:
args = SearchArgs.model_validate_json(tool_call.function.arguments)
except ValidationError as e:
return {'error': f'Bad arguments: {e}'}Show the Model the Error
Append the error as a tool result and call the model again. The model often corrects itself:
messages.append({
'role': 'tool',
'tool_call_id': tc.id,
'content': json.dumps({'error': 'Argument k must be an integer'})
})
# Next model call: 'Sorry, let me retry with k=5...'Avoid Infinite Error Loops
Some models, when shown an error, retry the same broken call. Cap the loop and detect repeats:
recent_calls = []
for tc in msg.tool_calls:
key = (tc.function.name, tc.function.arguments)
if recent_calls.count(key) >= 3:
return 'Agent stuck in retry loop, aborting.'
recent_calls.append(key)Tool-Specific Recovery
For known-flaky tools, build retry logic INSIDE the tool, not the loop:
def search_with_fallback(query):
try:
return tavily_search(query)
except Exception:
return bing_search(query) # secondary providerTimeout Every Call
Every external call needs a timeout. Otherwise one slow service freezes your whole agent:
import requests
response = requests.get(url, timeout=10) # 10s
# For LLM calls:
from openai import OpenAI
client = OpenAI(timeout=30.0)Circuit Breakers
When a tool fails repeatedly, "open" the circuit and skip it for some time:
import time
class CircuitOpen(Exception):
pass
def circuit(failure_threshold=5, recovery_timeout=60):
def decorator(func):
state = {'failures': 0, 'open_until': 0}
def wrapper(*args, **kwargs):
if time.time() < state['open_until']:
raise CircuitOpen('circuit is open')
try:
result = func(*args, **kwargs)
state['failures'] = 0
return result
except Exception:
state['failures'] += 1
if state['failures'] >= failure_threshold:
state['open_until'] = time.time() + recovery_timeout
raise
return wrapper
return decorator
@circuit(failure_threshold=3, recovery_timeout=1)
def fragile_tool(x):
if x < 0:
raise ValueError('bad input')
return x * 2
for x in [1, -1, -1, -1, -1]:
try:
print('ok', fragile_tool(x))
except CircuitOpen as e:
print('blocked:', e)
except ValueError as e:
print('failed:', e)
Logging Errors With Context
Log enough to debug after the fact: tool name, arguments, error type, stack trace, request id, user id, trace id. Send to your observability tool.
Graceful Degradation
When a critical tool is down, tell the user honestly instead of pretending the agent succeeded:
if all_search_tools_failed:
return 'I was unable to search the web right now. Please try again in a few minutes.'Tool Errors Pattern
What is the safest way to handle tool exceptions inside the agent loop?
Recap
Tools fail. Catch, classify, structure-as-content, and let the agent recover. Add timeouts, retries, and circuit breakers for production reliability.
Frequently asked questions
Is the “Detecting and Recovering from Tool Errors” lesson free?
Yes — the full text of “Detecting and Recovering from Tool Errors” is free to read here on the web, and the AI Agents course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Agents course, upgrade to CoddyKit PRO.
What will I learn in “Detecting and Recovering from Tool Errors”?
When a tool 500s, return the error to the model so it can try a different approach instead of crashing. You practise AI Agents with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start AI Agents?
No prior experience is required. AI Agents on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Detecting and Recovering from Tool Errors” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this AI Agents lesson?
Yes. Every AI Agents lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- ReAct: Reason + Act Pattern
- Implementing ReAct from Scratch
- Common Tool Sets (Web, Calculator, RAG)
- Detecting and Recovering from Tool Errors