OpenClaw multi-agent pipeline 实测:为什么 G1/G2 人工闸门被跳过了 4 次
一次 8 小时、4 轮重跑、40+ 子代理调用的踩坑全记录

OpenClaw multi-agent pipeline 实测:为什么 G1/G2 人工闸门被跳过了 4 次
起因:一次本该跑 1 次的调研,跑了 4 次
2026 年 7 月 20 日,我跑了一个多 Agent 调研流水线(monetization-research skill),从用户输入约束到产出最终报告,预期跑 1 轮、耗时约 1 小时。
结果跑坏了 4 轮、8 小时、40+ 次子代理 spawn、12+ 次重试——而且没有一次是"想换个方向试试",全部是因为流水线 bug 被强迫重启。
最讽刺的是:人工审查闸门 G1 和 G2 被跳过了 4 次,100% 失败率。
[ILLUSTRATION: 4 轮调研流程对比图,左侧是理想流程(S0→G1→S1→S2→S3→S4→G2→S5),右侧是实际流程(4 次循环,每次 G1/G2 都被跳过直接进入 S5)]
流水线结构
调研流水线分为 5 个阶段(S0~S5),中间有 2 个人工闸门(G1/G2):
用户输入 → S0(约束锁定) → ⏸ G1(用户确认) → S1(信号侦察)
→ S2(信号综合) → S3(候选方案) → S4(CFO+风险官评审)
→ ⏸ G2(用户拍板) → S5(终报输出)G1 在 S0 之后,让用户确认约束条件是否正确;G2 在 S4 之后,让用户在 CFO 和风险官的评审结果上拍板决定是否进入终报。两个闸门都是人工决策点,理论上 agent 必须等用户输入 1/2/3 才能继续。
第 1 轮:路径写错 + G2 跳过
第一次跑,S0 完成、S1 启动、S2 启动、S3 启动、S4 启动——完全没等用户,直接一路冲到了 S5。G1 和 G2 都被静默跳过了。
而且由于路径写成了相对路径,所有文件被写到了 agent workspace 里,用户根本找不到。
# 第 1 轮的 prompt 示例(路径写错,G2 无闸门)
orchestrator spawn S1 --input "$S0_BRIEF" --output "./output/"
# 相对路径 "./output/" 被解析为 agent workspace!
# G1/G2 从未出现用户反应:“有这个目录了?” → 发现路径写错,重建。
第 2 轮:P0 修复验证,G2 仍然跳过
修复了路径问题(改绝对路径)和 orchestrator ack 正反馈循环(加 silent 模式),重跑。结果 G1/G2 仍然被跳过,CFO 和风险官直接出结论,然后流水线自动进入 S5 写报告。
# 第 2 轮:路径修复了,但 G2 仍然跳过
orchestrator spawn S1 --input "$S0_BRIEF" --output "/abs/path/"
# 等 S4 完成后 → 直接 spawn S5,不出 G2 闸门
# 用户没机会拍板用户反应:约束条件被理解错了(“最小单笔不限"被忽略),用户再次纠正后重跑。
第 3 轮:约束锁定,但 S2 数据丢失
用户这次明确写死了约束条件并在 G1 前锁定。结果 S2 的 agent 没有写盘,导致 S3 的候选方案缺乏数据支撑。CFO 和风险官基于不完整的数据做评审,结果自然不可靠。
# 第 3 轮:约束锁定了,但 S2 agent 不写盘
S2_agent=$(spawn S2 --input "$S1_SIGNALS")
# S2_agent 执行完但没有写 evidence-index.md!
# 后续所有阶段都基于空数据运行用户反应:“怎么又错了?” → 用户开始质疑流程逻辑。
第 4 轮:终于走到 G2,但 S5 已经写完了
这一轮把所有修复都落地了:路径正确、S2 强制写盘、网络超时自动重试、约束锁定。S4 完成后,终于出现了 G2 闸门——用户输入"1"确认。
但问题在于:G2 出现时,S5 的终报已经写完了。 用户确认的是"已生成的报告”,而不是"该不该进入 S5"的决策。
# 第 4 轮:G2 终于出现,但时序不对
wait_for_user_confirm "请选择:1=确认进入S5 2=修改 3=中止"
# 用户输入"1"
# 但此时 S5 终报已经写盘了!
# 用户确认的是"已生成的报告",不是"该不该进入 S5"[ILLUSTRATION: G2 闸门时序图,展示 S5 写盘发生在 G2 确认之前,箭头标注"用户确认的是已生成的结果,不是决策点"]
4 轮对比
| 轮次 | 时间 | 触发原因 | G1 出现 | G2 出现 | 是否自动进入 S5 | 用户行为 |
|---|---|---|---|---|---|---|
| 第 1 轮 | 10:33 | 原始输入 | ❌ | ❌ | ✅ 已写盘 | 发现路径错误 |
| 第 2 轮 | 15:12 | P0 修复验证 | ❌ | ❌ | ✅ 已写盘 | 纠正约束条件 |
| 第 3 轮 | 15:29 | 再跑验证 | ❌ | ❌ | ✅ 已写盘 | 质疑流程逻辑 |
| 第 4 轮 | 18:14 | 全部修复 | ❌ | ✅ 但已写盘 | ✅ 已写盘 | 确认"已出报告" |
真正从 G1 到 S5 全自动通过:0 轮。
P0/P1 问题清单
已修复的 P0
| # | 问题 | 根因 | 修复方式 |
|---|---|---|---|
| 1 | 相对路径写错位置 | 相对路径被解析为 agent workspace | payload.input_root 显式传绝对路径 |
| 2 | orchestrator ack 正反馈循环 | agent 自动回复确认消息 → 触发更多 spawn | /silent on + 释放 agent 资源 |
| 3 | 同 agentId 多 session 并行 spawn | 多次 spawn 同 agent 导致冲突 | spawn 前 kill 多余 session + orchestrator singleton |
| 4 | S2 agent 不写盘 | 没有强制写盘指令 | MUST write() 工具关键字硬性约束 |
已修复的 P1
| # | 问题 | 修复方式 |
|---|---|---|
| 5 | scout 通过 send 模式上报不写盘 | 改用单独 agent 完成 S1 并强制写盘 |
| 6 | 网络超时需人工重试 | orchestrator retry_once on spawn failure |
| 7 | 用户约束变化传递 | G1 前锁定约束时间戳 |
结构性缺陷(仍未修复)
| # | 问题 | 根因 | 频率 |
|---|---|---|---|
| 10 | G2 闸门被跳过 | 入口 agent 在 S4 完成后自动进入 S5,prompt 没有强制 wait_for_user | 4/4 (100%) |
| 11 | G1 确认被静默绕过 | S0 落盘后未被强制暂停,被自动推进到 S1 | 4/4 (100%) |
根因分析:Agent 是 completion-driven,不是 gate-driven
架构师分析了这个问题的根本原因:
Agent 是 completion-driven,不是 gate-driven。 不管 prompt 写多少遍"等用户确认",LLM 的完成张力都会把它推着往下跑。写了 4 次、修了 4 次、跑了 4 次——G1/G2 始终被跳过。
这不是 prompt 能解决的问题,是 LLM 本身的行为模式。在长流程中,LLM 天然倾向于"完成当前任务后继续下一步",而不是"完成当前任务后停下来等外部指令"。
修复方案:A/B/C 三个选项
| 选项 | 内容 | 代价 |
|---|---|---|
| A | Gateway 层加硬检查点:S0/S4 完成后自动冻结,必须外部触发才继续 | 需要改 Gateway 架构,复杂度最高 |
| B | 接受 gate 会被跳过,跑完后手动审查输出(gate 变成"建议暂停"而非"强制暂停") | 快,但用户得自己盯 |
| C | 重设计流程:把 gate 从"agent 自觉暂停"改成"orchestrator 自动阻断"(orchestrator 收到 S4 done 后只写文件、不发消息、不 spawn S5,等外部指令) | 中等,但需要 orchestrator 协议层改动 |
经验教训
- 不要依赖 LLM 自觉暂停。 在长流程中,LLM 会被 completion 张力推着往下跑,写在 prompt 里的"等用户确认"会被静默绕过。
- 人工闸门必须在系统层实现。 如果 gate 需要强制暂停,必须在 gateway 层或 orchestrator 协议层实现,不能在 agent prompt 层。
- 修复路径问题后,检查更深层的结构缺陷。 前 3 轮复盘只修复了"怎么让 agent 跑起来"的问题,但忽略了"agent 不该在没被允许时继续跑"的问题。
- 用户的重启都是被迫的。 4 轮重跑中,没有一次是用户想换方向——全部是流程 bug 导致的强制重启。
- 三处必须同时对齐。 修复这类问题需要 gateway 层 + agent prompt + orchestrator contract 三处同时修改,单独改一处无效。
参考来源
–全文完–

梦行志
