Monitoring and Reliability › Putting It Together

Michael BrenndoerferAugust 20, 20252 min read
AI Agent HandbookAll chapters
Part 14 of 15Deployment and Operations - From Prototype to Production
Chapter 40Monitoring and Reliability › Putting It Together
Reading section 11 of 14 · Putting It Together · 2 minSection 11 of 14 · 2 min

Book contents

Section 11 of 14 · 2 min read

Monitoring and Reliability › Putting It TogetherOne section · Sections in this chapter11 / 14 ↓

Let's look at a more complete example that combines monitoring and reliability patterns:

In[2]:
Code
## Example (Claude Sonnet 4.5)
from flask import Flask, request, jsonify
import os
from anthropic import Anthropic
import logging
import time

app = Flask(__name__)
logger = logging.getLogger(__name__)

## Metrics tracking
metrics = {
    "requests": 0,
    "errors": 0,
    "response_times": []
}

def call_with_retry(func, max_attempts=3):
    """Retry failed operations"""
    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, retrying: {e}")
                time.sleep(1)
            else:
                raise

@app.route('/health', methods=['GET'])
def health():
    """Health check endpoint"""
    return jsonify({"status": "healthy", "timestamp": time.time()})

@app.route('/metrics', methods=['GET'])
def get_metrics():
    """Metrics endpoint"""
    avg_time = sum(metrics["response_times"]) / len(metrics["response_times"]) if metrics["response_times"] else 0
    return jsonify({
        "total_requests": metrics["requests"],
        "error_rate": metrics["errors"] / max(metrics["requests"], 1),
        "avg_response_time": avg_time
    })

@app.route('/chat', methods=['POST'])
def chat():
    start_time = time.time()
    metrics["requests"] += 1
    
    try:
        user_message = request.json.get('message')
        logger.info(f"Processing request: {user_message}")
        
        # Call agent with retry logic
        def make_agent_call():
            client = Anthropic()
            return client.messages.create(
                model="claude-sonnet-4-5",
                max_tokens=1024,
                messages=[{"role": "user", "content": user_message}],
                timeout=30.0  # 30 second timeout
            )
        
        response = call_with_retry(make_agent_call)
        
        # Track metrics
        response_time = time.time() - start_time
        metrics["response_times"].append(response_time)
        logger.info(f"Request completed in {response_time:.2f}s")
        
        return jsonify({"response": response.content[0].text})
        
    except Exception as e:
        metrics["errors"] += 1
        logger.error(f"Request failed: {e}")
        return jsonify({
            "error": "I encountered a problem processing your request. Please try again."
        }), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

This example includes:

  • Health check endpoint for monitoring
  • Metrics tracking for requests, errors, and response times
  • Retry logic for transient failures
  • Timeout on the API call
  • Comprehensive logging
  • Graceful error handling with user-friendly messages

It's not production-ready for a large-scale system (you'd want external metrics storage, more sophisticated error handling, etc.), but it demonstrates the core patterns that make an agent reliable and observable.