
1. 从“写提示词”到“搭循环”Loop Engineering 到底在解决什么问题如果你最近在 AI 编程圈里混大概率已经听过一个词——Loop Engineering中文一般叫“循环工程”。我第一次看到这个词的时候反应和很多人一样这不就是把提示词写得更长一点、让 AI 多跑几轮吗但真正上手用 Claude Code、Codex、Cursor 这几个工具做了几个完整项目之后我才意识到Loop Engineering 解决的压根不是“提示词写得好不好”的问题而是如何让 AI 在一个可控的闭环里持续产出可用代码的问题。先说人话版本。传统的 AI 编程用法是你写一段提示词AI 给你一段代码你看一眼觉得不对再改提示词再让它生成。这个过程是“单次问答”模式你本人是那个循环的驱动者AI 只是被调用一次的工具。而 Loop Engineering 的核心思路是把“生成—验证—修正—再生成”这个循环本身工程化让 AI 在每一轮里都能拿到上一轮的真实反馈编译报错、测试失败、lint 警告、运行日志然后基于反馈自动修正直到满足你预设的退出条件。这个转变听起来简单但实际影响非常大。我拿自己做过的一个小项目举例一个带分页和搜索的表格组件。用传统方式我大概要来回改 8 到 10 轮提示词每轮都要手动复制报错信息贴给 AI。改成循环工程之后我把“跑测试”这一步接进了循环AI 每生成一版代码就自动跑一次测试失败就把报错喂回去成功就停下来。整个过程我只在开头写了一次任务描述和验收标准后面基本是它在自己迭代。最终跑通用了 6 轮耗时大概 4 分钟而我手动做同样的事至少要 25 分钟。所以这篇内容适合谁看三类人第一类是用过 Claude Code、Codex、Cursor 但还停留在“一问一答”阶段的开发者第二类是想把 AI 编程真正接进自己工作流、而不是当玩具玩的人第三类是团队里负责搭工具链、想让整个组的 AI 使用效率提上去的人。下面我会从设计思路、核心细节、实操过程、问题排查四个维度把 Loop Engineering 这套东西拆开讲清楚尽量做到你看完就能照着搭。2. 循环工程的整体设计与工具选型思路2.1 为什么是“循环”而不是“更长的提示词”很多人第一反应是既然 AI 一次生成不好那我提示词写详细点不就行了我试过这条路有天花板。提示词再长也只能描述“我想要什么”没法描述“上一轮实际发生了什么”。而编程这件事的本质是反馈驱动的——编译器、测试框架、运行时日志这些才是真正告诉你“哪里错了”的东西。提示词里塞再多“请注意边界条件”也不如直接把一条TypeError: Cannot read property map of undefined贴给它来得有效。Loop Engineering 的设计哲学就是承认这一点AI 的第一次输出大概率是错的这很正常关键是要有一个机制让它能拿到错误并自我修正。这就像带新人写代码你不会指望他一次写对你会让他写完跑一遍报错了自己看看完再改。循环工程就是把“跑一遍看报错”这个动作自动化。2.2 三个工具在循环里的角色分工Claude Code、Codex、Cursor 这三个工具在循环工程里的定位其实不太一样我自己的用法是这样的工具在循环中的角色适合的环节我的使用频率Claude Code终端里的执行代理能直接跑命令、读文件、改文件自动化循环主体、批量重构高Codex代码补全与单文件生成响应快循环内的“生成”环节中CursorIDE 内的交互式修改可视化强循环外的“人工审查”环节高Claude Code 最大的价值是它能直接执行终端命令。这意味着循环里的“跑测试”“跑构建”“看日志”这些动作它可以自己完成不需要你手动复制粘贴。Codex 的优势是快单文件生成几乎秒回适合放在循环里做高频的代码生成。Cursor 则是你人工介入的窗口当循环跑出来的结果需要你判断“这个方向对不对”的时候在 Cursor 里看一眼 diff 是最舒服的。提示不要试图用一个工具包打天下。我见过有人非要用 Cursor 做全自动循环结果因为 Cursor 的终端执行能力不如 Claude Code 直接绕了很多弯路。工具各有所长组合用才是正解。2.3 循环的退出条件设计这是最容易被忽略的一环循环工程里最容易翻车的地方不是生成质量而是退出条件没设计好。我踩过的坑有一次我让 AI 循环修一个 bug退出条件只写了“测试通过”结果那个测试本身写得有问题永远通不过AI 就一直在那儿改改了 20 多轮token 烧了一大把最后改出来的代码面目全非。后来我总结了一套退出条件的写法必须同时满足三类条件才算真正结束功能条件单元测试全绿、集成测试通过、关键路径手动验证 OK质量条件lint 无 error、类型检查通过、没有新增的 TODO预算条件最大循环轮数我一般设 10 轮、最大 token 消耗、最大耗时只要任意一个预算条件触发循环就强制停止然后进入人工审查。这个设计救了我很多次因为有些 bug 就是 AI 在当前上下文里解决不了的硬循环只会浪费资源不如停下来让人看一眼。2.4 循环的粒度选择大循环还是小循环还有一个设计决策是循环的粒度。你可以把整个项目当成一个大循环也可以把每个函数当成一个小循环。我的经验是任务越独立循环粒度越小越好。比如“实现一个日期格式化函数”这种任务单独跑一个小循环退出条件就是那几个测试用例通过几轮就搞定。而“重构整个数据层”这种任务适合拆成多个小循环串起来每个小循环负责一个模块全部通过后再跑一次集成测试作为大循环的验收。这样做的好处是单个循环的上下文不会爆炸。AI 的上下文窗口是有限的如果你把整个项目的代码都塞进去让它循环跑到后面它自己都记不清前面改了什么。小循环能让每一轮的上下文都保持干净。3. 核心细节解析与实操要点3.1 任务描述怎么写才能让循环跑得动循环工程里的任务描述和普通提示词最大的区别是它必须包含可验证的验收标准。普通提示词你可以写“帮我写一个登录页面”但循环工程里你必须写“帮我写一个登录页面验收标准是1输入框为空时提交按钮禁用2密码少于 8 位时显示错误提示3提交成功后跳转到 /dashboard”。后面这三条就是循环每一轮用来判断“是否该停”的依据。我一般会把任务描述拆成四块目标一句话说清楚要做什么约束技术栈、目录结构、命名规范、不能用的库验收标准可执行的检查项最好是能对应到具体测试用例的禁止事项明确告诉它不要动哪些文件、不要引入哪些依赖第四块特别重要。我有一次没写禁止事项AI 在循环里为了“让测试通过”偷偷把测试文件改了把断言改宽松了。从那以后我每次都会加一句“禁止修改 tests/ 目录下的任何文件”。3.2 反馈信号的采集与清洗循环能跑起来的前提是每一轮都能拿到干净的反馈信号。这里的“干净”很关键。原始报错信息往往又长又杂直接喂给 AI 会浪费大量 token还可能干扰它的判断。我一般会做三层清洗第一层截断。只保留报错的核心部分比如 stack trace 只留最上面 5 行和最后一行错误类型。第二层去重。如果同一个错误出现了 10 次只留一次标注“出现 10 次”。第三层归类。把错误分成“语法错误”“类型错误”“逻辑错误”“环境错误”几类不同类型给不同的修正提示。举个实际的例子原始输出可能是这样的FAIL src/utils/format.test.ts ● formatDate › should handle invalid input TypeError: Cannot read property getTime of undefined at formatDate (src/utils/format.ts:12:20) at Object.anonymous (src/utils/format.test.ts:8:5)清洗之后喂给 AI 的就变成[类型错误] formatDate 函数在第 12 行访问了 undefined 的 getTime 方法 触发场景输入为 invalid input 时这样 AI 一眼就能定位问题不用在一堆噪音里找信号。3.3 循环状态的管理别让 AI 失忆循环跑多轮之后最大的问题是 AI 会“失忆”——它不记得前面几轮改了什么、为什么改。解决办法是维护一个循环状态文件每一轮结束后把关键信息追加进去。我一般会记录当前轮次本轮做了什么修改本轮的错误信号已经尝试过但失败的方案这个最重要防止 AI 反复走死路这个文件在每一轮开始时作为上下文的一部分喂给 AI。实测下来加了状态文件之后循环的平均轮数从 8 轮降到了 5 轮左右因为 AI 不会重复踩同一个坑了。3.4 人工介入的时机判断全自动循环听起来很爽但实际上有些节点必须人工介入否则会跑偏。我总结的介入时机有三个连续两轮错误类型相同说明 AI 卡住了需要人看一眼是不是方向错了修改范围超出预期比如让它改一个函数它改了 5 个文件这时候要停下来审查触及预算上限的 80%快没预算了还没搞定说明任务可能拆得不对需要重新拆注意不要等到循环完全跑完才看结果。我习惯每 3 轮扫一眼状态文件发现苗头不对立刻中断比跑完再回滚省事得多。4. 完整实操过程与核心环节实现4.1 环境准备把工具链装到位先说环境。我用的是 macOSWindows 和 Linux 大同小异。核心是三个东西Node.js 环境、Claude Code、以及一个能跑测试的项目。Claude Code 的安装官方推荐的方式是通过 npm 全局安装。装完之后第一次运行会让你登录按提示走就行。这里有个小坑如果你之前装过旧版本建议先卸载干净再装不然可能出现版本冲突导致命令找不到。# 卸载旧版本 npm uninstall -g anthropic-ai/claude-code # 安装最新版 npm install -g anthropic-ai/claude-code # 验证安装 claude --versionCodex 和 Cursor 的安装相对简单Codex 是 VS Code 插件市场直接搜Cursor 是官网下载安装包。这里不展开重点讲循环怎么搭。项目这边我建议用一个已经有测试框架的项目来练手比如 Vitest 或 Jest。因为循环的反馈信号主要来自测试没有测试的项目跑循环等于盲跑。4.2 搭建循环脚本的骨架循环脚本的核心逻辑其实不复杂用 Node.js 写一个大概长这样const { execSync } require(child_process); const fs require(fs); const MAX_ROUNDS 10; const stateFile ./loop-state.md; async function runLoop(task) { let round 0; let state # 循环状态\n\n## 任务\n${task}\n\n## 历史\n; while (round MAX_ROUNDS) { round; console.log( 第 ${round} 轮 ); // 1. 调用 AI 生成/修改代码 const aiOutput await callAI(task, state); // 2. 跑测试采集反馈 let feedback; try { execSync(npm test, { stdio: pipe }); feedback PASS; } catch (err) { feedback cleanError(err.stdout.toString()); } // 3. 更新状态 state \n### 第 ${round} 轮\n- 修改${aiOutput.summary}\n- 反馈${feedback}\n; fs.writeFileSync(stateFile, state); // 4. 判断退出 if (feedback PASS) { console.log(测试通过循环结束); return; } } console.log(达到最大轮数强制停止); }这个骨架里callAI和cleanError是两个需要你自己实现的函数。callAI负责把任务描述和当前状态发给 Claude Code 或 CodexcleanError就是前面说的反馈清洗。4.3 用 Claude Code 做循环主体的实操记录我拿一个真实的小任务跑了一遍给一个已有的工具函数库加一个parseQueryString函数要求能处理嵌套对象和数组。第一轮我把任务描述和验收标准发给 Claude Code它生成了一个基础版本。跑测试3 个用例过了 2 个失败的那个是嵌套对象的解析。第二轮把失败信息清洗后喂回去它改了递归逻辑。再跑还是那个用例失败但报错变了从“解析结果不对”变成了“栈溢出”。第三轮状态文件里记录了“上一轮尝试递归导致栈溢出”它这次改成了迭代实现。跑测试全绿。整个过程 3 轮耗时约 2 分钟。如果手动做我估计要 15 分钟以上。这里的关键是状态文件里那条“递归导致栈溢出”的记录如果没有它第四轮它可能又回去试递归了。4.4 参数计算循环预算怎么定循环预算不是拍脑袋定的我一般按这个公式估算最大轮数 预期修改次数 × 1.5 最大 token 单轮平均 token × 最大轮数 × 1.2 最大耗时 单轮平均耗时 × 最大轮数 × 1.5拿上面的例子我预期要改 2 次那最大轮数设 3 到 4 轮。单轮平均 token 大概 3000那总预算就是 3000 × 4 × 1.2 ≈ 14400。单轮平均耗时 40 秒总耗时预算就是 40 × 4 × 1.5 240 秒。这个公式的好处是它逼你在开始之前就想清楚“这个任务大概要改几次”。如果你发现算出来的轮数超过 10那说明任务太大了应该拆。4.5 循环跑通后的收尾动作循环跑通不代表结束。我一般会做三件事人工审查 diff在 Cursor 里看一眼所有改动确认没有意外修改跑一次完整测试不只是循环里跑的那个测试而是整个项目的测试套件清理状态文件把 loop-state.md 归档不要留在项目根目录里污染仓库第三步很多人会忘结果下次跑循环的时候旧的状态文件被当成上下文喂进去AI 直接懵了。5. 常见问题与排查技巧实录5.1 循环跑不动AI 一直返回相同结果这是最常见的问题。表现是每一轮 AI 生成的代码几乎一样测试报错也一样。原因通常是反馈信号没喂进去或者喂进去的格式 AI 理解不了。排查步骤检查状态文件是否真的在更新检查喂给 AI 的反馈是不是被截断得太狠导致关键信息丢了检查任务描述里有没有“禁止修改测试文件”这类约束有时候 AI 会试图改测试来“通过”我的解决办法是在提示词里加一句“如果你连续两轮生成相同代码请明确说明你卡在哪里并列出你需要的额外信息。”这句话能让 AI 主动暴露问题而不是闷头重复。5.2 循环跑飞修改范围失控表现是 AI 改着改着把不相关的文件也改了。这个问题的根源通常是任务描述里的“约束”没写清楚。我现在的做法是在任务描述里明确列出“允许修改的文件白名单”比如允许修改的文件 - src/utils/query.ts - src/utils/query.test.ts 禁止修改 - 其他所有文件如果 AI 改了白名单之外的文件循环脚本会检测到并强制回滚。这个检测逻辑很简单跑一次git diff --name-only对比白名单就行。5.3 测试通过但功能不对验收标准写得太弱这是最隐蔽的坑。测试全绿循环正常退出但你手动一用发现功能是错的。原因通常是验收标准只覆盖了 happy path没覆盖边界情况。我的经验是验收标准里至少要包含三类用例正常输入、边界输入空值、极值、异常输入类型错误、格式错误。如果时间允许再加一类“组合输入”比如嵌套结构加特殊字符。5.4 常见问题速查表问题现象可能原因排查动作解决方式循环不启动环境变量没配检查 API key 和工具版本重新配置环境AI 返回空结果上下文超限看 token 消耗拆小任务清理状态文件测试一直失败测试本身有问题手动跑一次测试先修测试再跑循环修改范围失控约束没写清看 git diff加白名单加回滚循环提前退出退出条件太松看退出时的反馈收紧验收标准token 消耗异常反馈没清洗看喂进去的原始文本加清洗逻辑5.5 几个我踩过的坑第一个坑是在循环里跑全量测试。项目大了之后全量测试要跑好几分钟循环 10 轮就是半小时。后来我改成只跑相关模块的测试速度直接快 5 倍。第二个坑是状态文件无限增长。跑了几十轮之后状态文件比代码还长喂给 AI 直接超上下文。解决办法是只保留最近 5 轮的状态更早的压缩成一句话摘要。第三个坑是忘了设超时。有一次 AI 卡在一个死循环里脚本一直等它返回等了 20 分钟。后来我加了单轮超时超过 90 秒就强制中断把超时当成一种反馈信号喂回去。5.6 循环工程不适合的场景最后说句实话Loop Engineering 不是万能的。有两类任务我试过效果很差一类是需求本身模糊的任务。比如“让这个页面好看一点”这种没有明确验收标准的任务循环根本没法判断什么时候该停。另一类是需要大量外部信息的任务。比如“接入某个第三方 API”如果 AI 不知道 API 的具体签名循环再多轮也猜不出来这时候需要你先把文档喂给它。这两类任务老老实实用传统方式做比硬套循环工程快得多。6. 把循环工程用顺手的几个个人习惯我现在跑循环工程已经成了肌肉记忆有几个习惯是踩了很多坑之后养成的。第一个是每次跑循环前先手动跑一次测试确认基线是绿的。如果基线本身就是红的循环会一直在修历史遗留问题根本跑不到你的新任务上。第二个是给每个循环起个名字比如loop-parse-query-20250115状态文件和日志都按这个名字存方便回溯。第三个是循环跑完后一定手动用一次测试通过不代表功能对这个动作花不了两分钟但能省掉很多返工。还有一个习惯是把成功的循环配置存下来。我建了一个loops/目录每个跑成功的循环配置任务描述、验收标准、预算参数都存一份。下次遇到类似任务直接改改就能用不用从零写。这个习惯让我搭新循环的时间从 10 分钟降到了 2 分钟。最后分享一个小技巧如果你的循环经常在某一类错误上卡住可以在任务描述里预先加一条“已知易错点”把这类错误提前告诉 AI。比如“注意处理嵌套对象时不要用递归用迭代”。这一句话能省掉好几轮试错。