An external request can fail even when an agent has chosen the right tool. Catching an exception at the tool boundary lets the tool return an error message instead of stopping the agent’s work. The caller must then handle either a successful result or a failure message. section 3.3.1
Listing 3.15 Web search function with error handling
def search_web(
query: str,
max_results: int = 5,
topic: str = "general",
time_range: str | None = None,
) -> list | str:
try:
response = tavily_client.search(
query,
max_results=max_results,
topic=topic,
time_range=time_range,
)
return response.get("results")
except Exception as e:
return f"Error: Search failed - {e}"
The search function wraps the Tavily request in try/except. It returns results on success and an error string on failure, making its return type list | str. section 3.3.1
A catchall is a useful starting point, but it discards distinctions that matter in production. An authentication error may need human attention; a rate limit may call for retry with backoff; a timeout may warrant retrying with a simpler query. Network and API errors may also need different responses. section 3.3.1
Evaluation code needs a similar boundary. When a problem–model run raises an exception, its evaluation function catches the failure and returns a result record rather than allowing that run to interrupt the batch. In a ReAct agent, graceful error handling supports the broader think–act–observe loop, where actions and their outcomes feed the next step. section 2.4.2 section 4.0
























