智能体编码循环:从Bash单行命令到/goal,检查机制与强制终止条件
逐步实现智能编码循环:bash单行命令、Claude Code的/goal与/loop功能、外部验证机制、三项支出上限以及值得保留的技能。
2026年6月,彼得·斯坦伯格的一句话主导了关于AI编码的讨论,并获得了两百万次浏览量:编码智能体不应再通过手动方式获得提示,而应设计出能够为这些智能体提供提示的循环结构。随后人们的回复演变成了一场关于其含义的争论。当有人询问实际应用场景时,被引用最多的回答竟是只有两个人知道答案。这既有趣又错误。这个理念并非玄妙不可捉摸,实现它的方法仅需一条指令。
与其争论提示工程是否已经过时,不如从一条五分钟内就能复制粘贴的代码开始,着手构建一个实用的提示系统。
有三点可以支撑其余观点:
- 循环是一种脚本,它向智能体发送指令,检查输出结果,判断任务是否完成,若未完成则重复执行。人类不再需要坐在循环中手动输入指令。循环只需编写一次,模型则作为其中的子程序运行。
- 最简单实用的循环是一行bash命令,而最有效的则是单个斜杠命令。启动这类循环无需任何编排框架,试图从更复杂的框架开始则是错误之举。
- 能正常工作的循环与会耗尽预算的循环之间的区别在于两点:一是要有办法将输出结果与外部真实值进行比对,二是要有明确的停止条件使其停止运行。
定义与层级结构
鲍里斯·切尔尼创建了 Claude Code,据他所说,在最近一个月里,他向该平台提交的259个拉取请求全部由 Claude Code 自动完成,而他的集成开发环境则从11月起就被卸载了。他简单描述了自己的方法:不再向 Claude 发出指令,而是让循环自动运行并自行决定下一步操作,他的工作仅限于编写循环代码。
他设计的三级阶梯让这一理念变得具体可感。一年前,这项工作还只是带有自动补全功能的手写代码;随后是多个并行运行的智能体会话,每个会话都需要人工输入指令。现在则变成了程序来为智能体提供指令,工程师则可以去做其他事情。这项工作已经上升到一个新的层次——从编写代码变为编写编写代码的程序。他明确表示这并不会让工程师失业:仍然需要有人来决定要构建什么,优秀的工程师依然至关重要,而且检查结果也始终不可或缺。按键操作依然存在,判断力也依然重要。
最简单的循环:一行bash代码
整个概念仅需一行代码即可实现,运行一次就能让人对其有直观感受。它被称为“拉尔夫循环”,以拉尔夫·威格姆命名,由杰弗里·亨特利在2025年推广开来。
while :; do cat PROMPT.md | claude -p --dangerously-skip-permissions; done
就是这么简单。相同的提示词文件会被输入到无界面模式的 Claude Code 中,智能体会持续运行直到退出,然后再次用完全相同的提示词开始新一轮循环。每次运行都不会记住上一次的结果,因此它需要从文件、检查清单以及之前运行留下的提交记录中重新获取信息。其中不涉及任何框架或状态机,只有围绕编码智能体的无限循环。
粘贴时请务必小心:那个用于跳过权限提示的标志正如其名般直接,智能体会直接执行命令而不会询问。应在可丢弃的 git 工作树或容器中,且选择那些丢失后无关紧要的分支,绝不能在主分支上操作。
关键在于习惯而非代码本身。为了避免漫长的对话变得乏味,每次迭代都从一组固定的基准文件开始。提示文件每次都会指定相同的几份文档,通常是规范文件和检查清单,智能体在处理过程中会逐项勾选并确认完成。这样,新的迭代就有明确的方向,而且每轮的进度记录能防止智能体偏离轨道或重复已完成的工作。
这种简单的技巧真的有效吗?在Y Combinator黑客松上,一个团队仅用“ralph循环”就在一夜之间创建了六个代码仓库,API使用费用约为297美元,而他们估计这相当于雇佣工人工作五万美元的成本。Huntley也是用同样的方法开发出了一整种小型编程语言。虽然作为一种简单工具,这种方式很快就会显得不够用,但它能在半分钟内让使用者掌握其基本架构。
问题在于,最熟悉这一技术的人为何会认为它已经过时。Ralph循环假定终端会一直保持打开状态,且从不检查任务是否已完成,它只是持续运行下去,接下来的两节将探讨这个问题。
两个命令:/goal 和 /loop
无需手动编写bash脚本,Claude Code已提供了两个命令,能够更安全地实现同样的循环逻辑。
/goal命令会让智能体持续工作,直到某个指定条件成立,而如何设定这个条件正是关键所在。
/goal all tests in test/auth pass and the lint step is clean,
or stop after 20 turns
使其区别于“while-true”循环的关键在于下一步操作。每轮对话结束后,Claude Code会将条件与对话内容传递给另一个独立的小型快速模型,默认为Haiku,该模型会给出“是”或“否”的回答并说明原因。若答案为“否”,则会将该原因作为下一轮的指导。而工作模型则永远无需自行声明任务已完成。
最关键的限制在于,法官既不会进行测试,也不会查看代码库。他只能看到对话记录,因此相关条件必须能从智能体自身的输出中得到证明。在认证文件夹中通过测试即符合要求,因为智能体已执行了这些测试,且结果记录在对话中;而声称认证过程可靠则无法满足要求,因为对话记录中没有任何内容可以证明这一点。法官只查看确认信息而不审查代码,因此真正的验证仍需由智能体实际执行命令,再由法官判断该确认信息是否显示为通过。
一个合理的状态描述会明确一个可测量的最终状态,并说明智能体将如何通过输出来体现该状态。提升认证质量并非一种状态条件;而认证测试通过、测试命令无错误退出,以及git status仅显示认证文件有变动,这些才属于状态条件,因为每一项都会作为智能体实际执行的命令出现在记录中。可设置诸如20轮后停止之类的限制,再加上最大轮数标志作为强制保障,这样无人监控的运行就不会无限持续下去。
无人监控的一次性运行会使用带该标志的无头模式以及用引号标出的目标。该进程在运行期间必须保持存活,因此需要保持终端打开或连接到服务器,而不能使用已关闭的笔记本电脑。若要关闭笔记本,可使用云端的Claude Code。在本地运行时,按下Ctrl+C即可提前终止。
实际中的短时间运行,比如两轮对话且耗时约40秒,看起来就是这样的。
> /goal all tests in test/auth pass, npm test exits 0, or stop after 15 turns
◎ /goal active · turn 1
ran: npm test
✗ 2 failing in test/auth/login.test.ts
judge: not done, expired-token case still throws◎ /goal active · turn 2
edited src/auth/token.ts
ran: npm test
✓ 41 passing, exit 0
judge: done, npm test exits 0 and only auth files changed✓ goal achieved · 2 turns · ~$0.40
那里可以看到所有内容:代理人执行检查,结果会被记录在文字记录中,法官阅读后决定继续还是终止流程。
/loop命令则是负责监督的定时功能。Cherny提供的初始示例值得复制,只需修改其中的名词即可。
/loop babysit all my PRs. Auto-fix build issues, and when
comments come in, use a worktree agent to fix them.
它会按固定间隔重复执行,处理自上一次运行后出现的新内容,直到有人停止它或确认工作已完成。这是一种轮询方式而非事件处理,足以用于监控拉取请求并修复故障。需要编写的是执行意图和停止条件,具体步骤则不必详述。
自我验证确保其可靠性
一个只负责编写代码而不进行验证的循环,会以越来越快的速度犯下严重的错误。它必须将输出结果与外部客观的标准进行比对,而非仅依据自身的判断。
实现这些功能的人都有一个共同原则:由外部检查而非模型自身的评估来决定任务是否完成。循环会持续进行,直到 docker build 成功、容器启动且健康检查通过,此时即便有代理报告一切正常也毫无意义。客观标准取代了主观感觉。用伪代码表示,一个可靠的循环体大致如下所示。
loop:
agent: make progress on the task
run: npm test (or the build, or the linter)
if check passes: done, exit
if check fails: feed the failure back, try again
if no progress in N tries, or budget hit: stop and ping me
实际使用用户还会做两项改进。其一是由与代码编写者不同的模型进行审查,因为每个模型都有其固有的盲点,而新的审查者能够发现作者忽略的问题。Dan Kornas正是为此开发了roborev:它在后台审查每一次代码提交,并在相关上下文仍新鲜时将发现的问题发送给处理程序。其二即便第一次审查没有问题,也要至少进行两次审查,同时将审查轮次限制在五到六次,以避免循环无止境地持续下去。
真正的关键不在于循环本身,而在于循环中的反馈机制。有了有效的检查机制,它就能像引擎一样发挥作用;而没有的话,它就只会生成账单而已。
保障预算不受影响的约束措施
由于代码生成几乎无需成本,费用便转嫁到了运行它的循环上,而没有终止条件的循环则构成了真正的财务风险。Uber在四个月内就耗尽了全年的AI预算,因此规定每位工程师每月使用Claude Code和Cursor每款工具的预算不得超过1,500美元。各生产团队最害怕的,就是那种永无止境的循环——一个被忽视的终端,到了早上就可能变成一张数千美元的账单。
每一个重要的循环都必须设置同样的三个强制终止机制,而且在这三个机制都到位之前,绝不能让循环在无人监控的情况下运行。
max_iterations: stop after N turns (the runaway cap)
no_progress: stop if M turns change nothing (the stuck cap)
budget_ceiling: stop at $X or T tokens (the wallet cap)
on_stop: ping me with the state and the reason
/goal命令几乎可以免费实现上限控制,它只需在条件中写入“20轮后停止”并传递轮次标志即可。剩下的两项则需要手动添加。该命令并未内置进度检测功能,最简单的做法是使用Stop钩子或小型封装代码,通过比较各轮次间的git diff --stat结果,在连续几轮没有变化后停止运行。预算上限应纳入提供方的支出控制机制,即在任何循环开始前在控制台设置一个固定的金额限制。这听起来像是让成千上万的智能体在一夜之间建立一家公司,但实际上大部分工程工作都是为了确保这些循环能够停止。
其中的核心要素是一种技能
循环只是实现机制,真正有价值的是它所调用的功能。
Steinberger再次提出了一个更为持久的建议:凡是重复做两次的事情都会变成可重复使用的技能,而那些原本困难的任务在解决一次之后就会变成技能,从而让下一次处理更加轻松。如果每次迭代都重新学习如何运行测试、定位配置以及格式化输出,那么模型就需要无限地重新学习这个项目。而如果使用一组经过测试、有明确名称的技能库,比如运行测试套件、以团队规定的方式提交拉取请求或部署到预发布环境,那么系统就能不断积累经验,因为每次迭代都建立在已有的能力之上,成本更低,偏差也更小。技能本身具有价值,而循环只是按顺序调用这些技能而已。
监督循环的循环
在边界层面,按照斯坦伯格和切尔尼的实际理解,循环会监控其他循环。一个监督循环会同时为多个代理分配任务、监控它们的运行情况并决定下一步行动,同时还会维护由 Git 支持的持久化状态,以避免系统崩溃导致一切工作丢失。史蒂夫·耶格开发的开源项目 Gas Town 就很好地展示了这一概念:由一个“市长”代理负责管理二十到三十个 Claude Code 实例,而巡逻代理则持续循环执行任务。Claude Code 中的动态工作流则是这种模式的封装形式,即由代理编写调度脚本并管理一组子代理。
没有人会从这种状态开始。正确的顺序是先设定一个目标,再进行自我检查,接着设置三个上限,只有当单个循环无法处理所有任务时才会进行调度,而这通常比人们想象的要晚发生。
本周的第一个循环
- 在临时分支上手动测试该检查功能。创建一个类似 loop-test 的分支,自行运行测试命令,当出现故障时确认命令的退出码不为零。如果自动化工具都无法区分测试通过与失败,人工审核者也同样无法判断。
- 选择具有明确完成时间限制的任务。容易出问题的测试、小型数据迁移或代码格式清理任务都很合适。那些完成标准因人而异的任务则应跳过。
- 将其定义为带有时间限制的目标。使用具体的命令而非模糊的描述,例如设置15次尝试的上限的无头调用,指定认证测试的条件,要求测试命令的退出码为零,并在15次尝试后停止执行。
到周末时,就会出现真正由程序自动完成的代码,一个能够自我检测并修正的循环结构,以及一个防止其失控的限制机制。这便是整个实践过程的缩影。
关于循环是什么的解答与“提示工程”的消亡毫无关系。其核心在于跳出循环结构:只需编写一次循环代码,加入有效的检测机制和可复用的技能,设置停止条件,然后将释放出的注意力用于决定要构建什么功能。Steinberger和Cherny从两个角度描述了同一概念,而如今的入口则只是一个斜杠命令。
相关阅读
- 实用笔记:21种代理设计模式简明解析 — 该文章提供了《实用笔记:21种代理设计模式简明解析》的详细操作指南,包括相关契约、校验规则以及供采用该模式的团队直接使用的代码模板。
- Claude Code的沙箱环境:笔记本电脑上的隔离式代理环境 — 讲解了如何通过本地Kubernetes沙箱为编程代理提供独立的机器、受限的权限、出站访问允许列表以及集群视图,同时分析了自行构建与购买服务之间的利弊。