Claude Code 卡在循环里:6 种 loop 签名 + 各自的一句话破解

Agent 反复同样 edit、来回切换两个文件、永远追 flaky 测试——6 种 loop 签名各有诊断和 one-prompt 破法。

Claude Code 第 8 次跑 pnpm test。每次:改同一行 expect(...).toBe(...)、重跑、又挂、回退。或者它在「修 auth bug」的两种解读间反复横跳——修 OAuth 挂 magic-link、修 magic-link 挂 OAuth。Token 烧着、进度条不动。Agent 进了循环。

95% 的 loop 不是「模型不行」——是反馈环坏了:flaky 测试、prompt 没约束、context 污染、工具失败没 flag。修法不是更强模型,是 30 秒内识别 loop 签名、用一句话约束打破。下面 6 种 loop 形态和各自的一句话约束。

常见原因

按命中率从高到低:

1. flaky 测试——过 / 挂 / 过 / 挂

最常见触发。测试用 Date.now()、网络调用、随机、snapshot 时间戳——同代码一次过一次挂。Agent 看到红 → 改 → 绿 → 重跑红 → 回退 → 绿 → 改 → 红,永远。

如何判断:停 agent。你自己不改代码跑 3 次同命令。能复现绿红绿——测试是问题。

2. 模糊 prompt——agent 在两种解读间漂

「修 login bug」——但你有 OAuth 和 magic-link。Agent 修 OAuth,magic-link 测挂;切 magic-link,OAuth 测挂——在互斥的两种解读间反复跳。

如何判断:看最近 5 个 diff——动了两个不同 feature 的两个不同文件、每个新 edit 撤上一个——prompt 没约束住。

3. Plan 错了 agent 拒绝 replan

agent 锁定「改 schema → 改 API → 改 UI」。Step 1 不可能(表有数据,列删不掉)——agent 死磕 step 1 反复重写 migration,而不是 replan。

如何判断:问「你当前 plan 是什么?现在第几步?」——5+ 轮都说”还在 step 1”,强制 replan。

4. context 被旧 error 塞满

长 session 80% context 是过期”上次失败”日志——agent 在拟合不再反映现状的旧 error。

如何判断:开新 session、贴当前代码、重述目标——第一次就成——是 context 污染。

5. Agent 在 mock 和实 implementation 间漂

写 mock 让测试过,下轮觉得 mock 不真实改实 impl,原测试挂,回 mock——loop。

如何判断:跨次 diff 里搜 jest.mock / vi.mock / MagicMock 被加被删。

6. 工具失败 agent 没察觉

Bash exit code 非 0。Agent 把 stdout 当成功,又跑同命令——loop 因为”失败信号”它看不见。

如何判断:看最近 3 个工具调用的 exit code——非 0 但 Claude 没说”命令失败”——它漏了。

最短修复路径

按收益从高到低。Step 1 + 2 在一分钟内打破大多数 loop。

Step 1:停 agent,让它列最近 10 个动作

按 Esc / Stop。然后问:

列最近 10 个动作(文件路径 + edit 总结 + 命令 + exit code)。
不要评论,只表格。

90% 时候你会看到两个文件交替、同一行反复改、或测试反复跑没代码进展——pattern 揭示 loop 签名。

Step 2:按签名套约束句

匹配 loop 类型和约束 prompt:

Loop 类型约束 prompt
反复改测试期望「不要动测试。测试是对的——改 implementation 匹配它。」
反复加/删 mock「保留真实现,删所有 mock,跑集成测试。」
反复改 migration「schema 冻结,重新 plan 只动 UI 层。」
来回两个文件「只允许动 src/auth/login.ts,其他全只读。」
同一 flaky 测试反复挂「停跑这个测试,mock 时间依赖,继续。」
重跑失败命令「上条命令 exit 非 0。读 error,不要盲重跑。」

Step 3:flaky 测试先稳

不要让 agent 在 flaky 信号上 loop——先稳:

# 跑 5 次看稳不稳
for i in {1..5}; do pnpm test -- --testNamePattern="login flow"; done

2+ 次挂就 mock 不确定性源:

// vitest setup
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-01-01'));

然后让 agent 在稳定的测试上继续。

Step 4:开新 session 用全 context

上面都不行——最后杠杆是 context reset:

1. 复制当前文件内容(不是 diff)。
2. 新 session。
3. 重启:
   目标:[一句话]
   当前代码:[贴整文件]
   失败测试/错误:[原样贴]
   约束:不动测试,只动 src/X.ts。
   先打 plan,等批准再 edit。

新 context 不被旧失败日志污染,通常一次过。

Step 5:设迭代上限

防下个 loop。CLAUDE.md 加:

## Agent 行为约束

- 每任务最多 5 次 build/test 迭代
- 3 次失败后停下汇报
- 同一文件同一块不要 edit 超过 3 次
- 任何工具调用重试 3 次后停下来问

Cursor 用 .cursorrules、Codex 用 AGENTS.md——同理。

Step 6:卡 plan 时强制 replan

agent 永远 step 1:

停。当前 plan 不行。不要继续。
打印:
1. 为什么 step 1 不行
2. 两个替代方案
3. 推荐一个

等我批准再继续。

强制 agent 跳出失败 plan,不是在上面磨。

预防建议

  • CLAUDE.md 设迭代上限——loop 有内建出口
  • flaky 测试隔离到 flaky.test.ts——agent 永不在不稳信号上迭代
  • 同步骤 3 次连失败强制 replan
  • 显式完成标准——不要”修 login”而是「pnpm test -- auth exit 0」
  • 看 agent 的动作 trace 不只看最终输出——loop 在 trace 里
  • loop 出现时开新 session,不要救污染的

相关阅读

标签: #排查 #Claude Code #排查 #Agent 死循环