Monitoring and Reliability › Building Reliability Through Error Handling
AI Agent HandbookAll chapters Monitoring and Reliability › Building Reliability Through Error HandlingOne section · Sections in this chapter7 / 14 ↓
Monitoring tells you when problems occur. Reliability is about handling those problems gracefully so users still get a good experience.
The key to reliability is expecting things to go wrong. Network requests fail. APIs have outages. Databases get slow. Your agent needs to handle these situations without crashing or leaving users stranded.
Graceful Degradation
When a non-critical component fails, your agent should continue working with reduced functionality rather than failing completely. This is called graceful degradation.
For example, if your agent uses a weather API but that API is down, the agent should acknowledge the problem and offer what help it can:
def get_weather(location):
try:
weather_data = weather_api.fetch(location)
return f"The weather in {location} is {weather_data['condition']}, {weather_data['temperature']}°F"
except Exception as e:
logger.warning(f"Weather API unavailable: {e}")
return "I'm having trouble accessing weather information right now. Please try again later or check a weather website directly."The user doesn't get the weather, but they get a helpful explanation instead of a cryptic error. The agent degrades gracefully.
Retry Logic
Some failures are transient. A network request might fail once but succeed if you try again. For operations that might fail temporarily, adding retry logic can significantly improve reliability.
Here's a simple retry pattern:
import time
def call_with_retry(func, max_attempts=3, delay=1):
"""Call a function with automatic retries"""
for attempt in range(max_attempts):
try:
return func()
except Exception as e:
if attempt < max_attempts - 1:
logger.warning(
f"Attempt {attempt + 1} failed: {e}. Retrying in {delay}s..."
)
time.sleep(delay)
else:
logger.error(f"All {max_attempts} attempts failed: {e}")
raise
## Use it for API calls that might fail temporarily
def fetch_weather(location):
return call_with_retry(
lambda: weather_api.fetch(location)
)This function tries up to three times before giving up. If the first attempt fails due to a temporary network hiccup, the second attempt might succeed. This makes your agent more resilient to transient failures.
Be thoughtful about what you retry. Retrying makes sense for network errors or timeouts. It doesn't make sense for errors like "invalid API key" or "malformed request", which will fail the same way every time.
Timeouts
Sometimes an operation doesn't fail, it just hangs. A tool call might wait indefinitely for a response that never comes. Without a timeout, your agent gets stuck, unable to respond to the user or handle other requests.
Always set timeouts for external operations:
import requests
def call_external_api(url, data):
try:
# Set a 10-second timeout
response = requests.post(url, json=data, timeout=10)
return response.json()
except requests.Timeout:
logger.error(f"API call to {url} timed out")
return None
except Exception as e:
logger.error(f"API call failed: {e}")
return NoneWith a timeout, if the API doesn't respond within 10 seconds, your agent gives up and returns an error. This is better than hanging forever.
Fallback Responses
When all else fails, your agent should still respond to the user. Even if it can't complete the requested task, it can acknowledge the problem and suggest alternatives.
def process_agent_request(user_message):
try:
# Try to process normally
return agent.process(user_message)
except Exception as e:
logger.error(f"Agent processing failed: {e}")
# Return a fallback response
return (
"I encountered an unexpected problem and couldn't complete your request. "
"Please try again, or rephrase your question if the issue persists."
)This fallback ensures users never see a blank screen or a raw error message. They get a response that explains what happened and suggests what to do next.