B15
概念 · 核心构件
智能体可观测性与追踪。
一个在 30 步任务的第 14 步失败的智能体,只会告诉你一件事——"它没成"——除非你为它做了埋点,那样你就能重放出把它带偏的那一条确切提示词、那一次确切工具调用、那一个确切结果。本条目讲清该记录什么、该以什么形式记录,以及"观察一个系统"与"评估一个系统"之间的区别。
STEP 1
一次运行是一棵树,而非一条线。
对普通 Web 服务而言,可观测性的单位是一次请求。对智能体而言,单位是一条追踪(trace):一次完整运行,被拆解成与智能体循环相对应的嵌套跨度(span)。典型形态是:
- 一次运行——一个用户目标,从首次输入到最终答案或放弃。
- 其中,循环每迭代一次就是一个步骤。
- 每个步骤里,有一次模型调用(送进去什么、返回来什么),以及零到多次工具调用(参数、结果、错误)。
- 子智能体、重试与检索调用,也以同样方式嵌套。
这棵树有两个属性让它有用。它保留了顺序——你能看出智能体是先搜索后写作,还是先写作再搜索来自圆其说。它也保留了因果——每一步的输入都包含上一步的输出,所以你可以从一个坏动作往回走,找到产生它的那次观察。
这正是普通日志行不够用的原因。日志告诉你某个事件发生了;追踪告诉你模型做决定时正在看着什么。
STEP 2
一条最小可用的追踪。
六样东西,而多数团队是吃了苦头才发现自己缺了其中三样:
- 实际发送出去的那份提示词。不是模板——是把检索、记忆与历史都拼接进去之后、完整组装好的文本。几乎每一个"它为什么那么做?",都能靠读一遍模型真正看到的东西来回答,而模板给不了你这个。
- 模型的原始响应。包括带着确切参数的工具调用,以及提供方所暴露的任何推理内容。参数极其要紧——一个错误动作,通常是对的工具配上了错的参数。
- 工具返回的结果。返回了什么,包括错误与超时,且要与智能体所见的完全一致。追踪里若是被截断或被重新格式化过的结果,会让下一步的推理无法复现。
- 每个跨度的成本与延迟。输入令牌、输出令牌、缓存令牌、墙上时钟。在一次运行上聚合起来,就得到"每任务成本"——这是任何为该系统付钱的人迟早会问的那个数字。
- 贯穿始终的一个追踪 ID。一个标识符,出现在每个跨度、每次下游服务调用、每件用户可见的产物上——这样一张工单就能被变成一次重放。
- 一切可变之物的版本。提示词版本、模型标识、工具 schema 版本、检索索引版本。没有这些,一次回归就无从归因:你知道行为变了,却不知道是同时发生的四处改动中的哪一处造成的。
STEP 3
三个问题,三种用途。
埋点靠回答三个不同缩放层级上的问题来赚回它的成本:
- 这一次运行里发生了什么?调试某个具体失败。你打开追踪,找到轨迹开始偏离应有路径的第一步,然后读这一步的输入。答案几乎总是就摆在那里——一次什么也没返回的检索、一个被模型当成结果的工具错误、一条仍滞留在上下文里的过期指令。
- 跨越多次运行会发生什么?聚合把轶事变成工程:任务成功率、每任务的成本与步数、按工具划分的错误率、智能体撞上步数上限的频次、延迟究竟花在哪里。一个错误率 30% 的工具是个设计问题,而你逐条看追踪永远发现不了它。
- 这次改动有没有帮上忙?在同一批任务上比较提示词修改或模型更换的前后。没有带版本的追踪,你就只能依赖印象——而在一个随机性系统上,印象在两个方向上都不可靠。
STEP 4
埋点是怎么做砸的。
- 只记录最终答案。最常见的一个错误。最终答案是失败浮现之处;轨迹才是失败发生之处。一次运行完全可能经由一条彻底走坏的路径产出貌似合理的最终答案——也完全可能在一切都做对之后败在最后一步。
- 记模板而不记渲染结果。存起来更省,调试时却没用。如果你只保留模板加上一份输入的引用,那你必须能逐字节重建出那份确切的提示词——而一旦牵涉检索与记忆,这种重建通常就不再可复现了。
- 把失败采样掉了。为控制存储成本而只采样 1% 的追踪是合理的;均匀采样则不然。请把每一次失败的、升级的、昂贵的或异常冗长的运行全部保留,而去采样那些平淡无奇的成功。
- 让机密泄进追踪。一条完整提示词的追踪,包含智能体看到的一切——客户数据、检索到的文档、泄漏进某条 shell 命令的工具凭据。追踪于是成了你最敏感数据的第二份副本,而其访问控制通常比原件更弱。请在采集时脱敏,而不是在读取时。
在你需要之前就先埋好点。智能体的失败常常无法复现——一次返回了不同文档的检索、一个采样到不同分支的模型、一个那天下午行为异常的外部服务。如果当时没把追踪抓下来,这次运行就没了,你只能对着一段"关于失败的描述"调试,而不是对着失败本身。
本站的追踪与可观测性章节讲生产级埋点技术栈,智能体事故响应讲出事之后拿着追踪该做什么,而轨迹与过程评估深入解析则讲如何为追踪所记录的每一步打分,而不只是给结尾那个答案打分。