多Agent上生产的第一课:日志、轨迹、回放与责任归因

多Agent上生产的第一课:日志、轨迹、回放与责任归因

单Agent出了问题,你打开对话记录从头看一遍就知道哪里错了。

多Agent出了问题,你可能连是哪个Agent干的都不知道。Lead Agent说它已经把任务分发下去了,Sub Agent A说它完成了自己的部分,Sub Agent B也说完成了。但最终结果是错的。谁的锅?

我在生产环境跑多Agent踩过这个坑。排查了两个小时,最后发现是Sub Agent A的输出格式跟Sub Agent B的预期不匹配,Lead Agent没有做格式校验就直接传递了。三个Agent都没报错,但结果就是废的。

从这件事之后,我把可观测性放到了多Agent系统的第一优先级。

01 第一层:日志

日志是最基础的。每个Agent的每次操作都要留痕。

一条合格的Agent日志至少包含这些字段:时间戳、Agent ID、动作类型(工具调用/LLM请求/消息传递)、输入参数、返回结果、耗时、token消耗。

很多人写日志只记"Agent调用了什么工具",不记参数和返回值。这在排查问题时几乎没用。你知道Agent调了一次文件读取,但不知道它读了哪个文件、拿到了什么内容。等你要回头查的时候,文件可能已经被改过了。

一个我在用的日志格式:

{
  "ts": "2026-02-10T14:32:01Z",
  "agent_id": "code-reviewer",
  "action": "tool_call",
  "tool": "read_file",
  "params": {"path": "src/api/handler.ts"},
  "result_length": 2847,
  "duration_ms": 120,
  "tokens_in": 0,
  "tokens_out": 0
}

LLM请求的日志要单独存。因为prompt内容通常很长,跟其他日志混在一起会导致日志文件膨胀到不可读。我的做法是主日志里记一个请求ID,详细的prompt和response存到独立的文件里。需要时按ID去查。

02 第二层:轨迹

日志是一条一条的记录。轨迹是把这些记录串成一条线,还原一个任务从开始到结束的完整路径。

一个典型的多Agent任务轨迹:

  1. 用户发起任务:"给这个API加上分页功能"
  2. Lead Agent分析任务,决定拆成两个子任务:修改数据库查询层、修改API响应格式
  3. Lead Agent把子任务1分发给Agent A(数据库专家)
  4. Agent A读取了当前的查询代码,调用了3次工具,生成了修改方案
  5. Agent A把结果返回给Lead Agent
  6. Lead Agent把子任务2和Agent A的结果一起发给Agent B(API专家)
  7. Agent B基于Agent A的修改,调用了4次工具,完成API层的修改
  8. Agent B返回结果
  9. Lead Agent汇总,返回给用户

轨迹要记录每一步之间的数据流。步骤3里Lead Agent发给Agent A的具体指令是什么?步骤5里Agent A返回的具体内容是什么?步骤6里Lead Agent有没有对Agent A的结果做二次加工?

没有这些信息,你在出问题的时候只能看到起点和终点,中间的传递过程是黑盒。

03 第三层:回放

能不能用同样的输入重现同样的执行路径?

理论上,如果你完整记录了每一步的输入输出,应该可以回放整个执行过程。实践中很难做到。

第一个障碍是LLM的非确定性。即使temperature设为0,同样的prompt在不同时间点跑出的结果也可能不同。模型供应商的服务端可能更新了权重、调整了推理参数,这些对你是透明的。

第二个障碍是外部状态。Agent在执行过程中读取了文件系统、调用了API、查询了数据库。回放时这些外部状态可能已经变了。你不能回到任务执行时的文件系统快照。

我的折中方案:不追求完美回放,追求"可解释的回放"。记录每一步的实际输入和实际输出,回放时用这些记录来还原逻辑链路,而不是真的重跑一遍。这样至少能回答"当时发生了什么",即使不能"重现当时的情况"。

对于关键任务,可以更进一步:在执行时把外部依赖的快照也存下来。Agent读了某个文件,就把那个时刻的文件内容存一份。Agent调了某个API,就把API的响应存一份。空间换可追溯性。

04 第四层:责任归因

出错时能定位到具体的Agent和具体的步骤。

这需要两个前提。第一是清晰的任务边界。每个Agent负责什么,输入是什么,输出是什么,要在任务分发时就定义清楚。如果Lead Agent给Sub Agent的指令是模糊的"帮我处理一下这个文件",出了问题你分不清是指令不清楚还是执行不到位。

第二是审计日志。不只是记录Agent做了什么,还要记录Agent为什么做这个决定。LLM在生成工具调用之前通常会有一段推理文本(thinking),这段文本对责任归因很有价值。它能告诉你Agent是基于什么判断选择了这个操作。

GitHub上有一个社区项目dylan-gluck/cc-dev-team,它做多Agent协作开发,里面提到了几个做法:实时可观测性、状态管理、智能hook。状态管理这一点我觉得说得好——每个Agent在执行过程中的状态变化(空闲→接收任务→执行中→等待依赖→完成)都应该被追踪。状态的异常变迁(比如从"执行中"直接跳到"空闲",跳过了"完成"状态)往往就是问题的信号。

05 Anthropic团队自己怎么做

Anthropic在他们的博客里提到过,内部安全团队用多Agent做生产问题诊断,问题诊断速度提升了3倍。

3倍提升的前提是他们有完整的观测体系。安全团队的多Agent系统能接入内部的日志平台、监控仪表盘、告警系统。Agent不是在黑盒里工作,而是在一个充分透明的环境里。

对于我们普通开发者,没有那么完善的基础设施,但思路可以借鉴。让Agent的执行环境尽可能透明。它读了什么、调了什么、判断了什么,都应该有记录。

06 一个最小可行的观测方案

如果让我推荐一个成本最低的方案,三个东西。

结构化日志。用JSON格式写日志,每条包含时间戳、Agent ID、动作、参数、结果。不要用纯文本日志,纯文本在后续分析时解析成本很高。

执行轨迹文件。每个任务生成一个轨迹文件,把这个任务涉及的所有Agent的所有操作按时间排列。文件名用任务ID命名,方便按任务检索。

错误快照。每次任务失败时,自动把当时的完整上下文存一份:所有Agent的日志、任务的输入、每个Agent的输出、失败时的错误信息。这些失败样本积累起来就是一个案例库。下次遇到类似的失败,先去案例库里搜一下,可能有现成的解决方案。

三样东西加起来,写代码大概一到两天的量。但它能把排查时间从"两小时翻聊天记录"缩短到"五分钟查日志"。

多Agent系统的可观测性投入,回报率远高于在prompt上反复调优。prompt调得再好,出了问题看不到执行过程,还是得靠猜。


参考链接:

  • dylan-gluck/cc-dev-team项目:https://github.com/dylan-gluck/cc-dev-team
  • Anthropic团队如何使用Claude Code:https://www.claude.com/blog/how-anthropic-teams-use-claude-code
  • Claude Code多Agent团队文档:https://code.claude.com/docs/en/agent-teams
  • Anthropic多Agent系统构建指南:https://claude.com/blog/building-multi-agent-systems-when-and-how-to-use-them
← 返回博客列表