教程

AI 智能体的可观测性:如何弄清智能体做了什么,以及应该记录什么

更新于: · Skillaria.Top

AI 智能体的可观测性,是指能够还原智能体做了什么、为何这样做以及有何证据支持的能力。它由两层构成:运行时(操作日志、追踪、检查输出)和过程(任务约定、验收标准、附带证据链接的报告)。缺少任何一层,智能体说的“完成”都毫无意义。

什么是 AI 智能体的可观测性

AI 智能体的可观测性,是指能够依据工件而非记忆,也不依据智能体的言辞,回答三个问题:它做了什么,为什么这样做,以及凭什么认为结果是正确的。如果智能体工作二十分钟后说“完成了,但有两个测试失败,可能是时序问题”,而被问到“涉及了哪些路径”时只回答“请让我看看代码”,那就谈不上可观测性。智能体并不笨,只是没有东西可以拿出来证明。

这个问题是系统性的。同一个智能体一周之内可能十次诚实地说“完成了”,而每次的含义都不同:有时是跑完了所有测试,有时只跑了一个,有时什么也没跑。项目存在得越久,每次新会话的代价就越高,因为每次都要从挖掘开始。

两层结构:运行时与过程

人们常把可观测性与日志混为一谈,但日志只是其中一半。

层回答的问题工件
运行时发生了什么智能体操作日志、追踪、测试和构建的输出、提交记录
过程想要什么,为何这样做任务约定(范围、验收标准)、评分细则、智能体报告

只有运行时:能看到什么失败了,却不知道目标是什么。只有过程:知道想要什么,却看不到为何没有成功。两者缺一不可。

为什么智能体自己做不到这一点

对智能体说“记录得详细些”是行不通的,原因有三点。

  • 它不知道自己不知道什么。智能体不会记录它没有意识到重要的信号。
  • 格式不固定。同一个智能体在一次会话中写得很详细,在另一次只写一行。无法比较各次会话,也无法统计汇总。
  • 过程无法靠日志来覆盖。“为什么这样做”的答案存在于工作开始前创建的文档中,而不在命令的输出里。

因此,可观测性应当写入 harness——即智能体的工作环境:模板、hooks、脚本,以及强制的报告格式。

应当记录什么:最小集合

好的日志不是对一切的逐字记录,而是一组事实,依靠它们可以还原工作的过程,也可以统计数据。

  • 标识符:会话 ID、任务或功能的 ID、智能体所用的模型。
  • 有副作用的操作:运行了哪些命令,修改了哪些文件。读取文件通常不必记录。
  • 检查结果:使用的检查命令、返回码、通过和失败的测试数量。
  • 重试:某一步花了多少次尝试,每次尝试有何不同。
  • 消耗:如果工具提供,记录 token 数量和耗时。
  • 结论:任务是被接受、被拒绝,还是被放弃,以及原因。

不要记录:密钥、访问令牌、命令输出中的个人数据。日志可能会被公开共享,或者再次进入模型的上下文。

通过 hooks 记录 Claude Code 的操作日志

在 Claude Code 中,操作日志最适合用 hooks 来记录——这些命令由工具本身运行,而不是由模型运行,因此总能触发。hook 从 stdin 接收描述事件的 JSON,其中包括会话 ID、工具名称及其参数。下面是在 .claude/settings.json 中的配置示例:每次调用 Bash、Edit 或 Write 之后,都会向日志中追加一行:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash|Edit|Write",
        "hooks": [
          { "type": "command", "command": ".claude/hooks/log-action.sh" }
        ]
      }
    ]
  }
}
#!/usr/bin/env bash
# .claude/hooks/log-action.sh — 每个操作一行 JSON
mkdir -p .agent/logs
jq -c '{ts: (now | todate), session: .session_id, tool: .tool_name,
        cmd: .tool_input.command, file: .tool_input.file_path}' \
  >> .agent/logs/actions.jsonl || true

JSONL 格式(每行一条 JSON 记录)的优点是便于用 jq 过滤,也便于导入任何分析系统。此外,Claude Code 自身会在 ~/.claude/projects/ 目录中本地保存完整的会话历史。如果需要查看完整的推理过程和输出,可以打开它;但要统计数据,自己维护的精简日志更方便。

追踪:每个会话一条 trace,每个任务一个 span

当智能体数量多,或者它们按计划运行时,文本日志就不够用了,需要汇总数据。这时可以使用常见的分布式追踪工具和 OpenTelemetry 标准。

  • Trace——一次智能体会话。
  • Span——会话中的一项任务。
  • 嵌套的 span——验证步骤:构建、测试、端到端测试。

每个 span 的最少属性:功能 ID 和会话 ID、模型、检查结果、token 数、重试次数。这些数据可以在 Jaeger、Grafana Tempo、Honeycomb 中查看,并回答单个会话无法回答的问题:哪类任务最常需要重试,智能体在哪里消耗的 token 最多,哪次对 harness 的修改之后被接受的任务比例下降了。Claude Code 内置了通过 OpenTelemetry 导出指标和事件的功能,通过环境变量开启,具体细节请参阅该工具的文档。

用提交作为日志

最便宜、最可靠的日志您早已拥有——那就是 git。只需要让它可读。

  1. 一次提交,对应一项任务。这样 git log 就与已完成的工作清单一致,撤销一项任务只需一次 git revert。
  2. 提交信息中写明做了什么、如何验证。不要写“fix”,而要写“改了什么、为什么改、用什么命令验证”。
  3. 只有在检查通过之后才提交。这样历史中的每个节点都是可用的状态,git bisect 才能找到问题的源头。
fix(payments): 折扣舍入到分

折扣在 float 中计算,金额 999.99 时丢失了一分钱。
改为以整数分为单位进行计算。
已验证:make test(142 passed),make e2e checkout — 正常。
范围之外:报表中的舍入,已记入 BACKLOG.md。

智能体报告:用证据代替印象

如果智能体的最终消息具有固定格式,它本身也是可观测性的工件。把模板写入 AGENTS.md 或 CLAUDE.md:

## 任务结束时的报告
- 完成了什么:修改清单(文件 — 内容)
- 如何验证:确切的命令及其结果
- 未验证的内容及原因
- 与任务约定的偏差
- 需要人工回答的开放问题

核心规则:每一项论断都要有证据支撑——文件和行号、测试输出、日志中的记录。“看起来正常”和“我觉得没问题”不算报告。“未验证的内容”这一项尤其有价值,它诚实地展示了信心的边界。

工作前的约定,工作后的评分细则

过程层从工作开始之前就已存在。简短的任务约定(sprint contract)需要写明范围、验收标准、“范围之外”一节,以及由人决定的开放问题。“范围之外”这一节能避免一半关于结果的争论。

工作完成之后,依据评分细则评估结果,而不是凭印象。否则,两位经验丰富的评审者可能给出截然不同的结论,评估就变成了抽签。

维度问题证据
正确性验收标准是否满足?测试输出、端到端测试
架构模块边界是否得到遵守?文件:行号
测试新行为是否被覆盖?新增测试的清单
错误处理故障和边界情况是否得到处理?测试或文件:行号
可观测性能否从日志中看出正在发生什么?日志片段

每个维度按 A/B/C/D 评分,没有证据链接的评分无效。简单的决策规则是:一个 D 或两个 C,就拒绝并列出需要改进的内容。同样的评分细则也可以交由独立的检查智能体来执行。

如何梳理智能体在一次会话中做了什么

如果没有报告,或者不信任报告,请按以下顺序检查工件。

  1. 工作区状态:git status——哪些内容未提交,有没有垃圾文件。
  2. 历史:从会话开始的 git log --stat——有哪些提交和文件。
  3. 改动规模:git diff --stat main...HEAD,然后逐一查看重要文件的完整 diff。
  4. 操作日志:运行过哪些命令,检查返回了什么。
  5. 重新验证:自己运行构建和测试。相信命令的输出,而不是对它的转述。
# 智能体在最近一次会话中运行了哪些命令
jq -r 'select(.tool=="Bash") | .cmd' .agent/logs/actions.jsonl | tail -n 30
# 哪些文件被修改得最频繁
jq -r '.file // empty' .agent/logs/actions.jsonl | sort | uniq -c | sort -rn | head

常见错误

  • 什么都记录。吉字节的逐字记录没有人会读。只记录有副作用的操作和检查结果。
  • 格式自由。如果日志的格式由智能体自行决定,就无法汇总。格式应由 harness 来规定。
  • 相信没有命令输出的报告。“测试都通过了”而没有输出,只是一种意见。
  • 盲目重试。不知道失败原因,智能体就会去修改随机的地方。应先要求给出带有日志链接的诊断,再允许修改。
  • “以后再清理”。调试文件和未提交的改动会误导下一个会话:它无法分辨哪些是临时的,哪些是有意为之的。

小结

AI 智能体的可观测性由两层构成:运行时(通过 hooks 记录的操作日志、追踪、带有验证说明的提交)和过程(工作前的任务约定、工作后的评分细则,以及附带证据的报告)。这样,“完成”在每个会话中都意味着同一件事,而分析智能体的工作只需几分钟。我们在 harness engineering 课程中,结合一个端到端的支付后端项目,对这一主题进行了实践讲解。

常见问题

AI 智能体的可观测性与普通的监控有什么不同?

监控回答的是系统现在是否在运行。智能体的可观测性还必须回答智能体为何作出某个决定,以及结果有何证据支持,因此在日志之外还要加入任务约定、评分细则和报告。

Claude Code 把会话历史保存在哪里?

本地,位于 ~/.claude/projects/ 目录中,以 JSONL 文件的形式按会话保存。要做统计,通过 hooks 维护自己的精简日志更方便。

能相信智能体关于工作的报告吗?

只有当每一项论断都有可验证的证据支持时才能相信:命令的输出、文件:行号的引用、日志记录。关键的检查最好由您自己重新运行。

对于单个开发者,需要 Jaeger 或 Grafana 吗?

通常不需要:JSONL 日志、规范的提交和报告模板就足够了。当智能体数量增多或者它们定期无人值守地运行时,追踪系统才会物有所值。

如果智能体不按模板写报告怎么办?

让模板简短,并放在指令文件的开头;同时用机制来保证遵守,例如在结束时运行的 hook,或者一个独立的检查智能体,它会把没有报告的工作退回。

通过视频学习本主题

课程“Harness Engineering: инженерия надёжности AI-агентов”结合实践详细讲解了这一主题。

前往课程