跳转到主要内容

你的智能体追踪在撒谎:LLM 智能体的基数、采样与 Span 层级结构

阅读需 3 分钟Tian PanTian Pan

你的链路追踪仪表盘显示 Agent 为了响应用户请求发起了 8 次调用。但实际上,它发起了 47 次。你的头部采样器(Head-based sampler)静默地丢弃了其中的大部分。你保留下来的那些调用在技术上是正确的,但在因果关系上毫无用处——它们是从被父级采样器丢弃的根节点中孤立出来的子 Span。

这并不是可视化层面的 Bug。它是将专为 10 个 Span 的 HTTP 扇出设计的分布式链路追踪基础设施,强行套用到每轮对话生成数百个 Span 的系统上的必然结果。默认的 OpenTelemetry 配置系统性地低估了 Agent 的工作量,而运行这些 Agent 的团队通常直到客户抱怨链路追踪视图中显示“不存在”的延迟时,才会察觉到问题。

Agent 的可观测性并不是微服务可观测性的加强版。它的数据形态不同、故障模式不同,成本曲线也完全不同。如果把它当作一个更复杂的 Web 后端来对待,结果就是你的链路追踪账单在一个季度内翻倍,而你的平均故障诊断时间(MTTD)不仅没有改善,反而变得更糟。

没人预警过你的基数计算难题

从单轮交互开始。传统的 REST 接口可能会扇出大约 10 个 Span:HTTP 处理程序、几个数据库查询、一个缓存读取、一个外部 API 调用。链路追踪工具就是围绕这种形态构建的。尾部采样处理器(Tail-sampling processor)的文档在示例中使用的是 10 个 Span 的链路。默认的存储配额也是基于此假设。Span 存储的定价也是据此校准的。

现在给一个 Agent 增加埋点。一个用于客户支持聊天机器人的合理 ReAct 循环,对于一条用户消息的处理可能如下:意图分类(1 次 LLM 调用)、工具选择(1 次 LLM 调用)、并行工具执行(3 个工具 Span)、工具结果验证(1 次 LLM 调用)、检索(1 次向量数据库查询,1 次重排序调用)、回答草稿(1 次 LLM 调用)、安全检查(1 次 LLM 调用)、后续查询的工具调用(1 次 LLM 调用加上 1 次 API 调用)、最终响应(1 次 LLM 调用)。这大约是 13 个操作。每个操作都会产生一个顶级 Span,再加上 HTTP、序列化和重试的子 Span。现实的计数是:每轮对话 30 到 60 个 Span。

将这个数字乘以一个 5 轮的对话。针对中型部署的公开估算描述了一个典型的轨迹:每天 50,000 条用户消息、200,000 次 LLM 调用、100 万个 Span、400 万个指标数据点、400 MB 日志。那些将 AI 工作负载直接套用到现有 Datadog、Honeycomb 或 New Relic 设置的团队,其可观测性账单增加了 40% 到 200% 不等,具体取决于存储时长和自定义指标。

10 到 50 倍的数量增长还不是最难的部分。难点在于每个 Span 的载荷(Payload)不同。在 OpenTelemetry 语义规范下,每个 gen_ai Span 都需要携带提示词(Prompts)、补全结果(Completions)、Token 计数、模型参数和工具参数。其中每一个属性都可能有数 KB 大小。而传统的 Span 只有几百字节。你不仅在为多出 10 到 50 倍的 Span 买单,你还在为更大的 Span 买单,而大多数链路追踪后端是按属性大小计费的。

为什么头部采样会静默损坏你的 Agent 追踪

头部采样(Head-based sampling)在根 Span 处就决定是否保留整条链路。它速度快、无状态,且成本可预测。它也是大多数 OTel SDK 的默认设置。对于传统服务来说,这没问题:丢失 90% 的健康链路是可以接受的,因为保留下来的 10% 具有代表性。

但对于 Agent 来说,头部采样是具有破坏性的。原因有二。

首先,单次 Agent 运行是一个依赖序列,而不是统计样本。你不想在一次运行中采样 10% 的 LLM 调用——你想要保留下来的那些运行中 100% 的调用,而丢弃掉的那些则一个都不留。任何部分的捕获都会产生一条对实际发生情况撒谎的链路。一个缺失了三个叶子节点的 Span 树不会告诉你 Agent 走了一段计划外的弯路;它只会向你展示一个从步骤 2 直接跳到步骤 7 且没有任何解释的 Agent。

其次,有趣的事件往往是罕见的。响应缓慢、幻觉导致的工具调用、推理循环、成本激增——这些才是你需要的链路,而它们恰恰是你在根 Span 处无法识别的。当采样器看到第一个 LLM 调用时,它无法预知这个 Agent 随后会再进行 45 次调用。应用在双峰延迟分布上的 1% 头部采样器会保留大量的快速链路,而几乎保留不到慢速链路,因为慢速链路始终是少数。

还有一个更隐蔽的失效模式:只有当你的埋点非常规范时,采样才会丢弃整个执行过程而非单个调用。在跨多个框架的 Agent 代码中——例如在 OpenAI SDK 之上运行 LangGraph,再在之上运行自定义工具路由器——上下文传播(Context propagation)经常会断裂。每个框架都会开启自己的链路,因为没有人传递父级上下文。你的采样器会将每个片段视为一个独立的根 Span 并做出独立决策。最终你可能在视图中看到一个保留下来的片段和四个被丢弃的片段,于是你看到的“链路”只是一个孤立的、断连的子树。

设计能在数据保留压力下存活的 span 层级结构

假设你必须丢弃大部分 span。层级结构的设计目标应该是:即使丢弃了部分数据,留下的 span 仍能回答你实际关心的那些问题。

根 span 应该是 Agent 的运行(agent run),而不是 HTTP 请求。这是许多团队将 gen_ai 规范强加到现有服务时最常犯的错误:他们让 Web 处理器作为根 span,导致 Agent 的轮次(turn)变成了原本就有四层深(来自中间件)的树结构中的一个深层节点。应该让 Agent 运行拥有自己的 trace 边界。如果需要关联,可以通过 span link(span 链接)向上连接到 HTTP 请求,但要让 Agent 拥有根 span。

在根 span 之下,在进入细粒度操作之前,请使用三个粗粒度层级:

  1. Turn(回合) — 一个用户消息以及为回答它所做的所有工作。
  2. Step(步骤) — 计划/执行循环(意图 → 计划 → 执行 → 观察)的一次迭代。
会员专享

余下内容仅对会员开放。

会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。

  • 完整文章,包含未公开存档的部分
  • 可落地的工作框架,附带权衡与决策依据
  • 新文章抢先看,先于公开发布

随时取消 · 一次订阅,畅读全部

参考资料

保持联系,关注我获取更多内容

阅读需 10 分钟

Agent 追踪采样:当 “记录所有内容” 耗费 8 万美元却依然漏掉性能退化时

请求级的采样策略对 Agent 追踪已不再适用。采用分层策略——始终追踪失败、对成功请求进行头部采样、按成本百分位进行尾部采样——能将追踪存储从预算黑洞转变为有效的事件响应工具。

insider
llm
阅读需 11 分钟

30 秒都去哪了:APM 无法察觉的 Agent 步骤内部延迟归因

传统的 APM 将 Agent 的一个步骤视为单一的粗粒度 Span,导致值班工程师只能靠猜。通过将其分解为七个阶段,区分首字延迟 (Prefill) 与解码 (Decode),并追踪关键路径而非总 Span 时间。

insider
observability
阅读需 11 分钟

跨 Agent 服务边界的分布式追踪:上下文传播的断裂

当 Agent 跨微服务边界调用 Agent 时,W3C TraceContext 会发生断裂,追踪信息碎片化为不相关的 Span。本文介绍故障的技术形态以及修复方法。

insider
observability
阅读需 9 分钟

Agent 流水线的分布式追踪:为什么你的 APM 工具形同虚设

标准 APM 工具在多步骤 Agent 流水线上会失效。以下是 AI Agent 专用可观测性的真正需求——以及三个能在用户察觉之前预判 Agent 劣化的关键指标。

insider
ai-engineering
阅读需 12 分钟

Agent 集群可观测性:在千并发 Agent 运行中监控而不陷入仪表盘盲区

单个 agent 运行的 span 树在集群规模下会失效。以下是在运行数百个并发 agent 时真正有效的集群级信号、采样策略和行为指纹技术。

insider
observability