Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

AI Agent 可观测性 2026:从 Tracing 到生产调试的完整技术栈

一、问题的起点:为什么传统可观测性不够用?

2026 年,AI Agent 已从原型实验走向生产基础设施。自主编程 Agent 连续运行数小时,多轮客服 Agent 跨越数天会话,自动化运维 Agent 直接操作数据库和 API。

但一个残酷的数字是:Gartner 报告显示,截至 2026 年初,仅 15% 的 GenAI 部署拥有可观测性能力。85% 的生产 Agent 在"盲飞"。

传统服务的可观测性方案在这里全面失效:

问题维度传统微服务AI Agent
状态性无状态,每次请求独立有状态,跨轮次累积上下文
可复现性相同输入 → 相同输出概率性,相同输入可能走不同路径
成本模型固定成本/请求弹性成本,路径依赖
Trace 时长毫秒~秒级可达数小时
归因能力知道"做了什么"难以知道"为什么这么做"

Agent 的 bug 可能在第 3 轮埋下,第 18 轮才暴露,且几乎无法复现。审计日志(audit trail)是主要调试手段,而非复现

二、核心标准:OpenTelemetry GenAI 规范

2.1 规范现状

OpenTelemetry GenAI 语义约定当前处于 Development 状态,但已足够用于生产:

当前版本:v1.41(2026 Q2)
MCP 支持:v1.39 起新增 gen_ai.mcp.* 属性
稳定状态:⚠️ Development(属性名可能变更)

必须导出的两个核心指标:

指标含义
gen_ai.client.operation.duration每个操作延迟(秒)
gen_ai.client.token.usageToken 消耗(区分 input/output)

2.2 属性稳定性策略

几乎所有 gen_ai.* 属性均为 Development 状态。推荐双发射兼容模式:

bash
# 同时导出稳定版和实验版属性,避免升级时仪表板断裂
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

2.3 Span 类型与层级

OTel 定义了四种核心 Span 操作:

invoke_workflow (INTERNAL)          ← 顶层编排
  ├── invoke_agent (INTERNAL)       ← Agent A
  │     ├── chat/inference (CLIENT) ← 模型调用
  │     │     ├── model: claude-sonnet-4-20250514
  │     │     ├── input_tokens: 4521
  │     │     └── output_tokens: 893
  │     └── execute_tool (INTERNAL) ← 工具调用
  │           ├── tool_name: read_file
  │           ├── tool_args: {"path": "src/auth.go"}
  │           └── [MCP 属性丰富]
  └── invoke_agent (INTERNAL)       ← Agent B
        └── ...

三、工具选型:2026 年 7 大平台横评

3.1 自托管方案(数据主权优先)

Langfuse(推荐首选)

Langfuse 是 2026 年最活跃的开源 LLM 可观测性平台,2026 年 1 月被 ClickHouse 收购后持续高速迭代。

bash
# Docker Compose 快速部署
git clone https://github.com/langfuse/langfuse.git
cd langfuse
docker compose up -d

核心优势:

  • MIT 许可(企业 ee 目录除外),自托管完全免费
  • 原生 OTel 支持,支持 Docker Compose / K8s / Helm 部署
  • 提供 Python/JS SDK,OpenAI/AWS Bedrock 自动仪表化
  • 内置 Prompt 管理、评估、数据集功能

Arize Phoenix

bash
pip install arize-phoenix
python -m phoenix.server.main serve
  • Elastic License 2.0,GitHub ~9.9k stars
  • 基于 OpenInference,OTLP 原生协议
  • 提供 embedding 可视化、检索评估等专项能力

3.2 托管 SaaS 方案(快速上手)

平台免费额度付费起价核心卖点
LangSmith5K traces/月$39/座位/月内置 NL trace 分析助手,SmithDB 查询速度 ~12x
Braintrust1M spans/月$249/月2026.02 完成 $80M B 轮,内置自动化评分器
Helicone10K 请求/月按用量代理网关模式,零代码改动,Vercel AI SDK 原生集成

3.3 企业 APM 扩展

Datadog LLM Observability 的核心特点:

  • 从 v1.37 起原生支持 OTel GenAI 规范
  • 仅对 LLM Span 计费——工具调用 Span 和检索 Span 不计费
  • 免费额度:40K LLM spans/月,付费 $160/月起

对工具调用密集型 Agent(如编程 Agent 单轮可能调用 10+ 工具),Datadog 可能比按 Span 计费的平台便宜得多。

3.4 选型决策树

数据主权/合规要求?
  └─ 是 → 自托管 Langfuse

已有 Datadog APM?
  └─ 是 → 扩展 LLM Observability

快速上手 + 内置评估?
  └─ 是 → LangSmith 或 Braintrust

零代码改动追踪成本?
  └─ 是 → Helicone(注意单点故障风险)

四、框架集成实战

4.1 LangGraph(v0.2+)

LangGraph 的 Checkpointer 同时作为调试快照存储,是调试功能最完整的框架之一。

python
from langchain.callbacks.tracers.langsmith import LangSmithTracer
from langchain.callbacks.tracers.opentelemetry import OpenTelemetryCallbackHandler

callbacks = CallbackManager([
    LangSmithTracer(project_name="prod-agent"),
    OpenTelemetryCallbackHandler(tracer=tracer),
])

result = await app.ainvoke(input, config={"callbacks": callbacks})

# 内置熔断:防止 Agent 无限循环
try:
    result = app.invoke(input, config={"recursion_limit": 25})
except GraphRecursionError:
    log.error("agent exceeded recursion limit", session_id=session_id)

4.2 AutoGen(v0.4+)

python
from autogen_ext.monitoring import OTelSubscriber

runtime.add_subscription(
    OTelSubscriber(tracer=tracer, session_id=session_id)
)

# v0.4.2+:MessageContext 内置 trace 传播
# 跨 Agent 通信自动携带 W3C TraceContext

⚠️ 注意:AutoGen Agent handler 内部的工具调用不自动生成 OTel span,需手动包装。使用消息队列(actor 模型)时,trace context 需要序列化进消息信封。

4.3 CrewAI(v0.80+)

bash
# 只需设置环境变量,自动集成 Langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-xxx
export LANGFUSE_SECRET_KEY=sk-lf-xxx
export LANGFUSE_HOST=https://cloud.langfuse.com

Crew → Agent → Task 的层级天然映射到 Trace 层级,无需额外代码。

4.4 Go Agent 仪表化

如果你的 Agent 是用 Go 写的,使用 OTel Go SDK 手动埋点:

go
import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/attribute"
    "go.opentelemetry.io/otel/trace"
)

func (a *Agent) ExecuteTurn(ctx context.Context, input string) (*TurnResult, error) {
    tracer := otel.Tracer("agent-executor")

    ctx, span := tracer.Start(ctx, "invoke_agent",
        trace.WithAttributes(
            attribute.String("gen_ai.agent.name", a.Name),
            attribute.String("gen_ai.system", "custom"),
        ),
    )
    defer span.End()

    // LLM 调用
    llmCtx, llmSpan := tracer.Start(ctx, "chat inference",
        trace.WithAttributes(
            attribute.String("gen_ai.request.model", "claude-sonnet-4-20250514"),
            attribute.Int("gen_ai.usage.input_tokens", usage.InputTokens),
            attribute.Int("gen_ai.usage.output_tokens", usage.OutputTokens),
        ),
    )
    defer llmSpan.End()

    // 工具调用
    for _, toolCall := range plan.ToolCalls {
        toolCtx, toolSpan := tracer.Start(ctx, "execute_tool",
            trace.WithAttributes(
                attribute.String("gen_ai.tool.name", toolCall.Name),
            ),
        )
        result, err := a.executeTool(toolCtx, toolCall)
        if err != nil {
            toolSpan.RecordError(err)
        }
        toolSpan.End()
    }

    return result, nil
}

五、Agent 特有的调试挑战

5.1 上下文漂移(Context Drift)

长会话中,第 1 轮的指令到第 30 轮可能被稀释或矛盾,Agent 表现为"遗忘"约束。

检测方案

python
import hashlib
import structlog

log = structlog.get_logger()

def snapshot_context_hash(messages: list[dict]) -> str:
    """计算上下文的 SHA-256 哈希"""
    content = json.dumps(messages, sort_keys=True)
    return hashlib.sha256(content.encode()).hexdigest()

# 每轮记录上下文快照
log.info(
    "turn_context_snapshot",
    session_id=session_id,
    turn=turn_number,
    context_hash=snapshot_context_hash(messages),
    active_constraints=extract_constraints(system_prompt),
    trace_id=current_span.get_span_context().trace_id,
)

5.2 工具调用级联失败

工具失败 → 重试 → 换工具 → 再失败 → LLM 困惑 → 重试风暴。

告警规则

python
# Prometheus 告警规则
groups:
  - name: agent_alerts
    rules:
      - alert: AgentToolFailureCascade
        expr: |
          rate(agent_tool_errors_total[5m]) > 0.2
        for: 5m
        annotations:
          summary: "Agent 工具错误率超过 20%"

      - alert: AgentRunawayCost
        expr: |
          agent_session_cost_usd > (avg_over_time(agent_session_cost_usd[1h]) * 5)
        annotations:
          summary: "单会话成本超过中位数 5x"

5.3 跨进程 Trace 上下文传播

多 Agent 系统中,必须显式传播 W3C TraceContext:

python
from opentelemetry import trace
from opentelemetry.propagate import inject, extract

# 调用子 Agent 时注入 trace 上下文
headers = {}
inject(headers)  # 自动添加 traceparent: 00-{trace_id}-{span_id}-01
response = requests.post("http://subagent:8080/run", headers=headers)

# 子 Agent 接收端提取上下文
context = extract(dict(request.headers))
with tracer.start_as_current_span("subagent_execution", context=context):
    # 此 span 自动成为父 Agent trace 的子节点
    ...

5.4 成本归因

go
type CostTracker struct {
    mu     sync.Mutex
    models map[string]ModelPricing
}

type ModelPricing struct {
    InputPricePer1K  float64 // $/1K tokens
    OutputPricePer1K float64
}

func (ct *CostTracker) Accumulate(model string, inputTokens, outputTokens int) float64 {
    ct.mu.Lock()
    defer ct.mu.Unlock()

    pricing := ct.models[model]
    cost := float64(inputTokens)/1000*pricing.InputPricePer1K +
        float64(outputTokens)/1000*pricing.OutputPricePer1K

    metrics.AgentCost.Add(cost,
        attribute.String("model", model),
        attribute.String("session_id", sessionID),
    )
    return cost
}

⚠️ 不要硬编码模型价格。2026 年 Q1 OpenAI/Anthropic 均多次调价,将价格存入配置并每日刷新。

六、最小可行可观测性栈

如果你现在就要为 Agent 接入可观测性,按以下优先级逐步实施:

P1: Langfuse(自托管或云端)     → 30 分钟集成,trace 捕获 + 调试 UI
P2: structlog 结构化日志          → 每行携带 trace_id
P3: Prometheus gauge              → 每会话成本
P4: Prometheus histogram          → 会话时长分布
P5: 告警规则                      → 成本 > 5x 中位数 & 时长 > 2x P95

扩展选项

  • 使用 LangChain/LangGraph → 加 LangSmith
  • 需要质量评估 → 加 Arize Phoenix
  • 多服务跨进程 → 接入完整 OTel pipeline
  • 成本追踪(零代码) → 加 Helicone 代理网关

七、审计日志:合规底线

对于执行外部操作(提交代码、发邮件、修改数据库)的 Agent,不可变审计日志是合规要求:

go
type AuditEntry struct {
    Timestamp     time.Time `json:"timestamp"`
    SessionID     string    `json:"session_id"`
    TraceID       string    `json:"trace_id"`
    UserID        string    `json:"user_id"`
    ToolName      string    `json:"tool_name"`
    ToolArgs      string    `json:"tool_args"`      // 已脱敏
    ResultSummary string    `json:"result_summary"`
    AgentVersion  string    `json:"agent_version"`
}

func (a *AuditLogger) LogToolCall(entry AuditEntry) error {
    data, _ := json.Marshal(entry)
    // 追加写入,不可修改
    _, err := a.writer.Write(append(data, '\n'))
    return err
}

关键属性:不可变(追加写入)、完整性、可查询(按 session_id/user_id/tool_name 索引)、长期保留(企业合规 ≥ 90 天)

八、仍未解决的核心问题

坦白说,AI Agent 可观测性仍处于早期阶段。以下是 2026 年的未解难题:

  1. 语义正确性规模化评估:可以记录 Agent 调用了 git_commit,但无法自动判断提交内容是否正确。人工评估不可替代。
  2. 跨模型 Trace 关联:同一会话使用多个 LLM provider(Claude 规划 + GPT-4o 写代码 + Gemini 摘要),跨 provider trace 关联仍是临时方案。
  3. 长上下文调试工具:80,000 token 的 trace 在技术上完整但实际上无法阅读,缺乏有效的导航和摘要工具。
  4. 推理错误根因归因:Agent 产生错误计划,trace 记录每一步,但哪条上下文、哪条指令、哪个工具结果是因果责任方——这是神经网络因果归因的研究问题。

九、总结

2026 年的 AI Agent 可观测性已经从概念验证走向工程落地。核心原则只有一条:始终针对 OTel GenAI 规范编写仪表化代码,而非厂商私有 SDK

这样做的好处是:Langfuse 今天好用,明天想换 Braintrust?只需重新指向 Exporter,无需重写任何仪表化代码。

关键数字:85% 的 GenAI 部署仍在"盲飞"——现在接入追踪的团队,当 Agent 出问题时,能在几分钟内从 trace 中找到根因,而竞争对手只能靠猜测。

参考资料

上次更新于: