
先看一个判断上的差异。
普通微服务里,"出问题"的信号是明确的:异常率涨了、P99 抖了、某个下游返回 5xx。观测系统的任务是把这些信号关联起来,回答"哪个依赖挂了"。
Agent 不是这样。它的典型故障长这样:任务跑完了,没有报错,耗时和 token 都在正常区间,但结果是错的。或者:任务没跑完,卡在第 6 步等一个永远不返回的工具调用,而监控上一切正常。
所以照搬 APM 会碰到三个结构性差异。
边界不同。 一个用户请求对应的是"一次任务",任务里包含若干步决策,每一步又可能触发一次模型调用和若干次工具调用。层级不是干净的 RPC 树,而是"任务 → 步骤 → 调用"三层,且步骤的数量在运行前是未知的。
失败形态不同。 服务会抛异常,模型不会。模型会给一个语法完全合法、语义完全错误的答案。超时也可能是"慢"而不是"挂",或者干脆是输出被截断。
内容即数据。 服务调用的关键信息是状态码和耗时;Agent 调用的关键信息是它看到了什么、决定了什么。只记耗时和状态码,等于什么都没记。
我会把观测模型定成:一次任务 = 一条 Trace,Span 按角色分四类。
最后这一项是 Agent 特有的,也是最有用的:线上出问题时,你要能一眼看出"这次任务动了几次非幂等写"。
如果你们已经在用 OpenTelemetry,可以直接沿用它的 GenAI 语义约定方向——它已经覆盖了模型名、token 用量、请求参数、响应标识这几类属性。Agent 特有的(任务、步骤、副作用等级)再自己加命名空间,不要硬挤进模型那套属性里。
这一条值得单独拎出来,因为它经常被合并成一个"耗时"。
两个指标指向完全不同的问题:
合并成一个耗时之后,这两种情况在监控上长得一模一样,而优化方向完全相反:前者要压上下文和排队,后者要压输出长度和工具耗时。
还有一个 Agent 特有的信号:一次任务里的重试次数。重试率突然上升,往往不是模型的问题,而是某个工具开始变慢或开始返回格式错的东西。
Span 里塞原始输入输出会让存储迅速失控。一个检索工具返回几万字是常事。
稳妥的做法是:Span 里存引用 + 摘要 + 哈希。
span.set_attribute("input_ref", "oss://agent-trace/{trace_id}/{span_id}/in")
span.set_attribute("input_len", len(payload))
span.set_attribute("input_hash", sha256(canonical(payload)))
span.set_attribute("input_preview", payload[:200])三个字段各有用途:
input_ref 让你在需要时能取回全文,用于回放。
input_hash 有两个额外好处。一是去重:同一段输入在两个任务里出现,可以直接看出是重复调用。二是调试缓存:前缀缓存的命中判定本质上是哈希比对,这个字段能直接告诉你"缓存为什么没命中"。
input_preview 是给人看的。九成的排查只需要看这两百个字符。
顺带说一句:内容里必然带敏感信息。所以 Span 落库前要有脱敏环节,并且给引用设置保留期限——观测数据的保存周期通常应该短于业务数据。
微服务里按 1% 采样是可以的,Agent 不行。原因是"这次执行有没有价值"要等 Trace 结束才知道。
所以要用尾部采样(tail-based sampling),规则大致是:
一个容易被忽略的点:慢不等于有价值。很多团队按耗时排序看 Trace,结果只看到了一堆慢但成功的请求。真正该被看的是"结果不对"的那批,而它们往往又快又安静。
回放是观测系统的终点,也是它区别于日志的地方。我把它分三级。
一级:日志回放。 把一条 Trace 渲染成可读的时间线——第几步、模型看到了什么、决定了什么、调了什么工具、返回了什么。这一级最容易做,也最能立刻解决问题。大多数团队做到这一级,就能处理八成以上的线上排查。
二级:决策回放。 把当时喂给模型的完整上下文逐字重现,然后用同样的参数重新请求一次。这要求上下文装配层输出结构(前缀、尾部、被丢弃的内容),而且要求装配是确定性的——这正好是上下文装配那一篇里强调过的性质。做不到确定性,这一级就没法做。
三级:副作用回放。 在沙箱里用打桩的外部依赖重跑同类任务,看行为是否一致。这一级依赖前面两件事:步骤要标副作用等级,外部调用要能打桩。它更接近"回归测试"而不是"排查",所以优先级可以往后放。
我的建议是明确只做一级,把它做扎实,别一上来就规划三级。
我不建议第一版就接全套 OTel collector + 后端。链路长、组件多,而你现在真正需要的只是"能按 task_id 查出一条时间线"。
先把 Span 写成一张普通的关系表(或者一个支持 JSON 字段的列存表),用 SQL 能查。等数据量和查询复杂度真的顶不住了,再往标准栈上迁。
观测系统的第一版,目标是让自己愿意打开它,而不是架构正确。
input_ref / input_hash / input_preview 三件套,脱敏规则同时定。Agent 的观测不是"给模型调用加个埋点",而是给一个多步、跨进程、失败不报错的过程建立可追问的记录。它的验收标准很朴素:线上有人说"这次结果不对",你能在几分钟内打开一条时间线,指着某一步说——问题在这儿。
同系列:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。