
1. 从“写提示词”到“搭回路”Loop Engineering 到底在解决什么问题如果你最近在 AI 编程工具圈子里混大概率已经被两个词刷屏了一个是 Harness Engineering另一个就是 Loop Engineering。前者讲的是怎么给模型搭一套稳定的“外骨骼”——工具调用、上下文注入、权限控制、错误重试后者更狠它关心的是怎么让模型自己转起来一轮输出之后谁来评估结果评估完怎么把反馈喂回去喂回去之后怎么防止它原地打转或者越跑越偏这就是 Loop Engineering 要处理的核心命题。简单说Loop Engineering 是围绕“让 AI 编程代理自主完成多轮任务”而设计的一整套循环控制机制它包含任务拆解、执行、结果校验、反馈注入、终止判断这几个关键环节。你平时用 Claude Code、Codex、Cursor 这些工具时感受到的“它能自己改好几个文件、跑测试、再根据报错继续修”背后就是 Loop 在起作用。为什么现在必须聊这个因为大多数人用 AI 编程工具还停留在“一问一答”的阶段提个需求等它吐代码复制粘贴报错了再贴回去。这种用法下模型的能力被浪费了一大半。真正拉开效率差距的是你能不能设计一个闭环——让模型自己发现错误、自己修正、自己验证直到任务真正完成。Claude Code 的 agent 模式、Codex 的自主执行、Cursor 的 Composer 多文件编辑本质上都在往这个方向走。这篇内容适合三类人看第一类是把 Claude Code、Codex、Cursor 当日常主力工具但总觉得“它还不够自动”的开发者第二类是正在做 AI Agent 产品需要理解循环控制底层逻辑的工程师第三类是想搞明白“为什么同样的模型别人用起来就是比我顺”的进阶用户。我会从循环的基本结构讲起拆解 Claude Code 和 Codex 各自的 Loop 实现差异然后给出一套可以自己动手搭的最小循环框架最后把踩过的坑和调优经验一次性倒出来。提示Loop Engineering 不是某个具体工具的专利它是一种设计思路。你完全可以在自己的脚本里实现一套简化版循环效果未必比现成工具差。2. 一个能跑起来的 Loop 由哪几个零件组成2.1 循环的四个核心阶段执行、观察、判断、修正任何一套能稳定运行的 Loop拆到最底层都逃不出这四个阶段。执行是让模型根据当前上下文生成动作可能是写代码、改文件、跑命令观察是收集执行结果包括命令输出、文件变化、测试报告判断是评估当前状态离目标还有多远决定继续还是停止修正是把观察到的偏差转成新的上下文喂回给模型进入下一轮。听起来像废话但真正动手搭的时候90% 的问题都出在“观察”和“判断”这两个环节。很多人只做了执行和修正模型输出什么就信什么结果就是它在错误的路上越跑越远。举个真实场景你让 Claude Code 修一个 bug它改完代码后自己说“已修复”但你没让它跑测试它也没主动跑这个循环就是断的——缺少了客观的观察信号。所以一个合格的 Loop判断阶段必须依赖外部可验证的信号而不是模型自己的口头声明。测试通过率、编译是否成功、lint 有没有报错、类型检查是否干净这些才是靠谱的终止条件。模型说“我觉得好了”不算数。2.2 上下文窗口是循环的燃料也是循环的枷锁Loop 每转一圈都会往上下文里塞新东西上一轮的输出、命令结果、错误日志、你的新指令。问题是上下文窗口是有限的。Claude Code 默认给 agent 模式的上下文预算大概在 20 万 token 级别Codex 那边也类似。转个五六圈历史记录就能把窗口撑满。这时候就涉及一个关键设计每轮循环该保留什么、丢弃什么。我的经验是原始对话历史可以压缩但以下几类信息必须保留当前任务的目标描述、最近一次失败的具体报错、已经尝试过但没成功的方案摘要。前两个保证模型不跑偏第三个防止它重复踩同一个坑。Claude Code 在这方面做得比较聪明它会在上下文接近上限时自动做摘要压缩把早期轮次折叠成一段简短描述。Codex 的策略更偏向“每轮重新构建上下文”把关键状态存在外部文件里循环开始时再读回来。两种思路各有优劣后面会细说。2.3 终止条件设计什么时候该让循环停下来这是最容易被忽视、但出事最多的环节。终止条件设计不好要么循环提前退出任务没完成就停了要么无限打转模型反复改同一个地方。我一般会设三层终止条件。第一层是硬性成功条件测试全绿、编译通过、目标文件存在且内容符合预期。第二层是轮次上限比如最多 10 轮超过就强制停止并报告当前状态。第三层是收敛检测如果连续两轮的错误信息完全一样说明模型卡住了继续转也没意义直接停。注意轮次上限不要设太高。我见过有人设 50 轮结果模型在第 30 轮开始胡乱改代码把原本能跑的部分也搞坏了。10 到 15 轮是比较安全的区间。2.4 反馈信号的质量决定循环的上限同样是“测试失败”这个信号颗粒度差别巨大。粗糙的反馈是“测试没通过”模型只能瞎猜精细的反馈是“第 3 个测试用例断言失败期望值 42 实际得到 41出错位置在 calculate.py 第 87 行”模型基本能直接定位问题。所以如果你要自己搭 Loop在观察阶段多花点功夫做信号提取收益远超在提示词上雕花。把测试框架的输出解析成结构化信息把编译错误按文件和行号归类把 lint 警告按严重程度排序这些预处理能让模型的修正效率提升好几倍。3. Claude Code 与 Codex 的 Loop 实现差异拆解3.1 Claude Code 的 agent 循环边想边做工具调用密集Claude Code 的循环风格是“高频工具调用”。它每一轮倾向于做一个小动作——读一个文件、改几行代码、跑一条命令——然后立刻观察结果再决定下一步。这种设计的好处是反馈及时出错能马上发现代价是轮次多token 消耗快。它的循环控制逻辑大致是这样的模型输出一个工具调用请求Claude Code 执行后把结果塞回上下文模型看到结果继续输出下一个动作。整个过程对用户是透明的你只看到它在终端里刷刷地跑。关键点在于Claude Code 会在每轮之间自动注入当前工作目录的状态比如 git diff、文件树变化这让模型对“自己改了什么”有清晰认知。实测下来Claude Code 在重构类任务上表现特别好因为它能一边改一边看发现改错了立刻回滚。但在需要大量前置思考的任务上比如设计一个新模块的架构它容易陷入“改一点看一点”的局部最优缺乏全局规划。3.2 Codex 的循环策略先规划后执行状态外置Codex 走的是另一条路。它倾向于在循环开始前先做一轮规划把任务拆成步骤列表然后逐步执行。执行过程中它会把关键状态写到外部文件里比如一个.codex-state之类的临时文件每轮循环开始时重新读取。这种设计的好处是上下文压力小因为不需要把全部历史都塞在对话里而且规划阶段能通盘考虑不容易陷入局部最优。缺点是灵活性差一些如果执行到一半发现规划有问题调整起来比较别扭。Codex 的终止判断也更依赖显式条件。它不太会“感觉差不多了就停”而是严格检查预设的成功标准。这在自动化流水线里是优点在探索性任务里就显得有点死板。3.3 两者在错误恢复上的不同取舍遇到错误时Claude Code 的反应是“立刻重试换个方式再试一次”。它会快速尝试多种方案直到找到能跑通的。这种策略在简单错误上效率很高但遇到复杂错误时容易浪费轮次。Codex 遇到错误会先分析原因把错误分类然后决定是回滚到上一个稳定状态还是继续修补。它更愿意“停下来想一想”而不是盲目重试。这两种策略没有绝对优劣取决于任务类型。修 bug 这种需要快速试错的场景Claude Code 更顺手做系统迁移这种一步错步步错的场景Codex 的谨慎更有价值。对比维度Claude CodeCodex循环节奏高频小步边做边看先规划后执行步幅较大状态管理上下文内保留自动压缩外部文件存储每轮重读错误恢复快速重试多方案并行尝试分析归类谨慎回滚终止判断相对灵活依赖模型判断严格依赖预设条件适用场景重构、修 bug、探索性任务迁移、批量处理、流程化任务3.4 选型建议别问哪个好问哪个适合当前任务我自己的用法是混着来。日常改代码、修小 bug用 Claude Code它的快速循环很舒服。遇到需要动多个模块、有明确步骤的大任务切到 Codex让它先规划再动手。Cursor 的 Composer 介于两者之间多文件编辑体验好但循环控制不如前两者精细。如果你刚开始接触 Loop Engineering建议先从 Claude Code 的 agent 模式入手观察它是怎么一轮轮推进任务的。看多了自然就有感觉知道什么时候该干预、什么时候该放手让它跑。4. 手搭一套最小可用 Loop从零到跑通4.1 环境准备你需要哪些基础组件自己搭 Loop 不需要多复杂的设施。核心就三样一个能调用的模型接口、一个能执行命令的沙箱环境、一个记录状态的存储。模型接口用 Claude 或 GPT 的 API 都行沙箱用 Docker 容器最省心状态存储一个 JSON 文件就够。我建议先用 Python 写因为生态成熟调 API、跑子进程、解析输出都有现成库。整个框架控制在 200 行以内跑通了再往上加功能。别一上来就搞什么多 agent 协作、向量数据库那些是后面的事。# 最小循环框架的骨架 import subprocess import json from anthropic import Anthropic client Anthropic() state {round: 0, history: [], max_rounds: 10} def execute(action): 执行模型给出的动作返回观察结果 if action[type] run_command: result subprocess.run( action[command], shellTrue, capture_outputTrue, textTrue, timeout60 ) return {stdout: result.stdout, stderr: result.stderr, returncode: result.returncode} elif action[type] write_file: with open(action[path], w) as f: f.write(action[content]) return {status: written}这段代码就是循环的“执行”阶段。关键点是给命令执行设超时不然模型跑个死循环命令你的整个循环就卡死了。60 秒是个比较安全的默认值具体任务可以调。4.2 循环主逻辑把四个阶段串起来主循环的结构很直白构建提示词、调模型、解析动作、执行动作、收集结果、判断是否继续。每一轮开始前把当前状态和上一轮的结果拼进提示词里。def build_prompt(state, task): 构建当前轮的提示词 recent state[history][-3:] # 只保留最近三轮控制上下文 return f任务目标{task} 当前轮次{state[round]} 最近执行记录{json.dumps(recent, ensure_asciiFalse)} 请输出下一步动作格式为 JSON。 def should_stop(state, observation): 三层终止条件判断 if state[round] state[max_rounds]: return True, 达到轮次上限 if observation.get(returncode) 0 and ALL TESTS PASSED in observation.get(stdout, ): return True, 任务成功 # 收敛检测连续两轮错误相同 if len(state[history]) 2: last_two state[history][-2:] if last_two[0].get(stderr) last_two[1].get(stderr) ! : return True, 错误未收敛强制停止 return False, 这里有个细节值得说只保留最近三轮历史。我试过保留全部结果上下文膨胀得飞快而且早期无关信息会干扰模型判断。三轮是个经验值够模型理解当前处境又不会太臃肿。4.3 提示词模板怎么让模型稳定输出结构化动作模型输出格式不稳定是自建 Loop 最大的痛点。这轮它输出 JSON下轮它给你一段自然语言解释。解决办法是在提示词里把格式要求写死并且给一个完整的示例。我用的模板大致是这样先描述任务再给当前状态然后明确说“你的输出必须是一个 JSON 对象包含 type 和参数两个字段不要输出任何其他内容”最后附上一个示例。实测下来加了示例之后格式合规率能从 70% 提到 95% 以上。如果模型还是偶尔跑偏可以在解析失败时做一次重试把“你上次的输出格式不对请严格按 JSON 格式重新输出”作为新提示再调一次。一般重试一次就能纠正。4.4 跑通第一个任务修一个真实的 bug拿一个真实的小项目来试。我选的是一个 Python 脚本里面有个除零错误。任务描述写成“修复 calculate.py 中的 bug使所有测试通过”。循环跑起来大概是这样的第一轮模型读文件发现第 42 行有除法操作输出修改动作。执行后跑测试还是失败因为还有第二个 bug。第二轮模型看到新的报错定位到第 67 行的索引越界修复。第三轮测试全绿循环终止。整个过程跑了 3 轮消耗大概 1.5 万 token。如果手动做来回粘贴报错、等模型回复至少得十分钟。Loop 跑下来不到两分钟。这就是循环的价值——把人的等待时间压缩成机器的执行时间。提示第一次跑建议选个简单任务确认整个链路通了再上难度。我见过有人一上来就让循环改一个大型项目结果模型在第三轮就把代码改乱了还没法回滚。5. 循环跑不稳这些坑我替你踩过了5.1 模型陷入“改-错-改-错”死循环的三种成因这是最常见的翻车场景。模型改了一处测试报新错它再改又报回原来的错来回震荡。成因通常有三个一是反馈信号太模糊模型不知道具体错在哪只能瞎试二是任务本身有矛盾比如两个测试用例的要求互相冲突三是模型对代码的理解有偏差改错了地方。对应的解法第一种情况把测试输出解析得更细精确到断言和行号第二种情况需要人工介入重新审视任务定义第三种情况在提示词里加上“修改前先说明你的推理过程”强迫模型想清楚再动手。我遇到过一次特别典型的模型反复在同一个函数里改来改去每次都说“这次应该对了”。后来我把测试的完整输出包括堆栈都喂给它它才发现问题根本不在那个函数而在调用它的地方。反馈的完整度直接决定模型能不能跳出局部视野。5.2 上下文爆炸什么时候该清空重来循环跑到七八轮之后上下文里堆满了历史记录模型开始“失忆”——忘记最初的任务目标或者把早期的错误当成当前状态。这时候继续跑就是浪费 token。我的做法是设一个上下文预算阈值比如 15 万 token超过就触发压缩。压缩策略是保留任务描述和最近两轮记录把中间的轮次总结成一段话比如“第 3 到 6 轮尝试了三种修复方案均因类型不匹配失败”。这样既保留了关键信息又把体积降下来。如果压缩后模型还是迷糊那就果断清空重来。把当前代码状态和任务目标重新描述一遍开一个新的循环。别舍不得那点历史跑偏的循环越早停越好。5.3 工具调用的权限边界别让循环删了你的文件这是安全底线。模型在循环里能执行命令意味着它理论上能跑rm -rf。我强烈建议在沙箱里跑循环或者至少给命令执行加白名单。只允许它跑测试命令、编译命令、读文件命令写文件和删文件的操作单独走审批。Claude Code 在这方面有内置的权限提示执行危险命令前会问你。自建 Loop 就得自己实现这套。我的做法是维护一个命令前缀白名单比如pytest、python -m、npm test、cargo build这些放行其他一律拦截并记录。5.4 循环日志出问题时怎么回溯循环跑挂了你得知道它每一轮干了什么。所以从第一天起就要记日志每轮记录轮次编号、模型输出的动作、执行结果、判断结论。日志用 JSON Lines 格式一行一条方便后续分析。我后来还加了个功能循环结束后自动生成一份摘要列出每轮的关键动作和最终状态。这份摘要比翻原始日志快多了一眼就能看出循环是在哪一轮跑偏的。6. 让循环更聪明的几个进阶调优手段6.1 给模型加“记忆”跨轮次的状态摘要基础版循环每轮只看最近三轮信息量有限。进阶做法是维护一份滚动状态摘要每轮结束后让模型自己总结“当前进展到哪了、还有什么没解决”把这段摘要作为下一轮的固定输入。这样模型既有短期记忆最近三轮的详细记录又有长期记忆滚动摘要对任务的整体把握会好很多。实测在超过 8 轮的长任务上加了滚动摘要的循环成功率明显更高。6.2 多模型接力规划用强模型执行用快模型成本敏感的话可以考虑这个策略。规划阶段用能力最强的模型比如 Claude 的 Opus 级别把任务拆解清楚执行阶段切换到快而便宜的模型Haiku 级别按规划一步步做。判断阶段再用强模型做质量把关。这样整体成本能降一半以上效果损失很小。因为规划是最需要智力的环节执行相对机械。Codex 的某些配置就支持这种模式自建 Loop 也可以照搬。6.3 并行循环多个任务同时跑怎么管如果你有多个独立任务可以开多个循环并行跑。但要注意资源隔离——每个循环用独立的沙箱目录避免互相干扰。状态存储也要分开别让两个循环写同一个文件。管理上我建议用一个简单的调度器维护任务队列和循环状态哪个循环结束了就取下一个任务。别手动开一堆终端窗口那样根本管不过来。6.4 人工介入点什么时候必须让人来拍板全自动循环听起来很美但有些节点必须留人工确认。比如循环要修改核心配置文件、要执行数据库迁移、要动生产环境的代码这些操作前应该暂停等人确认后再继续。我的做法是在循环里设“检查点”遇到敏感操作就挂起发通知给人。人确认后循环继续。这样既保留了自动化的效率又守住了安全底线。7. 从 Loop 到 Harness把循环嵌进更大的工程体系Loop Engineering 解决的是“单次任务怎么自动完成”但真实工程里任务是一个接一个来的而且任务之间有依赖关系。这就引出了 Harness Engineering 的范畴——怎么把多个 Loop 组织成一个稳定的工作流。一个典型的 Harness 包含任务队列管理、循环调度、结果验证、失败重试、状态持久化。Loop 是 Harness 里的执行单元Harness 负责决定什么时候启动哪个 Loop、Loop 失败了怎么办、多个 Loop 的结果怎么合并。我现在的做法是把每个 Loop 封装成一个独立的执行器输入是任务描述和初始状态输出是执行结果和最终状态。Harness 层用一个简单的状态机来调度这些执行器根据任务依赖关系决定执行顺序。这样 Loop 本身可以保持简单复杂性都收敛到 Harness 层。这套东西搭起来之后日常的重复性开发任务——跑测试、修 lint 错误、更新依赖版本、生成文档——基本都能自动处理。人只需要处理那些真正需要判断力的任务。这才是 Loop Engineering 的终极价值不是让 AI 替你写代码而是让 AI 替你处理那些不需要你亲自处理的环节。Cursor 的 Composer、Claude Code 的 agent 模式、Codex 的自主执行本质上都在往这个方向演进。区别只在于它们把 Harness 的多少部分做进了产品里。自建 Loop 的好处是你能完全控制这套体系按自己的需求定制用现成工具的好处是省事开箱即用。选哪条路取决于你的任务有多特殊、你对控制力的要求有多高。我个人的体会是先用现成工具跑一段时间摸清楚 Loop 的行为模式再决定要不要自建。很多时候你会发现现成工具加上合理的提示词设计已经能覆盖 80% 的场景了。剩下 20% 的特殊需求再考虑自己动手。这样投入产出比最高也不容易在一开始就陷入过度工程的泥潭。