🔭

Agent Observability 是什么?

AI Agent 可观测性详解 - 给Agent装上监控探头

世界上有一种技术叫 Observability,它就像给Agent装了一堆监控探头——每次调用工具、每次推理、每次出错,都被记录下来。

凌晨4点16分,我发现某个Agent的响应时间从2秒变成了20秒,一查日志才发现:它在循环调用同一个工具,因为没检测到上次已经成功。那一刻我感谢那些日志——没有它们,我可能还在瞎猜。

📚 定义

Agent Observability(Agent可观测性) 是指通过日志、追踪、指标三种数据,了解Agent内部运行状态的能力。

  • Logs(日志):记录事件、错误、调试信息
  • Traces(追踪):记录请求完整链路和耗时
  • Metrics(指标):量化性能数据(响应时间、成功率等)

🔬 核心维度

维度1: 推理可观测
├── LLM调用记录(模型、token消耗、成本)
├── Prompt和Response日志
└── 推理延迟和失败率

维度2: 工具调用可观测
├── 工具名称、参数、返回值
├── 执行时间、成功/失败
└── 错误堆栈和重试次数

维度3: 上下文可观测
├── 上下文大小(token数)
├── 历史消息数量
└── 摘要次数和压缩率

维度4: 业务指标
├── 任务完成率
├── 平均响应时间
├── 用户满意度
└── 成本(API调用费用)

🚀 OpenClaw 实战

# OpenClaw 可观测性配置
observability:
  # 日志配置
  logging:
    level: info  # debug | info | warn | error
    format: json  # json | text
    destination: /var/log/openclaw/agent.log
    rotation:
      max_size: 100mb
      max_files: 10
    
    # 敏感数据脱敏
    redact:
      - "api_key"
      - "password"
      - "token"
  
  # 追踪配置 (OpenTelemetry)
  tracing:
    enabled: true
    exporter: otlp  # console | otlp | jaeger
    endpoint: "http://localhost:4317"
    sample_rate: 1.0  # 采样率
    
    # 追踪内容
    record:
      - llm_calls       # LLM调用
      - tool_calls       # 工具调用
      - context_changes  # 上下文变化
      - errors           # 错误
  
  # 指标配置 (Prometheus)
  metrics:
    enabled: true
    endpoint: "/metrics"
    port: 9090
    
    # 自定义指标
    custom_metrics:
      - name: task_completion_rate
        type: gauge
        description: "任务完成率"
      - name: token_consumption
        type: counter
        description: "总token消耗"
      - name: tool_call_latency
        type: histogram
        description: "工具调用延迟"
  
  # 告警配置
  alerting:
    - condition: "error_rate > 0.1"
      action: "发送飞书通知"
    - condition: "latency_p95 > 5000"
      action: "记录警告日志"

💻 代码示例:简易可观测系统

// observability.js
export class AgentObservability {
  constructor() {
    this.logs = [];
    this.traces = new Map();
    this.metrics = {
      llmCalls: 0,
      toolCalls: 0,
      errors: 0,
      totalTokens: 0
    };
  }
  
  // 记录日志
  log(level, message, metadata = {}) {
    const entry = {
      timestamp: new Date().toISOString(),
      level,
      message,
      ...metadata
    };
    this.logs.push(entry);
    console[level](`[${entry.timestamp}] ${message}`, metadata);
  }
  
  // 开始追踪
  startTrace(name, metadata = {}) {
    const traceId = `trace_${Date.now()}_${Math.random().toString(36).slice(2)}`;
    this.traces.set(traceId, {
      name,
      startTime: Date.now(),
      spans: [],
      metadata
    });
    return traceId;
  }
  
  // 添加Span
  addSpan(traceId, spanName, duration, metadata = {}) {
    const trace = this.traces.get(traceId);
    if (!trace) return;
    trace.spans.push({
      name: spanName,
      duration,
      ...metadata
    });
  }
  
  // 结束追踪
  endTrace(traceId) {
    const trace = this.traces.get(traceId);
    if (!trace) return;
    trace.totalDuration = Date.now() - trace.startTime;
    this.log('info', `Trace ${trace.name} completed`, {
      traceId,
      duration: trace.totalDuration,
      spans: trace.spans.length
    });
  }
  
  // 记录指标
  recordMetric(name, value) {
    if (this.metrics[name] !== undefined) {
      if (typeof this.metrics[name] === 'number') {
        this.metrics[name] += value;
      }
    }
  }
  
  // 获取指标快照
  getMetrics() {
    return { ...this.metrics };
  }
  
  // 导出为OpenTelemetry格式
  exportTraces() {
    return Array.from(this.traces.values()).map(trace => ({
      traceId: trace.traceId,
      name: trace.name,
      startTime: trace.startTime,
      duration: trace.totalDuration,
      spans: trace.spans
    }));
  }
}

// 使用示例
const obs = new AgentObservability();

// 记录LLM调用
obs.log('info', 'LLM调用开始', { model: 'claude-opus-4' });
obs.recordMetric('llmCalls', 1);
obs.recordMetric('totalTokens', 1500);

// 追踪工具调用
const traceId = obs.startTrace('web_search');
const startTime = Date.now();
// ... 执行工具调用
obs.addSpan(traceId, 'tool_execution', Date.now() - startTime);
obs.endTrace(traceId);

🎯 最佳实践

✅ 推荐做法:
  • 日志分级:DEBUG用于调试,INFO用于常规,ERROR用于问题
  • 敏感数据脱敏:API密钥、密码不记录明文
  • 追踪采样:高流量时采样10-20%即可
  • 指标聚合:用Prometheus/Grafana做可视化
⚠️ 踩坑:
  • 日志爆炸:Agent每次循环都打印,一天能写几十GB
  • 上下文泄露:日志里记录了完整对话历史
  • 追踪开销:过多的追踪也会影响性能