πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό Servicesℹ️ Aboutβœ‰οΈ ContactView Pricing Plansfrom $10

Deploying Agents to Production

AI AgentsAgent Deployment Production🟒 Free Lesson

Advertisement

Deploying Agents to Production

Agent Deployment StackFastAPIDockerRedisPrometheusLoad BalancerAuto ScalerProduction Infrastructure

What is Agent Deployment?

Agent deployment transforms development prototypes into production-ready services. It encompasses containerization, API serving, monitoring, scaling, security, and operational reliability. The goal is five-nines availability with automatic recovery.

The deployment stack typically includes: FastAPI for HTTP serving, Docker for containerization, Redis for caching and sessions, Prometheus/Grafana for monitoring, and Kubernetes or ECS for orchestration.

Production agents differ from prototypes in: error handling, rate limiting, authentication, logging, health checks, graceful degradation, and cost monitoring.

Project Overview

We will deploy an agent with:

  • FastAPI REST API with async support
  • Docker containerization
  • Redis caching and session management
  • Prometheus metrics and Grafana dashboards
  • Auto-scaling configuration
  • Health checks and circuit breakers
  • Structured logging

Expected outcome: A production deployment template for any agent.

Difficulty: Advanced (requires understanding of DevOps, containerization, and production operations)

Architecture

Production ArchitectureLoad BalancerNGINX/ALBFastAPIAsync workersAgent CoreBusiness logicRedis CachePostgreSQLPrometheusKubernetes Cluster

Tools & Setup

ToolVersionPurpose
Python3.11+Core language
FastAPI0.109+HTTP framework
uvicorn0.27+ASGI server
redis5.0+Caching
docker24.0+Containerization
prometheus-client0.19+Metrics

Step 1: Environment Setup

python -m venv venv
source venv/bin/activate
pip install fastapi uvicorn redis prometheus-client pydantic httpx

Step 2: Project Structure

Architecture Diagram
deploy-agent/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ main.py
β”‚   β”œβ”€β”€ agent.py
β”‚   β”œβ”€β”€ routes.py
β”‚   β”œβ”€β”€ middleware.py
β”‚   β”œβ”€β”€ config.py
β”‚   └── metrics.py
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ requirements.txt
└── k8s/
    └── deployment.yaml

Step 3: FastAPI Application

# app/main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import redis.asyncio as redis

app = FastAPI(title="Agent API", version="1.0.0")
redis_client = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global redis_client
    redis_client = redis.from_url("redis://localhost:6379", decode_responses=True)
    yield
    await redis_client.close()

app = FastAPI(title="Agent API", lifespan=lifespan)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/health")
async def health():
    return {"status": "healthy", "version": "1.0.0"}

@app.get("/ready")
async def ready():
    try:
        await redis_client.ping()
        return {"status": "ready"}
    except:
        raise HTTPException(status_code=503, detail="Not ready")

# app/routes.py
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from app.agent import ProductionAgent
from app.metrics import track_request

router = APIRouter()
agent = ProductionAgent()

class QueryRequest(BaseModel):
    query: str
    user_id: str = "anonymous"
    session_id: str = None

class QueryResponse(BaseModel):
    answer: str
    request_id: str
    latency_ms: float
    tokens_used: int

@router.post("/query", response_model=QueryResponse)
@track_request
async def query(request: QueryRequest):
    result = await agent.process(request.query, request.user_id)
    return QueryResponse(**result)

# app/config.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "Agent API"
    debug: bool = False
    redis_url: str = "redis://localhost:6379"
    openai_api_key: str
    max_concurrent_requests: int = 100
    request_timeout: int = 30

    class Config:
        env_file = ".env"

settings = Settings()

# app/metrics.py
from prometheus_client import Counter, Histogram
import time
from functools import wraps

REQUEST_COUNT = Counter("agent_requests_total", "Total requests", ["method", "endpoint", "status"])
REQUEST_LATENCY = Histogram("agent_request_latency_seconds", "Request latency", ["endpoint"])
TOKEN_USAGE = Counter("agent_tokens_used_total", "Total tokens used", ["model"])

def track_request(func):
    @wraps(func)
    async def wrapper(*args, **kwargs):
        start = time.time()
        try:
            result = await func(*args, **kwargs)
            REQUEST_COUNT.labels(method="POST", endpoint="/query", status="success").inc()
            return result
        except Exception as e:
            REQUEST_COUNT.labels(method="POST", endpoint="/query", status="error").inc()
            raise
        finally:
            latency = time.time() - start
            REQUEST_LATENCY.labels(endpoint="/query").observe(latency)
    return wrapper

Step 4: Production Agent with Caching

# app/agent.py
from openai import AsyncOpenAI
import hashlib
import json
from typing import Dict

class ProductionAgent:
    def __init__(self):
        self.client = AsyncOpenAI()
        self.model = "gpt-4-turbo-preview"

    async def process(self, query: str, user_id: str) -> Dict:
        cache_key = f"query:{hashlib.md5(query.encode()).hexdigest()}"
        cached = await self._get_cache(cache_key)
        if cached:
            return cached
        response = await self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": "You are a helpful assistant."},
                {"role": "user", "content": query},
            ],
            temperature=0.7,
            max_tokens=1000,
        )
        result = {
            "answer": response.choices[0].message.content,
            "request_id": f"req_{hashlib.md5(query.encode()).hexdigest()[:8]}",
            "latency_ms": 0,
            "tokens_used": response.usage.total_tokens,
        }
        await self._set_cache(cache_key, result, ttl=300)
        return result

    async def _get_cache(self, key: str):
        try:
            from app.main import redis_client
            data = await redis_client.get(key)
            return json.loads(data) if data else None
        except:
            return None

    async def _set_cache(self, key: str, value: Dict, ttl: int = 300):
        try:
            from app.main import redis_client
            await redis_client.setex(key, ttl, json.dumps(value))
        except:
            pass

Step 5: Docker and Kubernetes

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
# docker-compose.yml
version: '3.8'
services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - REDIS_URL=redis://redis:6379
      - OPENAI_API_KEY=${OPENAI_API_KEY}
    depends_on:
      - redis
    deploy:
      replicas: 3

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agent-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: agent-api
  template:
    metadata:
      labels:
        app: agent-api
    spec:
      containers:
      - name: agent-api
        image: agent-api:latest
        ports:
        - containerPort: 8000
        env:
        - name: REDIS_URL
          value: "redis://redis-service:6379"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
  name: agent-api-service
spec:
  selector:
    app: agent-api
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: agent-api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: agent-api
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

Mathematical Foundation

Capacity Planning:

Intuition: Number of pods needed to handle expected load at target utilization.

Auto-scaling Threshold:

Intuition: Scale up when CPU exceeds 120% of target to handle increasing load.

Testing & Evaluation

import pytest
from httpx import AsyncClient
from app.main import app

@pytest.mark.asyncio
async def test_health():
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.get("/health")
        assert response.status_code == 200

@pytest.mark.asyncio
async def test_query():
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.post("/query", json={"query": "test"})
        assert response.status_code == 200

Performance Metrics

MetricValueNotes
Request Latency200ms-2sDepends on LLM
Throughput100+ RPSPer pod
Cache Hit Rate30-60%Depends on query patterns
Memory Usage256-512MBPer pod
Startup Time5-10sCold start

Real-World Use Cases

  • SaaS Products: Multi-tenant agent services
  • Internal Tools: Company-wide agent deployment
  • API Services: Agent-as-a-service offerings
  • Edge Deployment: Low-latency regional deployment
  • Hybrid Cloud: On-premise + cloud deployment

Common Pitfalls & Solutions

PitfallSolution
Cold start latencyPre-warm containers, use provisioned concurrency
Memory leaksMonitor memory, implement restart policies
Rate limitingImplement per-user quotas
Cost overrunsSet spending limits, monitor usage
Single point of failureMulti-AZ deployment, redundancy

Summary with Key Takeaways

  • FastAPI provides high-performance async HTTP serving
  • Docker ensures consistent environments across development and production
  • Redis caching reduces LLM costs and improves latency
  • Kubernetes auto-scaling handles traffic spikes
  • Comprehensive monitoring enables proactive issue detection

Need Expert AI Agents Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement