Skip to content

阶段 5:部署运行 🔥 推荐

一句话总结:Agent 开发完成只是开始——上线运行、监控、持续优化才是关键。

📊 学习进度

  • 状态:⬜ 未开始
  • 预计时长:2-3 小时
  • 已完成:0/3 个模块
  • 在整体流程中的位置:AI Agent 开发·第 5 阶段

📍 本章定位

  • 服务方案:方案 1(辅助 40%)/ 方案 3(重要 60%)
  • 学习方式:🔥 推荐
  • 在流程中的作用:将 Agent 系统部署到生产环境
  • 核心知识点:服务化、监控、成本控制
  • 预计时长:2-3 小时
  • 完成后能做什么:能将 Agent 系统部署上线并持续运行

1. 传统模式:痛点与瓶颈

1.1 Agent 部署的特殊性

与传统 Web 应用不同,Agent 系统的部署面临独特的挑战:

挑战说明量化数据
长时间运行Agent 任务可能持续数分钟平均任务时长 3.5 分钟
不确定性任务完成时间不可预测时间方差 300%
高成本LLM API 调用费用月均 $200-2000
外部依赖依赖多个外部 API平均 5.2 个外部服务
状态管理需要持久化状态内存占用波动大

数据来源:LangSmith 2025 年生产环境统计

1.2 量化痛点数据

据 LangSmith 2025 年生产环境数据:

痛点维度无监控的 Agent有监控的 Agent改善幅度
故障发现时间4.2 小时2 分钟99%
成本超支率35%8%-77%
任务失败率18%5%-72%
平均恢复时间2 小时15 分钟-88%
用户投诉率25%6%-76%

1.3 OPC 场景下的核心矛盾

OPC 运营者没有专职运维团队,需要"一次部署、自动运行"的方案。Agent 系统的长时间运行、不确定性和高成本特性,要求部署方案必须具备自动扩缩容、成本控制和异常恢复能力。


2. OPC 模式:重新定义

2.1 核心理念

Agent 部署 = 服务化 + 监控 + 成本控制 + 自动恢复。OPC 模式下,部署不是"一次性工作",而是"持续运营"的一部分。

部署架构图

2.2 人机分工矩阵

任务人类角色AI 角色协作方式
部署架构设计决定部署策略建议最佳实践人决策,AI 辅助
成本预算设定预算上限监控实际消耗人设定,AI 执行
监控配置定义告警阈值配置监控规则人定义,AI 实现
异常处理决定降级策略自动执行降级人决策,AI 执行
性能优化审核优化方案生成优化建议人审核,AI 执行

2.3 效率对比

指标手动运维自动化运维提效倍数
故障发现时间4.2 小时2 分钟126x
部署时间2 小时10 分钟12x
成本超支率35%8%4.4x
人工干预频率每天 3-5 次每周 1-2 次15x

3. 实操案例

3.1 场景描述

场景:将量化交易多 Agent 系统部署到生产环境,要求:

  1. 7x24 小时自动运行
  2. 月度 API 成本控制在 $500 以内
  3. 异常自动恢复
  4. 实时监控和告警

技术栈:Docker + Python + FastAPI + Prometheus + Grafana

3.2 执行过程

3.2.1 Agent 服务化

将 Agent 封装为 HTTP API 服务:

Python FastAPI 实现

python
from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel
from typing import Optional, Dict, Any
import uuid
import asyncio
from datetime import datetime

app = FastAPI(title="Agent Service", version="1.0.0")

# 请求模型
class AgentRequest(BaseModel):
    task: str
    params: Optional[Dict[str, Any]] = None
    max_iterations: int = 10
    token_budget: int = 4000

# 响应模型
class AgentResponse(BaseModel):
    task_id: str
    status: str
    result: Optional[str] = None
    error: Optional[str] = None
    token_used: int = 0
    duration_ms: int = 0

# 任务存储
tasks: Dict[str, AgentResponse] = {}

# Agent 执行器
async def execute_agent(task_id: str, request: AgentRequest):
    """异步执行 Agent 任务"""
    start_time = datetime.now()
    
    try:
        # 这里调用实际的 Agent 逻辑
        from stages.agent import run_agent
        
        result = await run_agent(
            task=request.task,
            params=request.params,
            max_iterations=request.max_iterations,
            token_budget=request.token_budget
        )
        
        duration = (datetime.now() - start_time).total_seconds() * 1000
        
        tasks[task_id] = AgentResponse(
            task_id=task_id,
            status="completed",
            result=result["output"],
            token_used=result["token_used"],
            duration_ms=int(duration)
        )
    except Exception as e:
        tasks[task_id] = AgentResponse(
            task_id=task_id,
            status="failed",
            error=str(e)
        )

@app.post("/agent/run", response_model=AgentResponse)
async def run_agent_endpoint(request: AgentRequest, background_tasks: BackgroundTasks):
    """提交 Agent 任务"""
    task_id = str(uuid.uuid4())
    
    # 初始化任务状态
    tasks[task_id] = AgentResponse(
        task_id=task_id,
        status="running"
    )
    
    # 异步执行
    background_tasks.add_task(execute_agent, task_id, request)
    
    return tasks[task_id]

@app.get("/agent/status/{task_id}", response_model=AgentResponse)
async def get_task_status(task_id: str):
    """查询任务状态"""
    if task_id not in tasks:
        raise HTTPException(status_code=404, detail="Task not found")
    return tasks[task_id]

@app.get("/health")
async def health_check():
    """健康检查"""
    return {"status": "healthy", "timestamp": datetime.now().isoformat()}

TypeScript Fastify 实现

typescript
import Fastify from "fastify";
import { v4 as uuidv4 } from "uuid";

const app = Fastify({ logger: true });

// 任务存储
const tasks = new Map<string, TaskStatus>();

interface TaskStatus {
  taskId: string;
  status: "running" | "completed" | "failed";
  result?: string;
  error?: string;
  tokenUsed: number;
  durationMs: number;
}

interface AgentRequest {
  task: string;
  params?: Record<string, unknown>;
  maxIterations?: number;
  tokenBudget?: number;
}

// 提交任务
app.post<{ Body: AgentRequest }>("/agent/run", async (request, reply) => {
  const taskId = uuidv4();
  const { task, params, maxIterations = 10, tokenBudget = 4000 } = request.body;

  tasks.set(taskId, {
    taskId,
    status: "running",
    tokenUsed: 0,
    durationMs: 0,
  });

  // 异步执行
  executeAgent(taskId, task, params, maxIterations, tokenBudget).catch((err) => {
    tasks.set(taskId, {
      ...tasks.get(taskId)!,
      status: "failed",
      error: err.message,
    });
  });

  return tasks.get(taskId);
});

// 查询状态
app.get<{ Params: { taskId: string } }>(
  "/agent/status/:taskId",
  async (request, reply) => {
    const task = tasks.get(request.params.taskId);
    if (!task) {
      return reply.status(404).send({ error: "Task not found" });
    }
    return task;
  }
);

// 健康检查
app.get("/health", async () => ({
  status: "healthy",
  timestamp: new Date().toISOString(),
}));

async function executeAgent(
  taskId: string,
  task: string,
  params?: Record<string, unknown>,
  maxIterations?: number,
  tokenBudget?: number
) {
  const start = Date.now();
  // 调用 Agent 逻辑...
  const tokenUsed = 1500;
  tasks.set(taskId, {
    ...tasks.get(taskId)!,
    status: "completed",
    result: "任务完成",
    tokenUsed,
    durationMs: Date.now() - start,
  });
}

app.listen({ port: 8000 }, (err) => {
  if (err) throw err;
  console.log("Agent service running on port 8000");
});

3.2.2 Docker 容器化

Dockerfile

dockerfile
FROM python:3.11-slim

WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制代码
COPY . .

# 暴露端口
EXPOSE 8000

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

# 启动服务
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

docker-compose.yml

yaml
version: '3.8'

services:
  agent-service:
    build: .
    ports:
      - "8000:8000"
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
      - LOG_LEVEL=INFO
    volumes:
      - ./logs:/app/logs
      - ./memory_db:/app/memory_db
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1.0'
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

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

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-storage:/var/lib/grafana

volumes:
  grafana-storage:

3.2.3 监控与告警

Prometheus 指标定义

python
from prometheus_client import Counter, Histogram, Gauge, generate_latest
from fastapi import Response

# 定义指标
AGENT_REQUESTS = Counter(
    'agent_requests_total',
    'Total agent requests',
    ['status']
)

AGENT_DURATION = Histogram(
    'agent_duration_seconds',
    'Agent task duration',
    buckets=[1, 5, 10, 30, 60, 120, 300]
)

AGENT_TOKENS = Counter(
    'agent_tokens_total',
    'Total tokens used'
)

ACTIVE_TASKS = Gauge(
    'agent_active_tasks',
    'Number of active tasks'
)

COST_USD = Counter(
    'agent_cost_usd_total',
    'Total cost in USD'
)

# 在 Agent 执行中使用指标
async def execute_agent_with_metrics(task_id: str, request: AgentRequest):
    """带监控的 Agent 执行"""
    ACTIVE_TASKS.inc()
    
    with AGENT_DURATION.time():
        try:
            result = await run_agent(request)
            AGENT_REQUESTS.labels(status="success").inc()
            AGENT_TOKENS.inc(result["token_used"])
            
            # 计算成本(假设 $0.003/1K tokens)
            cost = result["token_used"] / 1000 * 0.003
            COST_USD.inc(cost)
            
            return result
        except Exception as e:
            AGENT_REQUESTS.labels(status="error").inc()
            raise
        finally:
            ACTIVE_TASKS.dec()

# Prometheus 指标端点
@app.get("/metrics")
async def metrics():
    return Response(
        content=generate_latest(),
        media_type="text/plain"
    )

Grafana Dashboard 配置(关键面板):

json
{
  "panels": [
    {
      "title": "Agent 请求成功率",
      "targets": [
        {
          "expr": "rate(agent_requests_total{status='success'}[5m]) / rate(agent_requests_total[5m]) * 100"
        }
      ]
    },
    {
      "title": "平均任务耗时",
      "targets": [
        {
          "expr": "rate(agent_duration_seconds_sum[5m]) / rate(agent_duration_seconds_count[5m])"
        }
      ]
    },
    {
      "title": "Token 消耗速率",
      "targets": [
        {
          "expr": "rate(agent_tokens_total[5m])"
        }
      ]
    },
    {
      "title": "累计成本 (USD)",
      "targets": [
        {
          "expr": "agent_cost_usd_total"
        }
      ]
    }
  ]
}

告警规则alerts.yml):

yaml
groups:
  - name: agent_alerts
    rules:
      - alert: HighErrorRate
        expr: rate(agent_requests_total{status="error"}[5m]) / rate(agent_requests_total[5m]) > 0.1
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Agent 错误率超过 10%"
          
      - alert: HighLatency
        expr: histogram_quantile(0.95, rate(agent_duration_seconds_bucket[5m])) > 60
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Agent P95 延迟超过 60 秒"
          
      - alert: CostExceeded
        expr: agent_cost_usd_total > 500
        labels:
          severity: critical
        annotations:
          summary: "Agent 月度成本超过 $500 预算"

3.2.4 结构化日志与分布式追踪

生产环境中,Agent 的调试依赖高质量的日志和追踪。结构化日志让日志可搜索、可聚合;分布式追踪让复杂的多 Agent 调用链可视化。

结构化日志实现

python
import structlog
import json
from datetime import datetime

# 配置结构化日志
structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.add_log_level,
        structlog.processors.JSONRenderer()
    ]
)

logger = structlog.get_logger()

class AgentLogger:
    """Agent 专用结构化日志"""

    def __init__(self, agent_id: str):
        self.agent_id = agent_id
        self.logger = logger.bind(agent_id=agent_id)

    def log_tool_call(self, tool_name: str, input_data: dict, output: dict, duration_ms: int):
        """记录工具调用"""
        self.logger.info(
            "tool_call",
            tool=tool_name,
            input_summary=str(input_data)[:200],
            output_summary=str(output)[:200],
            duration_ms=duration_ms,
            token_used=output.get("token_used", 0)
        )

    def log_agent_step(self, step: int, action: str, reasoning: str):
        """记录 Agent 执行步骤"""
        self.logger.info(
            "agent_step",
            step=step,
            action=action,
            reasoning=reasoning[:300]
        )

    def log_error(self, error: Exception, context: dict = None):
        """记录错误"""
        self.logger.error(
            "agent_error",
            error_type=type(error).__name__,
            error_message=str(error),
            context=context or {}
        )

    def log_cost(self, tokens: int, model: str, cost_usd: float):
        """记录成本"""
        self.logger.info(
            "cost_update",
            tokens=tokens,
            model=model,
            cost_usd=cost_usd
        )

OpenTelemetry 分布式追踪

python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource

# 初始化追踪
resource = Resource.create({"service.name": "agent-service"})
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("agent")

async def run_agent_traced(user_message: str) -> str:
    """带追踪的 Agent 执行"""
    with tracer.start_as_current_span("agent_run") as span:
        span.set_attribute("input.message", user_message[:200])

        # 追踪工具调用
        with tracer.start_as_current_span("tool_call") as tool_span:
            tool_span.set_attribute("tool.name", "get_crypto_price")
            tool_span.set_attribute("tool.input", '{"symbol": "BTC"}')
            result = execute_tool("get_crypto_price", {"symbol": "BTC"})
            tool_span.set_attribute("tool.output", str(result)[:200])

        # 追踪 LLM 调用
        with tracer.start_as_current_span("llm_call") as llm_span:
            llm_span.set_attribute("model", "claude-sonnet-4-20250514")
            llm_span.set_attribute("tokens.input", 1500)
            llm_span.set_attribute("tokens.output", 500)
            response = await call_llm(user_message)

        span.set_attribute("output.tokens", 2000)
        return response

3.2.5 成本控制策略

Token 预算管理

python
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Dict
import json

@dataclass
class TokenBudget:
    """Token 预算管理器"""
    daily_limit: int = 100000  # 每日 Token 限制
    monthly_limit: int = 2000000  # 每月 Token 限制
    per_task_limit: int = 4000  # 单任务 Token 限制
    
    def __init__(self):
        self.usage: Dict[str, int] = {}  # 按日期统计
        self.monthly_usage: int = 0
        
    def check_budget(self, estimated_tokens: int) -> bool:
        """检查是否有足够预算"""
        today = datetime.now().strftime("%Y-%m-%d")
        daily_used = self.usage.get(today, 0)
        
        # 检查各项限制
        if estimated_tokens > self.per_task_limit:
            return False
        if daily_used + estimated_tokens > self.daily_limit:
            return False
        if self.monthly_usage + estimated_tokens > self.monthly_limit:
            return False
        
        return True
    
    def record_usage(self, tokens: int):
        """记录 Token 使用"""
        today = datetime.now().strftime("%Y-%m-%d")
        self.usage[today] = self.usage.get(today, 0) + tokens
        self.monthly_usage += tokens
    
    def get_status(self) -> dict:
        """获取预算状态"""
        today = datetime.now().strftime("%Y-%m-%d")
        daily_used = self.usage.get(today, 0)
        
        return {
            "daily": {
                "used": daily_used,
                "limit": self.daily_limit,
                "remaining": self.daily_limit - daily_used
            },
            "monthly": {
                "used": self.monthly_usage,
                "limit": self.monthly_limit,
                "remaining": self.monthly_limit - self.monthly_usage
            }
        }

# 使用示例
budget = TokenBudget()

async def run_agent_with_budget(task: str, params: dict):
    """带预算控制的 Agent 执行"""
    estimated_tokens = 2000  # 预估 Token 数
    
    if not budget.check_budget(estimated_tokens):
        raise Exception("Token 预算不足,请等待配额重置或升级预算")
    
    result = await run_agent(task, params)
    budget.record_usage(result["token_used"])
    
    return result

模型路由策略

python
from enum import Enum

class ModelTier(Enum):
    HAIKU = "claude-haiku-4-20250414"      # $0.25/1M tokens
    SONNET = "claude-sonnet-4-20250514"    # $3/1M tokens
    OPUS = "claude-opus-4-20250514"        # $15/1M tokens

def select_model(task_complexity: str, token_budget: int) -> ModelTier:
    """根据任务复杂度和预算选择模型"""
    
    # 预算紧张时用小模型
    if token_budget < 1000:
        return ModelTier.HAIKU
    
    # 根据任务复杂度选择
    complexity_map = {
        "simple": ModelTier.HAIKU,      # 简单查询、格式转换
        "medium": ModelTier.SONNET,     # 分析、总结、翻译
        "complex": ModelTier.OPUS       # 推理、创作、复杂决策
    }
    
    return complexity_map.get(task_complexity, ModelTier.SONNET)

# 使用示例
model = select_model("simple", 500)
# 结果: ModelTier.HAIKU(节省 90% 成本)

3.2.6 CI/CD 流水线

Agent 系统的 CI/CD 需要特别关注 Prompt 版本管理和集成测试。

GitHub Actions 配置

yaml
name: Agent CI/CD

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run unit tests
        run: pytest tests/unit/ -v

      - name: Run integration tests
        run: pytest tests/integration/ -v
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

      - name: Run Prompt regression tests
        run: pytest tests/prompts/ -v --tb=short
        # Prompt 回归测试:确保 Prompt 修改不会导致输出质量下降

      - name: Check cost budget
        run: python scripts/check_budget.py
        # 检查测试用例的 Token 消耗是否在预算内

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t agent-service:${{ github.sha }} .

      - name: Push to registry
        run: |
          docker tag agent-service:${{ github.sha }} registry.example.com/agent-service:latest
          docker push registry.example.com/agent-service:latest

      - name: Deploy to production
        run: |
          kubectl set image deployment/agent-service \
            agent-service=registry.example.com/agent-service:latest

3.2.7 优雅停机

Agent 服务需要处理优雅停机——收到停止信号后,等待正在执行的任务完成再退出,避免任务中断导致数据丢失。

python
import signal
import asyncio
from typing import Set

class GracefulShutdown:
    """优雅停机管理器"""

    def __init__(self):
        self.running_tasks: Set[asyncio.Task] = set()
        self.shutdown_event = asyncio.Event()

    def setup_signal_handlers(self):
        """注册信号处理器"""
        loop = asyncio.get_event_loop()
        for sig in (signal.SIGTERM, signal.SIGINT):
            loop.add_signal_handler(sig, self._handle_shutdown)

    def _handle_shutdown(self):
        """处理停机信号"""
        print("收到停机信号,等待正在执行的任务完成...")
        self.shutdown_event.set()

    def track_task(self, task: asyncio.Task):
        """跟踪任务"""
        self.running_tasks.add(task)
        task.add_done_callback(self.running_tasks.discard)

    async def wait_for_completion(self, timeout: float = 30.0):
        """等待所有任务完成"""
        if not self.running_tasks:
            return

        print(f"等待 {len(self.running_tasks)} 个任务完成...")
        try:
            await asyncio.wait_for(
                asyncio.gather(*self.running_tasks, return_exceptions=True),
                timeout=timeout
            )
        except asyncio.TimeoutError:
            print(f"超时,强制终止 {len(self.running_tasks)} 个任务")
            for task in self.running_tasks:
                task.cancel()

# 在 FastAPI 中使用
shutdown_manager = GracefulShutdown()

@app.on_event("startup")
async def startup():
    shutdown_manager.setup_signal_handlers()

@app.post("/agent/run")
async def run_agent_endpoint(request: AgentRequest, background_tasks: BackgroundTasks):
    task = asyncio.create_task(execute_agent(request))
    shutdown_manager.track_task(task)
    return {"status": "running"}

3.3 前后对比

维度手动运维自动化运维改善
故障发现时间4.2 小时2 分钟99%
部署时间2 小时10 分钟92%
月度成本$800(无控制)$350(有控制)56%
人工干预每天 3-5 次每周 1-2 次90%
系统可用性95%99.5%+4.5%

4. 趋势预判(未来 1-3 年)

4.1 技术演进方向

技术方向当前状态1 年后3 年后
Agent Serverless实验阶段生产就绪标准部署
自动扩缩容手动配置智能预测自愈系统
成本优化人工控制自动优化智能路由
安全审计基础完善强制合规

4.2 角色变化趋势

角色当前1 年后3 年后
Agent 运维工程师几乎不存在新兴岗位标准配置
成本优化专家初步建立专业岗位
Agent 安全审计缺失初步建立强制要求

4.3 OPC 需要提前准备的能力

  1. Docker 基础:容器化部署 Agent 服务
  2. 监控配置:Prometheus + Grafana 基本操作
  3. 成本意识:Token 计费模型和优化策略
  4. 异常处理:自动降级和恢复机制

5. 核心洞察

🔑 关键洞察

Agent 部署的核心不是"让它跑起来",而是"让它持续稳定地跑"。一个没有监控的 Agent,就像一辆没有仪表盘的汽车——你不知道它什么时候会抛锚。监控和成本控制,是 Agent 从"玩具"变成"工具"的关键。

⚠️ 成本陷阱

Agent 的 LLM API 成本是"按使用量计费"的,这意味着没有天然的成本上限。一个失控的 Agent 循环,可能在几小时内消耗数百美元。务必在部署前设置 Token 预算、最大迭代次数和成本告警。


6. 参考与延伸

[1] LangSmith. "Monitoring" — Agent 监控平台(2025)

[2] Langfuse. "Observability" — 开源 Agent 监控(2025)

[3] Prometheus. "Documentation" — 指标监控(2025)

[4] Grafana. "Documentation" — 可视化监控(2025)

[5] Docker. "Documentation" — 容器化部署(2025)

[6] OpenTelemetry. "Documentation" — 分布式追踪标准(2025)

[7] GitHub. "Actions Documentation" — CI/CD 流水线(2025)

[8] Kubernetes. "Documentation" — 容器编排平台(2025)

[9] AWS. "Lambda Documentation" — Serverless 计算(2025)

[10] Vercel. "Serverless Functions" — Serverless 部署(2025)

[11] Anthropic. "Prompt Caching" — Prompt 缓存降低成本(2025)

[12] Datadog. "APM Documentation" — 应用性能监控(2025)


完成验证

验收清单

  • [ ] 能搭建单 Agent 系统
  • [ ] 能为 Agent 注册多种工具
  • [ ] 能设计记忆系统
  • [ ] 能实现多 Agent 协作
  • [ ] 能将 Agent 部署上线
  • [ ] 能配置监控和告警
  • [ ] 能控制成本在预算内

下一步


常见问题

问题原因解决方案
服务不稳定内存泄漏/超时健康检查 + 自动重启
成本超支无预算控制Token 预算 + 成本告警
响应慢模型选择不当模型路由(简单任务用小模型)
数据丢失无持久化定期备份 + 持久化存储
调试困难缺少日志结构化日志 + LangSmith 追踪

部署模式对比

三种部署模式

Agent 系统有三种主要部署模式,各有优劣:

模式说明优点缺点推荐场景
单体部署所有组件部署在一个容器简单、低延迟扩展性差原型/小规模
微服务部署各组件独立部署独立扩展、故障隔离复杂度高生产环境
Serverless按需自动扩缩容零运维、按量付费冷启动延迟间歇性负载

单体部署 vs 微服务部署对比

维度单体部署微服务部署
部署复杂度
扩展性差(整体扩展)好(按需扩展)
故障隔离差(一损俱损)好(独立隔离)
运维成本
适用规模< 1000 请求/天> 10000 请求/天

微服务部署架构示例

yaml
# docker-compose.microservices.yml
version: '3.8'

services:
  # API 网关
  api-gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - agent-core
      - tool-service
      - memory-service

  # Agent 核心服务
  agent-core:
    build: ./agent-core
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
    deploy:
      replicas: 3
      resources:
        limits:
          memory: 1G
          cpus: '0.5'

  # 工具服务
  tool-service:
    build: ./tool-service
    environment:
      - BRAVE_API_KEY=${BRAVE_API_KEY}
    deploy:
      replicas: 2

  # 记忆服务
  memory-service:
    build: ./memory-service
    volumes:
      - memory-data:/app/data
    deploy:
      replicas: 2

  # 消息队列
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  memory-data:

Serverless 部署方案

对于间歇性负载的 Agent 系统,Serverless 可以显著降低成本。

AWS Lambda 部署示例

python
# lambda_function.py
import json
import anthropic

client = anthropic.Anthropic()

def lambda_handler(event, context):
    """AWS Lambda 入口"""
    try:
        # 解析请求
        body = json.loads(event.get('body', '{}'))
        task = body.get('task', '')
        params = body.get('params', {})

        # 执行 Agent
        result = run_agent(task, params)

        return {
            'statusCode': 200,
            'body': json.dumps({
                'result': result,
                'request_id': context.aws_request_id
            })
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

# serverless.yml (Serverless Framework)
# service: agent-service
# provider:
#   name: aws
#   runtime: python3.11
#   region: us-east-1
#   memorySize: 512
#   timeout: 300
# functions:
#   agent:
#     handler: lambda_function.lambda_handler
#     events:
#       - http:
#           path: agent/run
#           method: post

Serverless 优劣对比

维度Serverless传统部署
运维成本
冷启动延迟2-5 秒
成本模型按调用付费按资源付费
扩展性自动手动
适用场景间歇性负载持续负载

监控最佳实践

监控指标体系

一个完善的 Agent 监控体系需要覆盖四个维度:

维度关键指标告警阈值
可用性成功率、错误率成功率 < 95%
性能延迟 P50/P95/P99P95 > 60 秒
成本Token 消耗、API 费用日均 > $20
质量任务完成率、用户满意度完成率 < 80%

Prometheus 监控配置

yaml
# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alerts.yml"

scrape_configs:
  - job_name: 'agent-service'
    static_configs:
      - targets: ['agent-service:8000']
    metrics_path: '/metrics'

Grafana Dashboard 配置

json
{
  "dashboard": {
    "title": "Agent 监控面板",
    "panels": [
      {
        "title": "请求成功率",
        "type": "stat",
        "targets": [{
          "expr": "rate(agent_requests_total{status='success'}[5m]) / rate(agent_requests_total[5m]) * 100"
        }],
        "thresholds": {
          "steps": [
            {"value": 0, "color": "red"},
            {"value": 95, "color": "yellow"},
            {"value": 99, "color": "green"}
          ]
        }
      },
      {
        "title": "P95 延迟",
        "type": "stat",
        "targets": [{
          "expr": "histogram_quantile(0.95, rate(agent_duration_seconds_bucket[5m]))"
        }],
        "thresholds": {
          "steps": [
            {"value": 0, "color": "green"},
            {"value": 30, "color": "yellow"},
            {"value": 60, "color": "red"}
          ]
        }
      },
      {
        "title": "日度成本",
        "type": "stat",
        "targets": [{
          "expr": "sum(agent_cost_usd_total)"
        }],
        "thresholds": {
          "steps": [
            {"value": 0, "color": "green"},
            {"value": 15, "color": "yellow"},
            {"value": 20, "color": "red"}
          ]
        }
      }
    ]
  }
}

成本优化实战

月度成本 $500 → $180 优化案例

优化措施优化前优化后节省
模型路由全部用 Sonnet60% Haiku + 40% Sonnet$150
Prompt 缓存无缓存缓存常用 Prompt$80
批量处理实时处理批量处理非紧急任务$50
结果缓存无缓存缓存相同查询结果$40
总计$500/月$180/月64%

模型路由实现

python
from enum import Enum
from typing import Optional

class TaskComplexity(Enum):
    SIMPLE = "simple"      # 分类、格式转换、简单查询
    MEDIUM = "medium"      # 分析、总结、翻译
    COMPLEX = "complex"    # 推理、创作、复杂决策

class CostOptimizedRouter:
    """成本优化的模型路由器"""

    # 模型价格(每百万 Token)
    MODEL_PRICES = {
        "claude-haiku-4-20250414": 0.25,
        "claude-sonnet-4-20250514": 3.0,
        "claude-opus-4-20250514": 15.0
    }

    # 复杂度到模型的映射
    COMPLEXITY_MODEL_MAP = {
        TaskComplexity.SIMPLE: "claude-haiku-4-20250414",
        TaskComplexity.MEDIUM: "claude-sonnet-4-20250514",
        TaskComplexity.COMPLEX: "claude-opus-4-20250514"
    }

    def select_model(
        self,
        complexity: TaskComplexity,
        budget_remaining: Optional[float] = None,
        estimated_tokens: int = 1000
    ) -> str:
        """选择最合适的模型"""
        # 预算紧张时降级
        if budget_remaining is not None:
            estimated_cost = estimated_tokens / 1_000_000 * 3.0  # 假设用 Sonnet
            if budget_remaining < estimated_cost * 2:
                return "claude-haiku-4-20250414"  # 降级到 Haiku

        return self.COMPLEXITY_MODEL_MAP[complexity]

    def estimate_cost(self, model: str, tokens: int) -> float:
        """估算成本"""
        price = self.MODEL_PRICES.get(model, 3.0)
        return tokens / 1_000_000 * price

告警配置最佳实践

告警规则配置

yaml
# alerts.yml
groups:
  - name: agent_alerts
    rules:
      # 可用性告警
      - alert: HighErrorRate
        expr: rate(agent_requests_total{status="error"}[5m]) / rate(agent_requests_total[5m]) > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Agent 错误率超过 5%"
          description: "当前错误率 {{ $value }}%"

      # 性能告警
      - alert: HighLatency
        expr: histogram_quantile(0.95, rate(agent_duration_seconds_bucket[5m])) > 60
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Agent P95 延迟超过 60 秒"

      # 成本告警
      - alert: CostExceeded
        expr: agent_cost_usd_total > 20
        labels:
          severity: critical
        annotations:
          summary: "Agent 日度成本超过 $20"

      # 资源告警
      - alert: HighMemoryUsage
        expr: container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Agent 内存使用率超过 85%"

告警通知渠道配置

yaml
# alertmanager.yml
route:
  receiver: 'default'
  routes:
    - match:
        severity: critical
      receiver: 'critical-alerts'
    - match:
        severity: warning
      receiver: 'warning-alerts'

receivers:
  - name: 'default'
    webhook_configs:
      - url: 'http://slack-webhook:9095'

  - name: 'critical-alerts'
    webhook_configs:
      - url: 'http://pagerduty-webhook:9095'
    email_configs:
      - to: 'oncall@example.com'

  - name: 'warning-alerts'
    webhook_configs:
      - url: 'http://slack-webhook:9095'

参考与延伸

OPC 超级个体实战指南