多 Agent 系统一旦出问题,调试难度是单 Agent 的十倍。本文提供一套可操作的诊断框架:故障分类 → Tracelog 拓扑 → 四步诊断法 → 根因修复。适用于 Supervisor-Worker、Consensus、Pipeline 等主流多 Agent 架构。


目录


一、为什么多 Agent 调试是独立课题

在单 Agent 场景下,调试的核心问题是:

“Agent 输出的代码为什么有 Bug?”

调试对象是代码——断点、打印、日志,这些传统方法依然有效。

在多 Agent 协作场景下,问题变成了完全不同的性质:

“为什么 Agent A 的输出导致 Agent B 行为异常?”

这不是代码问题,而是系统架构问题。传统调试方法失效,因为:

  1. 思维过程是隐性的:Agent 的决策链不透明,工具调用之间存在复杂的因果链
  2. 故障可能在协作层:不在任何单个 Agent 内部,而在 Agent 之间的信息传递
  3. 症状和根因分离:Agent C 报错,但根因是 Agent A 两个小时前的一个错误决策

本文目标:提供一套系统化的多 Agent 故障诊断方法,让”坏了知道怎么修”成为可复制的能力,而不是靠运气。


二、故障分类:协作层 vs 系统层

多 Agent 系统的故障分为两类:协作层故障(Agent 之间的交互问题)和系统层故障(底层基础设施问题)。两类故障的诊断方法不同。

2.1 协作层故障

故障 1:上下文污染(Context Pollution)

一个 Agent 的输出包含了不该传递到下游的信息,下游 Agent 收到错误上下文。

典型场景:

User: "修复登录 bug"
Supervisor → Agent-A: 分析登录模块
Agent-A 回复: "登录模块的问题已定位,顺便检查了支付模块发现潜在问题"
Supervisor → Agent-B: 验证登录修复
Agent-B 回复: "你提到支付模块有问题,要不要一起修?"

问题根因:Supervisor 没有对 Agent-A 的输出做过滤,把全部内容透传给了 Agent-B。Agent-B 接收到了与当前任务无关的信息。

诊断信号

故障 2:角色漂移(Role Drift)

某个 Agent 在多轮迭代中逐渐偏离了自身角色定位,开始承担其他 Agent 的职责。

典型场景:

Worker Agent(负责实现)经过多轮后开始:
- 自己优化代码风格(本该 Architect 做)
- 添加注释(本该 Human Review 做)
- 重构架构(本该 Architect 做)

问题根因:Agent 的 System Prompt 没有强约束力,或者任务分解时角色边界不清晰。

诊断信号

故障 3:共识失效(Consensus Failure)

Multi-Agent Consensus 模式下,多个 Agent 独立分析同一问题,但结论差异过大,无法形成有效共识。

典型场景:

Agent-1 结论: "根因是数据库连接池配置太小"
Agent-2 结论: "根因是 API 超时设置不合理"
Agent-3 结论: "根因是 Redis 缓存失效"
→ 人工介入阈值设置过低,导致大量假阳性
→ 或者阈值设置过高,真问题被忽略

诊断信号

2.2 系统层故障

故障 4:循环依赖(Circular Dependency)

Agent-A 需要 Agent-B 的输出才能完成任务
Agent-B 需要 Agent-C 的输出才能完成任务
Agent-C 需要 Agent-A 的输出才能完成任务
→ 系统死锁,LLM 推理进入无限循环

诊断信号

故障 5:资源竞争(Resource Contention)

多个 Agent 同时修改同一个文件/模块,后面的修改覆盖了前面的。

典型场景:

Agent-1 修改了 UserService.java 第 50-60 行
Agent-2 修改了 UserService.java 第 55-65 行
(由同一个 Supervisor 分配,并发执行)
git merge 时产生冲突,Agent-1 不知道 Agent-2 已经改过

诊断信号

故障 6:记忆干扰(Memory Interference)

多 Agent 系统共享的记忆被污染,Agent 用错误的历史信息做判断。

典型场景:

Agent-1 前一个任务处理了"用户 A 的订单问题"(含敏感数据)
Agent-2 当前任务需要"分析订单模块"
共享记忆没有做隔离,Agent-2 从记忆里读到了用户 A 的敏感信息

诊断信号


三、核心调试工具:Tracelog 拓扑与因果追踪

3.1 多 Agent Tracelog

单 Agent 的 Tracelog 记录一个 Agent 的操作序列。多 Agent Tracelog 需要记录整个系统的协作拓扑

{
  "session_id": "multi-agent-debug-001",
  "timestamp": "2026-04-14T10:00:00Z",
  "agents": [
    {
      "agent_id": "supervisor-1",
      "role": "supervisor",
      "parent": null,
      "children": ["worker-1", "worker-2"]
    },
    {
      "agent_id": "worker-1",
      "role": "code-writer",
      "parent": "supervisor-1",
      "children": []
    }
  ],
  "events": [
    {
      "event_id": 1,
      "timestamp": "2026-04-14T10:00:05Z",
      "from": "user",
      "to": "supervisor-1",
      "type": "task_assignment",
      "content": "修复登录 bug"
    },
    {
      "event_id": 2,
      "timestamp": "2026-04-14T10:00:10Z",
      "from": "supervisor-1",
      "to": "worker-1",
      "type": "subtask_dispatch",
      "content": "分析 login.py",
      "tool_calls": ["Bash: grep -n session", "Read: login.py"]
    },
    {
      "event_id": 3,
      "timestamp": "2026-04-14T10:00:30Z",
      "from": "worker-1",
      "to": "supervisor-1",
      "type": "subtask_result",
      "content": "发现 session TTL 配置问题",
      "is_error": false
    }
  ]
}

关键调试信号对照表

信号 含义
同一父节点连续触发多个同类型子任务 可能的角色漂移或过度拆分
消息传递延迟突然增大 某个 Agent 陷入复杂推理或死锁
子 Agent 输出被父 Agent 直接透传 缺乏输出过滤层(上下文污染风险)
循环消息(Agent A→B→A 反复) 循环依赖或死锁
某节点长期处于 waiting 状态 上游消息丢失或处理超时
共识轮次超过 5 轮仍无结果 共识失效,需要干预

3.2 消息拓扑可视化

多 Agent 系统的调试视图应该是消息拓扑图,而不是线性日志:

User
  ↓ [task: 修复登录 bug]
Supervisor
  ├→ Worker-A [analyze] → "发现 session TTL 问题"
  │                      ↓
  │                   Supervisor
  ├→ Worker-B [implement] → "已修复配置文件"
  │                      ↓
  │                   Supervisor
  └→ Worker-C [verify] → "测试通过"
                       ↓
                    Supervisor
  ↓ [result]
User

这个拓扑图需要标注:

工具实现

3.3 因果追踪(Counterfactual Tracing)

因果追踪是多 Agent 调试的核心方法——“如果当时不是这样做,结果会不同吗?”

场景:
  Supervisor 把 Agent-A 的输出直接传给了 Agent-B
  Agent-B 基于错误上下文做出了错误决策

调试方法:
  1. 用 Agent-B 收到的"干净"输入重新运行
  2. 观察 Agent-B 的决策是否改变
  3. 如果变了 → 证明是 Agent-A 输出污染
  4. 如果没变 → 问题在 Agent-B 本身
  
OpenClaw 实现:
  sessions_spawn 创建分支 Session,同时运行两条路径对比结果

四、四步诊断法

Step 1:拓扑重建——先画图,不急着看代码

在调试多 Agent 系统之前,先重建整个协作拓扑:

1. 导出 Session 历史(sessions_history)
2. 提取所有 Agent 间的消息传递事件
3. 生成 Mermaid 拓扑图
4. 标注每个节点的输入/输出关键内容

目标:搞清楚”谁在什么时机给了谁什么信息”。

拓扑重建检查清单

Step 2:异常信号检测——找出口和入口

异常信号(说明有问题):

正常信号(说明系统运行正常):

Step 3:单点隔离——逐个 Agent 诊断

找到异常节点后,单独对该 Agent 做诊断:

1. 用该 Agent 的输入(收到的消息)重新构造独立会话
2. 单独运行,看它是否产生同样的错误
3. 如果错误消失 → 问题是上游传来的(回到 Step 2 找上游)
4. 如果错误保留 → 问题在该 Agent 内部(深入分析该 Agent)

单点隔离检查清单

Step 4:根因修复——改架构,不是改 Prompt

多 Agent 系统的很多问题本质上是架构问题,而非 Prompt 问题:

问题类型 架构修复 Prompt 修复
上下文污染 在 Supervisor 层加 Filter Agent “不要传递无关信息”
资源竞争 在调度层加互斥锁(文件锁) “不要修改其他 Agent 修改过的文件”
记忆干扰 使用向量数据库做记忆分区 “忽略其他任务的上下文”
循环依赖 引入超时退出机制和死锁检测 降低 LLM 推理层数
共识失效 调整共识阈值或引入 LLM 裁判 “你的结论需要与其他人一致”

核心原则:能用架构解决的问题,不要用 Prompt。Prompt 是软约束,架构是硬约束。


五、根因修复:改架构,不是改 Prompt

5.1 协作层的架构修复

上下文污染 → 加 Filter Agent:

Before: Supervisor → 直接透传 → Worker
After:  Supervisor → Filter Agent → "干净"上下文 → Worker

Filter Agent 的职责:
  - 分析 Supervisor 的输出
  - 提取与当前子任务直接相关的内容
  - 丢弃无关信息(如其他任务的发现、闲聊、推测)

资源竞争 → 调度层加互斥:

Before: Supervisor 并发分配 → Agent-1 和 Agent-2 同时改 File-A
After:  调度层维护文件锁
        Agent-1 请求 File-A → 获得锁
        Agent-2 请求 File-A → 等待释放

记忆干扰 → 向量数据库分区:

Before: 共享记忆,所有 Agent 看到相同的记忆上下文
After:  记忆按 Agent 角色/任务分区
        Architect Agent 只检索架构相关记忆
        Coder Agent 只检索代码相关记忆
        跨角色记忆共享需要显式授权

5.2 系统层的架构修复

循环依赖 → 超时 + 死锁检测:

# 在 Agent 调用层加入超时控制
async def call_agent(agent_id, task, timeout=30):
    try:
        result = await asyncio.wait_for(
            agent[agent_id].process(task),
            timeout=timeout
        )
        return result
    except asyncio.TimeoutError:
        # 触发死锁告警,回滚到上一个稳定状态
        trigger_deadlock_recovery(agent_id)

Token 预算爆炸 → 多层熔断:

Layer 1: 单 Agent max_turns(防止单个 Agent 无限循环)
Layer 2: Session max_tokens(防止整个系统 Context 溢出)
Layer 3: 预算超支时强制触发 compaction
Layer 4: 超过预算阈值时触发人工告警

六、实战案例:从上下文污染到循环依赖

案例背景

项目:Spring Boot 微服务改造
架构:Supervisor + 3 Worker(Architect / Coder / Reviewer)
问题表现:Reviewer Agent 突然开始修改架构设计文档

Step 1:拓扑重建

导出 Session 历史,重建拓扑:

User
  ↓ [task: 微服务拆分]
Supervisor
  ├→ Architect: "设计服务边界"
  │               ↓ "推荐按订单/支付/用户拆分"
  │            Supervisor
  ├→ Coder: "实现订单服务"
  │          ↓ "使用了 XX 框架"
  │       Supervisor
  └→ Reviewer: "Review 代码"
                ↓ "建议调整架构" ← 这里 Reviewer 开始做 Architect 的事
             Supervisor

Step 2:异常信号检测

Step 3:单点隔离

隔离 Reviewer Agent,用”干净”的代码审查输入运行:

结果:Reviewer 正常做代码审查,没有出现架构建议
结论:问题不是 Reviewer 本身,而是它接收到的上下文

Step 4:根因定位

Supervisor 的消息传递拓扑:

Architect → [全部输出] → Supervisor → [全部内容] → Reviewer
                              ↑
                         没有 Filter 层

Supervisor 把 Architect 的所有输出(包括架构分析)都传给了 Reviewer,而 Reviewer 的 System Prompt 没有明确说”只做代码审查,不要提架构建议”。

Step 5:修复

架构修复(根本解决方案):

class FilteringSupervisor:
    def route(self, worker_output, target_agent):
        # 只传递与目标 Agent 角色相关的内容
        relevant_context = self.filter(
            context=worker_output,
            target_role=target_agent.role  # "reviewer"
        )
        return relevant_context

Prompt 修复(临时缓解):

Reviewer Agent 的 System Prompt 增加:
"你只负责代码层面的审查,包括:逻辑错误、安全漏洞、测试覆盖率。
不要提出架构调整建议——那是 Architect Agent 的职责。"

七、与现有博客的关联

本文是以下博客的”反面”

已有博客 本文关联
多Agent编排(2026-03-22) 编排的正面设计 → 编排的故障诊断
AI辅助调试(2026-03-23) 单 Agent 调试 → 多 Agent 调试
Agent治理(2026-03-24) 预防问题 → 出了问题怎么查
自修正模式(2026-04-12) 单 Agent 自修正 → 多 Agent 系统级修复
Agent Teams vs Subagents(2026-03-25) 架构选择 → 架构坏了怎么修

完整能力闭环

设计(编排) → 运行(自修正) → 调试(本文) → 治理(预防)
     ↑                                              ↓
     ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ←

附录:多 Agent 调试检查清单

每次诊断必查

预防性检查(系统上线前)