典型的”agent 死循环”长这样:Claude Code 或 Cursor agent 跑了 12 轮 npm test,每轮都改同一处 expect(...).toBe(...)、跑、失败、再改回去;或者 Aider 在 git diff 和 git restore 之间来回横跳。屏幕上 token 一直在烧,进度条没动。
最快的修法(不到一分钟):先把 agent 停下来(Claude Code 按 Esc,Cursor 或 Codex 点停止按钮)。让它把最近 10 步动作列成一张表,然后发一句约束,明确说清楚不要碰什么、下一步只做哪一件事——比如 Don't touch the test. The test is correct — change the implementation to match.(不要动测试,测试是对的,去改实现让它符合测试)。这一句话就能打破大多数循环。
大多数时候,模型并不是”不会修”,而是陷进了一个反馈坏掉的小闭环:测试 flaky、约束不够、或它读到的上下文和磁盘上的代码已经对不上了。这篇讲怎么 30 秒内识别循环、怎么用一句话打破它,以及怎么从一开始就预防。
先判断你属于哪一类
| 动作轨迹里的现象 | 最可能的原因 | 对应修法 |
|---|---|---|
| 不动代码,同一测试也会绿-红-绿 | 测试 flaky | Step 3 |
| 改动在两个不相关文件之间横跳 | Prompt 有歧义 | Step 2 |
| 同一计划步骤卡了 5 轮以上 | 计划错了但不肯重新规划 | Step 2 |
| 长会话里反复”修”已经修好的错误 | 上下文被旧 log 塞满 | Step 4 |
mock / stub 反复被加上又删掉 | mock 和真实实现来回打转 | Step 2 |
| 重跑一条已经失败过的命令 | 工具失败但 agent 没识别到 | Step 1 |
| 同一处改动反复套用,文件里出现重复代码块(Cursor) | 编辑器以为改动失败了 | 见下方 Cursor 说明 |
常见原因
按命中率从高到低排序。
1. 它一直跑的测试本身是 flaky
最常见的循环触发器:测试里有时间戳、随机数、网络请求或 Date.now(),导致同样的代码每次跑结果不一样。Agent 看到红,改一处;变绿;下一轮又红——它以为是自己改坏了,于是回滚——又绿——再改——又红。
Run 1: pass
Run 2: fail (snapshot mismatch — timestamp drift)
Run 3: pass (after agent "reverted")
Run 4: fail
如何判断:把 agent 停下来,你自己手动连跑 3 次同一条命令。如果不动代码也能复现”绿-红-绿”,问题就在测试,不在 agent。
2. Prompt 有歧义,agent 在两种解读之间反复横跳
你说”修复登录 bug”,但代码里有 OAuth 和 magic link 两条路径。Agent 改完 OAuth 看到 magic link 测试挂,转头改 magic link,OAuth 又挂——它在两个互斥目标之间反复横跳。
如何判断:看 agent 最近 5 步动作的 diff,如果改的是两个不同文件的不同函数,并且每次改完都”撤销上一次”,就是 prompt 太宽。
3. 计划写错了但 agent 不肯重新规划
Agent 一开始写了个”先改 schema,再改 API,最后改 UI”的计划。Schema 那步其实走不通(比如数据库已经有数据),但 agent 死守计划,只在 schema 这一步反复改 migration 文件,不肯回头重新规划。
如何判断:让 agent 输出当前 plan + 现在卡在第几步。如果它说”还在 step 2”超过 5 轮,就该手动让它重新规划。
4. 上下文窗口被旧错误塞满,agent 看不到全局
Claude Code 或 Codex 在长会话里,上下文里大部分都是”上一次失败”的 log,agent 一直在拟合那些旧错误,看不到当前代码已经变了。Claude Code 在接近上下文上限时会自动 compact,但在一个反复磨的任务上,那份摘要仍可能把错误的假设带下去。
如何判断:开个新会话,把当前代码贴进去,重新描述目标。如果新会话一次就改对了,就是上下文污染。
5. Agent 在 mock 和真实实现之间打转
它写了一个 mock 让测试过,下一轮发现 mock 不真实,去改真实实现,结果原来的测试又挂,于是回去改 mock——循环。
如何判断:搜 diff 里有没有 jest.mock、vi.mock、MagicMock、sinon.stub 反复出现。
6. 工具调用失败但 agent 没意识到
Bash 工具返回了非零 exit code,但 agent 把它当 stdout 解析,以为命令”成功了只是输出不对”,于是再跑一遍。Cursor 的 Agent mode 有一个已知的变种:它套用了一次改动,但负责 apply 的模型报告这次编辑失败,于是 agent 重试——有时会把同一段代码粘两遍,留下重复代码。
如何判断:看最近 3 次工具调用的 exit code,如果都是非 0 但 agent 没在 chat 里提”命令失败了”,就是它没识别到失败。在 Cursor 里,打开它正在改的那个文件,看有没有重复的函数或 import。
最短修复路径
按收益排序。前两步通常 60 秒内就能打破循环。
Step 1:立刻停下,回看最近 10 步动作
按 Esc(Claude Code)或点停止按钮(Cursor / Codex)。在 Codex CLI 里,后台命令可以用 Ctrl-C 中断,且会保留它的最终输出和 exit status。不要让它继续烧 token。然后在聊天里要它输出最近的动作总结:
列出你最近 10 步做了什么操作(文件路径 + 改动摘要 + 命令 + 结果)。
不要解释,只要表格。
90% 情况下你会立刻看到它在两个文件之间来回切,或在同一行反复改。
Step 2:用一句话约束打破循环
最有效的反循环 prompt 模板:
停。不要再改 X。
当前真实情况是 Y。
下一步只做一件事:Z。
不要碰其他文件。
具体例子:
| 循环类型 | 约束 prompt |
|---|---|
| 反复改测试期望值 | ”不要再动测试。测试是对的,去改实现让它符合测试。“ |
| 反复加 / 删 mock | ”保留真实实现。把 mock 全删了,跑集成测试看真实失败信息。“ |
| 反复改 schema migration | ”schema 不动。回到 step 1,从只改 UI 层开始。“ |
| 在两个文件之间横跳 | ”只允许编辑 src/auth/login.ts,其他文件全部只读。” |
如果 agent 已经改得一团乱,先把代码回滚到干净状态再继续。在 Claude Code 里,在空输入框上连按两次 Esc(或运行 /rewind)打开 checkpoint 菜单——Claude 在每次编辑前会自动建 checkpoint,你可以选 Restore code(只回滚代码)、Restore conversation(只回滚对话)或两者都回滚。注意 checkpoint 只记录通过 Claude 文件编辑工具做的改动;被 rm、mv 等 bash 命令改动的文件不会被记录,这类操作请用 git 找回。
Step 3:把测试或验证条件钉死
如果 agent 一直在追一个 flaky 测试,先把测试稳定下来再让它继续:
# 连跑 5 次同一个测试,看是否稳定
for i in {1..5}; do npm test -- --testNamePattern="login flow"; done
如果有 2 次失败,先 mock 时间 / 网络 / 随机源:
// vitest setup
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-01-01'));
测试稳定后再让 agent 继续修。
Step 4:开新会话,喂干净上下文
如果以上都不行,最后一招是 reset 上下文。在 Claude Code 里,做完全重启之前还有两个更省事的选项:
/clear清空当前会话的对话历史(你的CLAUDE.md和项目文件不受影响)。/compact把目前为止的对话总结成摘要、替换掉完整历史。你可以给它方向:/compact Focus on the failing auth test and the current implementation.
如果会话已经污染得太严重,就干脆重开:
- 复制当前文件的完整内容(不是 diff)。
- 开新会话。
- 用这个模板重新启动:
目标:[一句话目标]
当前代码(已经改过 N 轮):
[贴完整文件]
当前失败的测试 / 错误:
[贴完整错误]
约束:不要改测试,不要改配置,只允许改 src/X.ts。
先输出你的计划,等我批准再动手。
新会话不会被旧错误污染,往往一次就过。
Step 5:设硬性 iteration cap
让循环不要再发生。Claude Code 可以在 CLAUDE.md 里加:
## Agent 行为约束
- 单个任务最多 5 轮 build/test 迭代
- 第 3 轮还没过,主动停下输出现状让用户决策
- 不允许在同一个文件的同一段代码上反复改 ≥ 3 次
其他 agent 也是同样的思路,但各自读的文件已经变了——写错地方,你的规则就会悄悄不生效:
| Agent | 规则文件放哪里(截至 2026 年 6 月) | 别再用的旧名字 |
|---|---|---|
| Claude Code | CLAUDE.md(项目根目录) | — |
| Codex | AGENTS.md(从根目录往下读,离工作目录最近的那份优先) | — |
| Cursor | .cursor/rules/*.mdc(Project Rules) | .cursorrules 已废弃,且在 Agent mode 里会被直接忽略 |
| Aider | CONVENTIONS.md,用 aider --read CONVENTIONS.md 或在 .aider.conf.yml 里写 read: 加载 | .aiderrules 并不是 Aider 真正认的文件 |
怎么确认循环真的被打破了
别信”看起来好了”。走开之前先验证:
- 你自己把目标命令连跑两遍:两次都是同样的绿,说明反馈信号现在稳定了。
- 看 agent 最后一次的 diff,确认它只改了你允许的文件——没去碰你冻结的测试或配置。
- 在 Cursor 里,扫一遍被改的文件,看有没有重复的函数或 import(apply 循环 bug 会留下这些)。
- 让 agent 复述完成标准并确认已满足(比如”
npm test -- auth全过”),然后你再亲手把那条命令跑一遍。
预防建议
- 在对应 agent 的正确规则文件里设 iteration cap(见上面的表),比如”同一个测试连挂 3 次就停下问人”。
- 不只看 agent 最终输出,要看它的 reasoning / action trace,循环模式往往要看 trace 才发现。
- 把 flaky 测试隔离到单独的
flaky.test.ts,别让 agent 在不稳定的反馈下迭代。 - 长任务每 5 轮强制 agent 重新输出”当前 plan + 当前进展”,或者跑
/compact把上下文压瘦。 - 给 agent 明确的”完成标准”——不要说”修好登录”,要说”
npm test -- auth全过”。 - 出现循环就 reset 上下文(
/clear或开新会话),不要试图在污染的上下文里继续。 - 在 Cursor 里,如果 agent 卡在某一次编辑上死循环,关掉 Auto 模型选择、手动指定一个具体模型;还不行就复制 Request ID 上报。
常见问题
为什么 agent 总把自己改对的修法又撤回去? 几乎都是测试 flaky。修法是对的,但下一轮测试因为无关原因(时间戳、网络、随机种子)挂了,agent 把它读成”我把别的改坏了”,于是回滚。先按 Step 3 把测试稳定下来,再让它继续。
Claude Code 改乱了一堆,怎么撤回?
在空输入框上连按两次 Esc,或运行 /rewind,选一个 checkpoint,选 Restore code。checkpoint 在每次编辑前自动创建。它不覆盖被 bash 命令改动的文件,所以凡是 rm/mv 动过的,用 git 找回。
.cursorrules 还是约束 Cursor agent 的正确做法吗?
不是。截至 2026 年,单个 .cursorrules 文件已废弃,而且在 Agent mode 里会被直接忽略——而循环恰恰就发生在这个模式下。规则请改放到 .cursor/rules/*.mdc。
上下文满了,该用 /clear 还是 /compact?
想继续干同一个任务、只是想要更轻的历史,就用 /compact(可以加一句聚焦说明)。要切到一个不相关的任务、想要干净起点,就用 /clear。如果是单个任务被污染得很严重,最可靠的重置是开一个全新会话、把当前文件完整贴进去。
agent 说命令”成功了”但其实什么都没变,为什么? 多半是它把非零 exit code 误读成了正常输出。检查最近几次工具调用的 exit code。你自己把命令再跑一遍;如果确实失败,把真实错误贴回去,并明确告诉 agent 上一条命令失败了。
相关阅读
- AI 凭空引用了不存在的文件
- Cursor 没读到整个项目
- AI 提交前审查工作流
- Claude Code SEO 审计教程
- AI 依赖升级工作流
- AI 写出来 TypeScript 类型错误
- AI agent 把 .env 覆盖了怎么办
- AI 建议了过时依赖:3 个原因 + 修复路径
- Claude Code 不理解你的项目怎么办:让 agent 真正读懂代码的 7 个方法
- AI 加了一条绕过鉴权中间件的路由 —— 排查与修复
- AI 编造了根本不存在的 API 签名 —— 排查与修复
- AI 写的 SQL 把热点表锁了好几分钟 —— 排查与修复
- AI 无视 lint 报错继续用废弃语法 —— 排查与修复
- AI 在 pnpm / Yarn 项目里跑 npm 命令 —— 排查与修复
- AI 生成的迁移本地能跑、上生产就炸 —— 排查与修复