2026/10/8 20:53:39

Loop Engineering实战:用Claude Code与Codex搭建自动修Bug回路

Loop Engineering实战:用Claude Code与Codex搭建自动修Bug回路 1. 从“写提示词”到“搭回路”Loop Engineering 到底在解决什么问题如果你最近在 AI 编程圈里混大概率已经被两个词刷屏了一个是 Harness Engineering另一个就是 Loop Engineering。前者讲的是怎么给模型搭一套“马具”让它跑得稳、不跑偏后者讲的是怎么设计一个“回路”让模型能自己迭代、自己纠错、自己往前推进。这两个词听起来玄乎但落到实操上其实都是被同一个痛点逼出来的——单次对话搞不定复杂任务。我最早用 Claude Code 和 Codex 的时候习惯是打开终端敲一句需求等它吐代码然后手动复制、手动测试、手动把报错贴回去。这个流程在改一个小函数的时候还行一旦任务变成“给这个项目加一套完整的用户鉴权模块”问题就来了模型第一轮生成的代码可能缺依赖第二轮补依赖的时候又把配置文件改坏了第三轮修配置的时候忘了前面已经改过的路由。你来回贴几次报错上下文就爆了模型开始胡言乱语最后你只能自己上手重写。Loop Engineering 要解决的就是这个。它的核心思路不是让模型一次做对而是设计一个可循环的执行结构让模型执行一步、拿到反馈、根据反馈调整、再执行下一步直到任务完成或者触发退出条件。这个“反馈”可以来自编译器、测试用例、lint 工具也可以来自另一个模型的审查。关键在于这个回路是自动闭合的不需要你每次手动把结果喂回去。我拿一个真实场景举例。之前我要给一个 Node.js 项目批量升级依赖并修复所有 breaking change。手动做的话大概要改十几个文件每个文件改完都要跑一遍测试。用 Loop Engineering 的思路我搭了一个回路第一步让 Claude Code 读取 package.json 和 lock 文件列出所有需要升级的包第二步让它逐个升级并修改调用代码第三步跑测试第四步如果测试失败把失败信息喂回给模型让它只修失败的那部分第五步重复第三步和第四步直到测试全绿或者重试超过五次。整个流程跑下来我只需要在最后 review 一遍 diff中间几乎不用干预。这套东西适合谁如果你只是偶尔用 AI 补全几行代码那 Loop Engineering 对你来说可能有点重。但如果你在用 Claude Code、Codex、Cursor 这类工具做完整的项目开发或者你在搭自己的 AI 编程工作流那这套思路能帮你把“能用”变成“好用”。它不要求你会写复杂的框架代码但要求你理解模型的能力边界知道什么时候该让它自己跑什么时候该把它拉回来。接下来我会从工具选型、回路设计、实战搭建、踩坑排查这几个角度把 Loop Engineering 拆开讲清楚。中间会穿插 Claude Code、Codex、Cursor 的具体配置和命令也会讲清楚 Harness Engineering 和 Loop Engineering 的关系。你不需要全部照搬但至少能拿走一套可以改吧改吧就用起来的方法。2. 工具链选型Claude Code、Codex、Cursor 在回路里各站什么位置搭回路之前得先想清楚用哪些工具。现在市面上能参与 AI 编程回路的工具不少但真正适合做“回路节点”的其实就那么几个。我自己的组合是 Claude Code 做主力执行器Codex 做代码审查和补全Cursor 做交互式调试和快速修改。这三个工具在回路里的角色不一样不能混着用。2.1 Claude Code回路里的“主执行器”Claude Code 最大的优势是它能直接在你的终端里跑命令、读文件、写文件而且支持多轮工具调用。这意味着你可以把它当成回路里的“手”和“脚”——让它执行具体的操作比如安装依赖、运行测试、修改代码。它的工具调用机制允许你在一个会话里连续执行多个步骤不需要每次重新描述上下文。安装 Claude Code 的方式取决于你的系统。在 macOS 或者 Linux 上官方推荐用 npm 全局安装npm install -g anthropic-ai/claude-codeWindows 用户如果不想折腾 WSL可以直接下载桌面版安装包。安装完之后在项目根目录运行claude就能启动。第一次启动会让你登录登录完之后它会读取当前目录的文件结构建立上下文。Claude Code 在回路里的典型用法是这样的你给它一个任务描述它会自己决定先读哪些文件、执行哪些命令。比如你说“把这个项目的测试跑通”它会先找 package.json 看测试命令是什么然后执行拿到报错后自己分析再改代码再跑。这个“自己决定”的能力就是它能做回路主执行器的原因。但要注意Claude Code 的自动执行能力是有边界的。它默认不会执行破坏性操作比如删除文件或者强制推送。如果你需要它执行这类操作得在配置里显式允许。另外它的上下文窗口虽然大但也不是无限的。回路跑太多轮之后上下文会被历史记录塞满这时候你需要手动清理或者开新会话。2.2 Codex回路里的“审查者”和“补全器”Codex 在回路里的角色和 Claude Code 不太一样。它更擅长做代码生成和审查而不是执行系统命令。我通常用它来做两件事一是让它在 Claude Code 改完代码之后做一轮 review看看有没有明显的逻辑错误或者风格问题二是在回路卡住的时候让它从另一个角度给出修改建议。Codex 的安装方式取决于你用的是哪个版本。如果你用的是 OpenAI 的 Codex CLI可以通过 npm 安装npm install -g openai/codex安装完之后你需要配置 API key。Codex 的配置文件通常放在~/.codex/config.json里面可以设置模型、温度、最大 token 数这些参数。如果你在国内网络环境下使用可能会遇到连接不稳定的情况这时候可以配置代理或者使用兼容的 API 端点。但具体怎么配得看你用的服务商支持什么方式。Codex 在回路里的接入方式比较灵活。你可以让 Claude Code 在改完代码后把 diff 输出到一个临时文件然后调用 Codex 对这个文件做审查。Codex 返回的审查意见再喂回给 Claude Code让它根据意见做下一轮修改。这样就形成了一个“执行-审查-修正”的闭环。不过 Codex 有个问题它的响应速度有时候不太稳定。如果你在回路里把它当成关键节点最好设置一个超时机制避免它卡住导致整个回路停摆。我的做法是给 Codex 的调用加一个 30 秒的超时超时就直接跳过审查步骤让 Claude Code 继续往下跑。2.3 Cursor回路里的“交互式调试台”Cursor 和前面两个工具不太一样它是一个完整的 IDE而不是命令行工具。它的优势在于交互式调试——你可以在编辑器里直接看到模型生成的代码手动改几行然后再让模型继续。在回路里Cursor 通常不参与自动循环而是作为“人工干预点”存在。Cursor 的设置里有一个很实用的功能中文回复。如果你习惯用中文描述需求可以在设置里把语言改成中文。具体路径是打开设置搜索 “language”找到 “Cursor: Language” 选项改成 “zh-cn”。这样模型在回复你的时候会用中文减少理解成本。注册 Cursor 的时候如果你没有海外手机号可以用邮箱注册不一定非要填手机号。免费额度方面Cursor 每个月会给一定的免费请求次数具体数额会变但足够你试用一段时间。在回路里Cursor 的典型用法是当自动回路跑完一轮之后你在 Cursor 里打开 diff快速扫一眼哪些改对了、哪些改错了。如果发现某处改得不对你可以直接在编辑器里手动修正然后把修正后的代码作为下一轮的输入。这个“人工检查点”在回路初期特别重要因为模型在前几轮很容易跑偏你需要及时把它拉回来。2.4 三个工具的协作方式把这三个工具串起来一个典型的回路是这样的Claude Code 读取任务描述执行第一步操作比如修改某个文件。Claude Code 运行测试拿到结果。如果测试失败Claude Code 把失败信息和当前 diff 写到临时文件。调用 Codex 审查 diff返回审查意见。Claude Code 根据审查意见修改代码回到第 2 步。如果连续三轮测试都失败暂停回路在 Cursor 里人工检查。这个流程不需要你写复杂的编排代码用 shell 脚本就能串起来。关键是每个工具的职责要清晰Claude Code 负责执行Codex 负责审查Cursor 负责人工干预。不要让一个工具干所有事那样回路会变得很脆弱。3. 回路设计的核心原则什么时候该循环什么时候该停搭回路最容易犯的错误就是让它无限循环下去。模型有时候会陷入“改一个错、引入两个新错”的死循环如果你不设退出条件它能跑一晚上第二天你打开终端发现它把项目改得面目全非。所以回路设计的第一个原则就是每个回路必须有明确的退出条件。3.1 退出条件的三种类型我一般把退出条件分成三类成功退出、失败退出、超时退出。成功退出最好理解测试全绿、lint 无报错、构建成功。这个条件要尽量具体不能是“代码看起来没问题”这种模糊判断。比如你可以让回路在npm test返回 0 的时候退出或者在tsc --noEmit没有输出的时候退出。失败退出是指回路跑了 N 轮之后仍然没有达到成功条件这时候应该停下来把当前状态保存下来让人来看。N 的取值取决于任务复杂度简单的重构任务 3 到 5 轮就够了复杂的模块开发可以放到 10 轮。但不要超过 10 轮因为超过 10 轮之后模型的上下文里全是失败记录它很难再做出有效修改。超时退出是兜底机制。有时候模型会卡在某个工具调用上比如等一个永远不返回的网络请求。这时候需要一个硬性超时比如整个回路最多跑 30 分钟到了就强制退出。这个超时可以在 shell 脚本里用timeout命令实现也可以在 Claude Code 的配置里设置单次命令的超时时间。3.2 反馈信号的质量决定回路的效率回路能不能跑通很大程度上取决于你喂给模型的反馈信号质量。如果你只告诉它“测试失败了”它得自己去猜哪里失败了这个猜测过程会浪费很多轮。但如果你把完整的测试输出、错误堆栈、甚至相关文件的上下文都喂给它它就能直接定位问题。我的做法是在回路里加一个“反馈提取”步骤。比如测试失败后不直接把原始输出扔给模型而是先用 grep 提取出关键行npm test 21 | grep -A 5 FAIL\|Error\|Expected /tmp/feedback.txt然后把/tmp/feedback.txt的内容作为下一轮的输入。这样模型看到的不是几百行测试日志而是十几行关键错误信息定位效率会高很多。另一个技巧是给反馈加上“变更上下文”。模型在第二轮修改的时候往往忘了第一轮改了什么。你可以在反馈里附上当前 diffgit diff /tmp/current_diff.txt然后把 diff 和错误信息一起喂给它。这样它就知道自己上一轮改了什么避免重复修改或者改错地方。3.3 回路的粒度控制大任务拆小回路一个常见的误区是把整个大任务塞进一个回路里跑。比如“给项目加一套完整的用户系统”这个任务涉及数据库设计、API 开发、前端页面、测试用例一个回路跑下来模型很容易在中途迷失方向。更好的做法是把大任务拆成多个小回路每个回路只负责一个子任务。比如回路一设计数据库 schema 并生成 migration 文件。回路二实现用户注册和登录 API。回路三实现前端登录页面。回路四写集成测试并跑通。每个小回路有自己的退出条件跑完一个再跑下一个。这样即使某个回路失败了也不会影响其他部分。而且每个回路的上下文都比较干净模型不容易跑偏。拆回路的粒度怎么定我的经验是如果一个子任务的预期修改文件数超过 5 个或者预期代码行数超过 200 行就应该考虑再拆一层。当然这不是硬性标准具体还得看任务的性质。有些任务虽然文件多但改动都很机械这种可以放在一个回路里有些任务虽然只改一个文件但逻辑复杂这种也值得单独开一个回路。3.4 人工检查点的设置时机虽然 Loop Engineering 的目标是自动化但完全不设人工检查点的回路是很危险的。我的做法是在三个地方设检查点第一回路启动前。让模型先输出一个执行计划你确认没问题再让它开始跑。这个计划不需要很详细但至少要列出它打算改哪些文件、执行哪些命令。如果计划里有明显不合理的操作你可以提前拦下来。第二回路跑完一半轮次的时候。比如你设了 6 轮上限那在第 3 轮结束后暂停一下看看当前 diff 有没有跑偏。如果发现它改的方向不对及时调整任务描述或者直接手动修正。第三回路失败退出后。这时候不要急着重新跑先看看它卡在哪里。有时候只需要手动改一行代码回路就能继续跑通有时候需要调整任务描述让它换个思路。这三个检查点不需要你全程盯着但至少要在回路跑完之后看一眼日志。我一般会把回路的每轮输出都写到日志文件里跑完之后用tail -f快速扫一遍看看有没有异常。4. 实战用 Claude Code Codex 搭一个自动修 bug 的回路前面讲了这么多原理现在来一个完整的实战。这个实战的目标是给一个 TypeScript 项目搭一个自动修 bug 的回路让它能自己跑测试、自己定位失败原因、自己修改代码直到测试全绿。4.1 环境准备和项目结构我用的测试项目是一个简单的 Express API里面有五六个路由和对应的单元测试。项目结构大概是这样的project/ ├── src/ │ ├── routes/ │ │ ├── user.ts │ │ └── order.ts │ └── index.ts ├── tests/ │ ├── user.test.ts │ └── order.test.ts ├── package.json └── tsconfig.json测试命令是npm test用的是 Jest。我先手动改坏了两个路由文件制造了几个测试失败然后让回路去修。Claude Code 的安装前面讲过了这里补充一点如果你在 Ubuntu 上配置 Claude Code可能会遇到 Node 版本的问题。Claude Code 要求 Node 18 以上如果你的系统默认 Node 版本太低可以用 nvm 切一下nvm install 20 nvm use 20Codex 这边你需要确保 API key 已经配好。如果你用的是兼容 OpenAI 接口的服务可以在~/.codex/config.json里改 base URL。配置文件大概长这样{ model: gpt-4, apiKey: your-api-key, baseUrl: https://your-api-endpoint/v1, maxTokens: 4096, temperature: 0.2 }温度设低一点因为修 bug 这种任务不需要创造力需要的是准确性。4.2 回路脚本的编写我用一个 shell 脚本把整个回路串起来。脚本的核心逻辑是跑测试如果失败就调用 Claude Code 修修完再跑测试循环直到成功或者达到上限。#!/bin/bash MAX_ROUNDS6 ROUND0 while [ $ROUND -lt $MAX_ROUNDS ]; do ROUND$((ROUND 1)) echo Round $ROUND # 跑测试 npm test /tmp/test_output.txt 21 TEST_RESULT$? if [ $TEST_RESULT -eq 0 ]; then echo All tests passed. Exiting. exit 0 fi # 提取失败信息 grep -A 10 FAIL\|Error\|Expected /tmp/test_output.txt /tmp/feedback.txt # 生成当前 diff git diff /tmp/current_diff.txt # 调用 Claude Code 修复 claude --prompt 以下是测试失败信息和当前代码变更请修复代码使测试通过。只修改必要的部分不要重构无关代码。 失败信息 $(cat /tmp/feedback.txt) 当前变更 $(cat /tmp/current_diff.txt) /tmp/claude_output.txt 21 # 调用 Codex 审查 codex review --diff /tmp/current_diff.txt /tmp/codex_review.txt 21 # 如果 Codex 有审查意见喂回给 Claude Code if [ -s /tmp/codex_review.txt ]; then claude --prompt Codex 对上一轮修改有以下审查意见请根据意见调整 $(cat /tmp/codex_review.txt) /dev/null 21 fi done echo Max rounds reached. Manual intervention needed. exit 1这个脚本有几个关键点。第一每轮都重新跑测试而不是依赖上一轮的结果。第二反馈信息经过 grep 过滤只保留关键错误行。第三Codex 的审查是可选的如果它没有输出就跳过。第四达到最大轮次后退出不无限循环。4.3 跑通第一轮从失败到定位第一次跑这个脚本的时候Claude Code 在第一轮就定位到了问题。测试报错说user.ts里的getUserById函数返回了 undefined但测试期望返回一个对象。Claude Code 读了user.ts和对应的测试文件发现是数据库查询的 where 条件写错了把id写成了userId。它改了这一行然后跑测试通过了。但第二轮又出现了新的失败这次是order.ts里的一个类型错误。Claude Code 在修user.ts的时候不小心改了一个共享的类型定义导致order.ts编译不过。这时候 Codex 的审查就派上用场了它指出这个类型定义的修改会影响其他模块建议回滚这一处改动只在user.ts内部做类型断言。Claude Code 根据 Codex 的意见回滚了类型定义改用局部类型断言。第三轮测试全绿回路退出。整个过程跑了三轮耗时大概四分钟。4.4 回路跑不通时的排查思路不是每次回路都能这么顺利。我遇到过几种典型的卡住情况这里把排查思路分享一下。第一种情况模型反复改同一个地方但测试一直不过。这通常是因为反馈信息不够具体。比如测试报错说“expected 200 but got 404”模型可能以为是路由没注册反复改路由配置但实际问题是中间件顺序不对。这时候你需要把更完整的上下文喂给它比如把相关中间件的代码也贴进去。第二种情况模型改对了 A 测试但弄坏了 B 测试。这是因为模型没有全局视角它只盯着当前失败的测试。解决办法是在反馈里附上所有测试的结果而不只是失败的那个。让模型知道它的修改影响了哪些其他测试。第三种情况模型卡在某个工具调用上比如等一个不存在的命令。这时候检查一下你的环境里有没有装对应的工具。比如 Claude Code 可能会尝试用npx jest跑测试但你的项目里 jest 是本地安装的没有全局命令。你可以在任务描述里明确告诉它用npm test。第四种情况Codex 的审查意见和 Claude Code 的修改方向冲突。比如 Codex 说“不要用 any 类型”但 Claude Code 为了快速通过测试用了 any。这时候你需要决定听谁的。我的做法是如果任务对代码质量要求高就听 Codex 的如果只是快速修 bug就听 Claude Code 的。你可以在脚本里加一个开关来控制。4.5 回路跑通后的收尾工作回路跑通不代表任务结束。我一般会做三件事第一检查 diff看看有没有意外的修改。有时候模型会顺手改一些无关的代码比如格式化或者重命名变量这些改动虽然不影响测试但会让 review 变得困难。第二跑一遍完整的 CI 流程包括 lint、类型检查、构建确保没有遗漏。第三把回路的日志保存下来以后遇到类似问题可以翻出来看。日志的保存方式很简单在脚本开头加一行exec (tee /tmp/loop_log_$(date %Y%m%d_%H%M%S).txt) 21这样整个回路的输出都会同时写到终端和日志文件里。日志文件按时间戳命名方便以后查找。5. 那些文档里不会写的踩坑记录搭回路的过程中我踩过不少坑。有些坑是工具本身的限制有些是设计思路的问题。这里挑几个最有代表性的讲一下希望能帮你少走弯路。5.1 Claude Code 的上下文污染问题Claude Code 在一个会话里跑太多轮之后上下文会被历史记录塞满。这时候它的表现会明显下降开始重复之前的错误或者忘记任务目标。我遇到过最夸张的一次是跑到第八轮的时候它突然开始修改一个完全不相关的文件原因是那个文件在很早之前的某轮里被提到过。解决办法有两个一是控制单次会话的轮次不要超过 6 轮二是每轮结束后手动清理上下文或者开一个新的 Claude Code 会话只把当前状态传进去。我现在的做法是在脚本里每三轮就重启一次 Claude Code 会话把当前 diff 和失败信息作为新会话的输入。这样虽然麻烦一点但能保证模型的状态是干净的。5.2 Codex 审查的误报和漏报Codex 做代码审查的时候有时候会给出一些不太靠谱的意见。比如它会把正常的类型断言当成错误或者建议你改一个其实没问题的命名。这些误报如果直接喂给 Claude Code会让它做无意义的修改浪费轮次。我的处理方式是在 Codex 的审查意见后面加一个过滤步骤。具体做法是让 Claude Code 先判断 Codex 的意见是否合理如果它认为不合理就忽略这条意见。你可以在 prompt 里加一句“如果审查意见与当前任务无关或者明显错误请忽略它并说明理由。”这样 Claude Code 就有了自主判断的空间不会盲目听从 Codex。漏报的问题更麻烦。有时候 Codex 没看出问题但代码确实有 bug。这种情况只能靠测试来兜底。所以回路里测试环节不能省哪怕 Codex 说没问题也要跑一遍测试确认。5.3 测试环境的不稳定性如果你的测试依赖外部服务比如数据库或者 API回路跑起来会很痛苦。因为外部服务偶尔会超时或者返回意外结果导致测试失败但失败原因和代码无关。模型看到这种失败会一脸懵然后开始乱改代码。解决办法是在回路里区分“代码失败”和“环境失败”。你可以在测试命令后面加一个重试机制如果第一次失败等几秒再跑一次。如果第二次还是同样的失败才认为是代码问题。如果两次失败原因不一样就认为是环境问题跳过这一轮。npm test /tmp/test_output.txt 21 if [ $? -ne 0 ]; then sleep 5 npm test /tmp/test_output_retry.txt 21 if [ $? -ne 0 ]; then # 比较两次失败信息如果一致才认为是代码问题 if diff (grep FAIL /tmp/test_output.txt) (grep FAIL /tmp/test_output_retry.txt) /dev/null; then echo Consistent failure, treating as code issue. else echo Inconsistent failure, likely environment issue. Skipping round. continue fi fi fi这个逻辑虽然简单但能过滤掉大部分环境噪音。5.4 模型对“最小修改”的理解偏差我在 prompt 里反复强调“只修改必要的部分”但模型有时候还是会顺手改一些无关的东西。比如它会把let改成const或者调整 import 顺序。这些改动本身没问题但会让 diff 变得很大增加 review 成本。后来我发现与其在 prompt 里强调不如在脚本里加一个 diff 大小检查。如果某一轮的 diff 行数超过阈值比如 50 行就暂停回路让人工确认。这样能防止模型在修一个小 bug 的时候把整个文件重写一遍。DIFF_LINES$(git diff --stat | tail -1 | awk {print $4}) if [ $DIFF_LINES -gt 50 ]; then echo Diff too large ($DIFF_LINES lines). Pausing for manual review. exit 2 fi这个检查放在每轮修改之后、跑测试之前。如果 diff 太大直接退出让你来看。5.5 回路日志的可读性问题回路跑多了之后日志文件会变得很长。如果你不整理回头根本看不懂哪轮发生了什么。我的做法是在每轮日志里加一个分隔符和摘要比如echo Round $ROUND /tmp/loop_log.txt echo Test result: $TEST_RESULT /tmp/loop_log.txt echo Files changed: $(git diff --name-only | tr \n ) /tmp/loop_log.txt echo Diff lines: $DIFF_LINES /tmp/loop_log.txt这样你翻日志的时候一眼就能看到每轮改了哪些文件、测试结果如何。如果某一轮改的文件特别多或者测试结果异常就能快速定位到那一轮。6. 从单回路到多回路把 Loop Engineering 用在整个项目上单个修 bug 的回路跑通之后你可以把思路扩展到整个项目。我现在做新功能开发的时候会搭一套多回路系统每个回路负责一个阶段阶段之间通过文件或者 git 分支传递状态。6.1 多回路的分层设计我的多回路系统大概分三层规划层、执行层、验证层。规划层的回路负责把需求拆成任务列表。输入是一段需求描述输出是一个 markdown 格式的任务清单每个任务包含目标、涉及文件、验收标准。这个回路不需要跑代码只需要让模型读需求、读项目结构然后输出计划。我一般用 Claude Code 做这件事因为它的文件读取能力比较强。执行层的回路负责逐个完成任务清单里的任务。每个任务启动一个独立的回路跑完一个再跑下一个。执行层的回路就是前面讲的那种“修改-测试-修复”循环。每个任务跑完之后把结果写到一个状态文件里记录哪些任务完成了、哪些失败了。验证层的回路负责做集成测试和代码审查。所有执行层回路跑完之后启动验证层回路跑完整的测试套件调用 Codex 做整体审查检查有没有跨模块的问题。如果验证层发现问题把问题反馈给执行层让对应的回路重新跑。这三层回路可以用一个主脚本串起来也可以用 CI 工具比如 GitHub Actions来编排。我用的是 shell 脚本加 cron简单粗暴但够用。6.2 状态传递的几种方式多回路系统里状态传递是最容易出问题的地方。如果状态传丢了下一个回路就不知道上一个回路做了什么。我试过几种方式最后稳定下来的是“文件加 git 分支”的组合。每个回路跑完之后把状态写到一个 JSON 文件里{ task_id: task-001, status: completed, files_changed: [src/routes/user.ts], test_result: passed, timestamp: 2025-01-15T10:30:00Z }同时每个回路在独立的 git 分支上跑跑完之后合并回主分支。这样即使状态文件丢了也能从 git 历史里恢复。状态文件放在项目根目录的.loop/文件夹里不要提交到 git但也不要删。这样你随时可以查看每个回路的状态。6.3 回路之间的依赖处理有些任务之间有依赖关系比如“实现登录 API”必须在“设计用户表”之后做。处理依赖的方式有两种串行和并行。串行最简单任务 A 跑完再跑任务 B。缺点是慢但胜在稳定。我大部分时候用串行因为 AI 编程回路本身就不快再并行的话资源竞争会很严重。并行适合独立任务比如“实现用户 API”和“实现订单 API”可以同时跑。但并行的时候要注意文件冲突。如果两个回路同时改同一个文件合并的时候会打架。我的做法是在任务规划阶段就检查文件重叠如果有重叠就强制串行。6.4 多回路系统的监控和告警回路跑多了之后你需要一个地方看整体状态。我用的方案很简单一个静态 HTML 页面读取.loop/文件夹里的状态文件用表格展示每个任务的进度。这个页面不需要后端用 JavaScript 直接读文件就行。告警方面我设了两个触发条件一是某个回路失败退出二是某个回路跑了超过 30 分钟还没结束。触发的时候发一封邮件给自己或者往聊天工具里发一条消息。这样你不需要一直盯着终端有问题会主动通知你。6.5 多回路系统的成本控制多回路跑起来之后API 调用成本会上升。一个任务跑五六轮每轮调用一次 Claude Code 和一次 Codex一天跑十几个任务成本不小。控制成本的方式有几个一是限制每轮的 token 数不要让模型读太多无关文件二是复用会话不要每轮都开新会话三是设置每日预算上限到了就停。我在脚本里加了一个简单的预算检查DAILY_BUDGET10.00 CURRENT_COST$(cat /tmp/loop_cost.txt 2/dev/null || echo 0) if (( $(echo $CURRENT_COST $DAILY_BUDGET | bc -l) )); then echo Daily budget exceeded. Stopping. exit 3 fi每轮结束后把当轮的成本累加到/tmp/loop_cost.txt里。这个成本可以从 API 返回的 usage 字段里拿也可以粗略估算。虽然不精确但能防止意外超支。7. 一些关于 Loop Engineering 的常见误解最后聊几个我经常听到的误解这些误解如果不澄清很容易让人在搭回路的时候走错方向。7.1 误解一回路越自动越好很多人觉得 Loop Engineering 的目标就是完全自动化人最好一点都不用管。但实际上完全自动的回路在复杂任务上表现很差。模型需要人的判断来纠正方向尤其是在任务初期。我现在的做法是“半自动”回路自动跑但关键节点需要人确认。这样虽然慢一点但成功率更高。7.2 误解二回路能解决所有问题回路不是万能的。有些问题模型就是解决不了比如需要领域知识或者需要访问外部系统。这种时候你硬跑回路只会浪费时间和 API 额度。判断标准很简单如果模型在头两轮里没有找到方向那大概率它解决不了这个问题该人工介入就人工介入。7.3 误解三Harness Engineering 和 Loop Engineering 是一回事这两个词经常被混着用但它们说的不是一回事。Harness Engineering 关注的是怎么给模型搭一套稳定的运行环境包括工具调用、权限控制、错误处理。Loop Engineering 关注的是怎么设计执行循环包括任务拆分、反馈机制、退出条件。Harness 是基础设施Loop 是执行策略。两者配合使用效果最好但不能互相替代。7.4 误解四回路跑通了就一劳永逸回路跑通一次不代表以后都能跑通。项目结构变了、依赖升级了、模型更新了都可能让回路失效。我现在的习惯是每个月跑一次回归测试用一个固定的测试项目验证回路是否还能正常工作。如果发现失效及时调整脚本和 prompt。7.5 误解五只有大项目才需要回路小项目也可以用回路只是回路的粒度要更细。比如你只是改一个函数可以搭一个“改函数-跑单元测试-修复”的小回路跑一两轮就结束。回路的本质是“让模型自己迭代”这个思路和项目大小无关。小项目用回路反而能帮你快速验证回路设计是否合理。8. 回路跑起来之后我实际感受到的变化搭这套东西之前我用 AI 编程的方式是“问一句、改一句、跑一次”。搭完之后变成了“描述任务、等回路跑完、review 结果”。这个转变带来的最大变化不是速度而是注意力的释放。以前我改一个模块注意力要一直挂在终端上随时准备把报错贴回去。现在我可以把回路跑起来去干别的事回来再看结果。当然回路不是银弹。它跑得慢有时候会卡住有时候会改错。但它的价值在于把重复的、机械的迭代工作交给模型让人专注于判断和决策。这个分工我觉得是合理的。模型擅长快速试错人擅长判断方向。回路就是让这两者配合起来的桥梁。如果你刚开始接触 Loop Engineering我的建议是从一个小回路开始比如“自动修 lint 错误”或者“自动补单元测试”。跑通之后再逐步扩大范围。不要一上来就搭多回路系统那样很容易被复杂度劝退。先让一个回路稳定跑起来再考虑加第二个、第三个。另外不要迷信工具。Claude Code、Codex、Cursor 都只是工具它们会更新、会变化、会有 bug。回路的核心是你的设计思路怎么拆任务、怎么给反馈、怎么设退出条件。这些思路是工具无关的换一个工具照样能用。把思路搞清楚比把某个工具用熟更重要。