背景#

注:文章由 codex 整理。

Loop engineering 讨论的不是普通代码里的 for/while,也不是 agent harness 内部已经存在的 observe -> act -> observe 工具调用循环,而是人类交给 agent harness 的外部循环规格(loop specification)

arXiv 论文 Stop Hand-Holding Your Coding Agent: Engineering the Loops that Replace Step-by-Step Prompting 给出的核心定义是:loop specification 是一个有边界、可复用的 artifact,包含 triggergoalverificationstopping rulememory,由人类交给 Claude Code、Codex 等 agent harness,让 agent 在无需人类逐步提示的情况下追踪目标、执行、检查并停止。

这篇论文的价值在于把社区里比较口号化的说法收束成一个工程问题:

  • prompt engineering 问的是:这一轮怎么问?
  • context engineering 问的是:agent 应该知道什么?
  • harness engineering 问的是:agent 能在什么环境里行动?
  • loop engineering 问的是:如何设计一个系统,让 agent 能发现工作、执行工作、验证结果、记录状态,并知道什么时候停?

所以它不是“prompt engineering 已死”,而是 prompt 之外多了一层控制系统。一个 loop 的底层仍然会使用 prompt,但关键杠杆从“写一句更聪明的话”变成“设计一个带反馈、验证和刹车的闭环”。

基本概念#

Loop specification 和 harness 的边界#

可以把两者分成三层:

Loop engineering
  = 设计闭环的方法论
    目标、触发、验证、停止、记忆、预算、人工介入点

Agent harness
  = Codex / Claude Code / oh-my-pi / Cursor / Amp 等运行时
    负责调用模型、执行工具、读写文件、跑命令、维护上下文、处理权限

Harness primitives
  = /goal, /loop, automations, hooks, worktrees, skills, plugins, MCP, subagents
    是 loop engineering 在具体产品里的操作入口

/goal/loop、automation、hook 本身不是完整的 loop engineering。它们只是 harness 暴露出来的执行原语。真正的 loop engineering 在于:你是否定义了可靠的完成条件、反馈如何改变下一步、失败怎么停止、状态放在哪里、谁来审查 agent 的结果。

一个真正 loop 的最小结构#

结合论文、OpenAI Codex 文档、Claude Code 文档和 Ralph loop 的实践,一个 loop spec 至少应该有这些字段:

## Trigger
- Manual / schedule / event:
- Cadence:
- Preconditions:

## Goal
- Desired outcome:
- Scope:
- Out of scope:

## Execution
- One turn does:
- Allowed tools:
- Required skills:
- Isolation:

## Verification
- Level:
- Concrete check:
- Evidence required:

## Stop Conditions
- Success:
- No-op:
- Blocked:
- Stalled:
- Exhausted:

## Memory
- State file:
- Decision log:
- Progress queue:
- What must be updated every turn:

## Guardrails
- Budget:
- Human approval gates:
- Irreversible actions:
- Security boundaries:

这里最重要的是 VerificationStop Conditions。如果没有真实检查,loop 只是“让 agent 重复干活”;如果没有停止条件,loop 就会把不确定性变成成本。

Verification Ladder#

论文里最有用的分类是五级验证阶梯:

Level 验证方式 例子 自主性
1 Deterministic check exit code、单测、golden output、断言 最强
2 Rule / constraint linter、schema、policy、格式规则
3 Delayed field truth 部署后指标、真实用户反馈、线上观测 客观但慢
4 Model-as-judge rubric 评分、LLM review 脆弱
5 Human checkpoint 人工 review、审批、验收 监督,不是自动验证

实践原则:

  • 优先把 loop 设计到 Level 1 或 Level 2。 这才是无人值守时最可靠的区域。
  • Level 3 可以作为长期闭环,但不能替代本轮验收。例如线上指标要过几小时才知道,就需要把当前 loop 的状态标成 pending-field-validation,而不是 success
  • Level 4 必须诚实标注为 model judgment,不要伪装成确定性检查。
  • 如果必须使用 Level 4,maker 和 checker 要分离:不同 session、不同 subagent、不同模型,至少使用 fresh context。
  • Level 5 是人工监督,不是 loop 自动完成的证据。

这也解释了为什么 coding agent 是 loop engineering 的天然场景。Anthropic 在 Building effective agents 里提到,代码任务适合 agent 的原因之一就是可以通过 automated tests 验证,agent 可以用 test results 作为反馈继续迭代。

最佳实践#

1. 先定义 done,再定义 prompt#

一个 loop 的第一问题不是“怎么提示 agent”,而是:

什么证据能证明这轮工作真的完成?

OpenAI Codex 的 Goal mode 也强调,goal text 同时是 starting prompt 和 completion criteria,好的 goal 应该包含具体结果、可测目标或测试标准。Claude Code 的 /goal 更进一步:每轮后用一个小模型检查 completion condition 是否满足;但文档也提醒,这个 evaluator 不会独立跑命令或读文件,它只能根据 transcript 里 Claude 已经展示的证据判断。

所以 loop spec 里的 done condition 应该写成:

Success:
- `npm test -- auth` exits 0
- `npm run lint` exits 0
- No files outside `src/auth/**` and `test/auth/**` are modified
- Final output includes exact command results and changed files

而不是:

Success:
- auth works

2. 让每轮反馈改变下一轮动作#

论文提出一个很实用的判断:如果上一轮结果不会改变下一轮动作,那它不是 loop,只是 scheduled prompt。

例如:

  • 每天 9 点让 agent 总结新闻:通常是 scheduled one-shot。
  • 每 5 分钟检查 CI,失败就修、通过就停:这是 loop。
  • 每轮读取 coverage,挑最低覆盖文件补一个测试,再重新计算 coverage:这是 loop。
  • 每天随机让 agent “优化代码”:很可能是成本黑洞。

这个判断能防止把所有定时任务都包装成 loop。Loop 的价值来自 feedback,不来自重复。

3. 每轮只移动一个主要变量#

Ralph loop 的经验里反复强调 “one item per loop”。这和论文里的 act without breaking what works 是同一个原则:每轮只改一个主要对象,马上跑检查,失败时归因才清楚。

适合写进 loop spec 的形式:

One turn:
1. Read current failure list.
2. Pick the highest-priority unresolved item.
3. Change only the files needed for that item.
4. Run the smallest relevant test.
5. If green, run the broader regression gate.
6. Update progress memory.

这比“修掉所有失败”更适合无人值守,因为它让 verification signal 保持可解释。

4. Maker 和 checker 分离#

论文把 self-approving loop 列为核心反模式:同一个模型生成、同一个模型打分,容易 reward hacking。Addy Osmani 的 Loop Engineering 也把 sub-agent 视为关键部件:一个 agent 写,另一个 agent 查。

实践上有几种分离方式:

  • Codex / Claude Code 里使用 reviewer subagent。
  • 一个 session 实现,另一个 fresh session review。
  • 用 deterministic tests 替代 model review。
  • 使用 Level 4 judge 时,换模型、换 prompt、换上下文,并保留 rubric。
  • 对高风险变更,human checkpoint 放在 irreversible action 前,例如 merge、deploy、push tag。

不要让“写代码的 agent 自己说自己写对了”成为成功条件。

5. 状态必须外部化#

长期 loop 不能依赖单一对话窗口。论文和 Ralph 都强调:状态要落在文件、issue board、Linear、PR comment、markdown progress log 或数据库里。

Ralph 的极端版本是:

while :; do cat PROMPT.md | claude-code ; done

它每轮可以是 fresh context,但会重新读取 PROMPT.mdfix_plan.mdspecs/*、测试结果和代码状态。换句话说,上下文不是 conversation history,而是 versioned artifacts

这给普通 loop 的启发是:

  • AGENTS.md / CLAUDE.md / project rule:放长期运行规则。
  • fix_plan.md:放当前 backlog 和优先级。
  • loop-state.md:放每轮完成、阻塞、失败、下轮动作。
  • 测试和代码注释:记录为什么某个 check 存在。
  • PR / issue / Linear:作为跨系统状态。

状态外部化还有一个好处:下一轮 agent 可以 fresh start,减少旧上下文污染。

6. 用 skills 固化可重复能力#

论文指出,当前实践里 reusable skills 使用还不充分;但从工程角度看,skills 是 loop 能否稳定复用的关键。

不要把所有项目知识塞进一个巨大 prompt,而是把可复用动作做成 skill:

  • $triage-ci-failure
  • $fix-flaky-test
  • $review-pr
  • $update-release-note
  • $coverage-improvement
  • $security-review

一个好的 loop spec 应该调用命名 skill,而不是每轮重新解释完整流程。Addy 的总结也类似:automation 负责 heartbeat,skill 负责可维护的任务逻辑。

7. 自动化之前先手动跑通#

OpenAI 的 Codex best practices 倾向于把复杂任务拆成可验证步骤,并通过 AGENTS.md、skills、workflows 固化重复经验。Codex cookbook 的 iterative repair loops 也把流程拆成 Review -> Repair -> Validate:先结构化发现问题,再局部修复,再让 validation 输出成为下一轮输入。

成熟路径应该是:

  1. 手动 prompt 跑一次。
  2. 写出 loop spec。
  3. 加 deterministic check。
  4. 限制 scope 和 budget。
  5. /goal 跑单 session。
  6. 加 reviewer 或 human gate。
  7. 最后再改成 /loop、automation、cron、GitHub Action 或 Routine。

不要把手动都不稳定的流程直接放进后台。

Ralph Loop#

Ralph 是 loop engineering 的一个很有代表性的极端形态。Geoffrey Huntley 在 Ralph Wiggum as a “software engineer” 里把它定义成一个 Bash loop,本质上每轮重放同一个 prompt,让 agent 在 repo、spec、plan 和测试反馈之间反复推进。

它的核心不是那行 shell,而是这些工程约束:

  • Fresh context:每轮可以从干净上下文开始,减少上一轮幻觉和错误推理污染。
  • File-backed memoryAGENT.mdfix_plan.mdspecs/* 是真正的状态。
  • One item per loop:每轮只做一个最重要的事项,避免归因混乱。
  • Backpressure:build、test、type checker、static analyzer、security scanner 都可以作为回压。
  • Plan regeneration:计划文件本身可被重建、清理、更新。
  • Self-documenting tests:写测试时记录测试存在的原因,帮助未来 fresh context 的 agent 理解。
  • Human judgment remains:Ralph 能跑很久,但坏掉时仍需要 senior engineer 判断是回滚、修复还是重写 prompt。

Ralph 的适用边界也很清楚:

  • 适合 greenfield、可由 spec 驱动、检查信号明确的项目。
  • 不适合已有复杂代码库里无约束地乱跑。
  • 如果没有强 backpressure,Ralph 会把“能编译”误当成“实现完整”。
  • 如果没有人工巡检和状态整理,fix_plan.md 会变成垃圾堆。

从 loop engineering 角度看,Ralph 是一种 fresh-context file-state loop:它牺牲 conversation continuity,换取状态可版本化、上下文可重置、失败可重新启动。

OpenAI / Codex 实践#

/goal#

Codex 的 /goal 是 condition-driven loop primitive。根据 Codex Goal mode,goal text 同时作为起始任务和完成标准,Codex 会跨多步工作,并根据 goal 判断下一步和是否完成。

适合:

  • 大任务有明确完成条件。
  • 需要跨多 turn 实现、验证、修复。
  • 验证证据能由 Codex 自己运行并展示。

不适合:

  • 纯审美目标。
  • 完成条件模糊。
  • 需要外部长时间信号但没有中间状态。

Automations#

Codex app automations 更像 trigger 层:定时运行任务,结果进入 Triage inbox;也可以与 skills 结合。它适合 discovery、triage、heartbeat,而不是替代 verification 本身。

一个合理组合是:

Automation:
  每天检查 CI / issue / PR / dependency

Skill:
  结构化 triage 和修复策略

Worktree:
  隔离具体修复

Subagent:
  reviewer fresh-context 检查

Goal:
  单个修复任务 run-until-done

Agent Improvement Loop#

OpenAI cookbook 的 Agent Improvement Loop 重点不是 coding repair,而是 harness improvement flywheel:

traces
  -> human / model feedback
  -> evals
  -> ranked harness changes
  -> Codex handoff
  -> rerun evals

它把真实运行反馈变成 eval,再把 eval 变成下一轮 harness change。这是 loop engineering 在 agent 产品迭代上的形态:不是让 agent 随机自我改进,而是把 traces、feedback、eval 和 implementation handoff 连起来。

Iterative Repair Loop#

OpenAI cookbook 的 Build iterative repair loops with Codex 给了一个更贴近代码开发的模式:

Review:
  inspect artifact and produce structured findings

Repair:
  apply focused edits based on findings and validation feedback

Validate:
  run checks and report remaining issues

Repeat:
  remaining issues become next repair input

这个模式适合文档、notebook、测试修复、迁移等任务。关键是 Validate 输出必须结构化,否则下一轮只是重新猜。

Anthropic / Claude Code 实践#

Workflow 和 agent 的区分#

Anthropic 的 Building effective agents 区分了 workflow 和 agent:

  • workflow:路径由代码预先规定。
  • agent:模型根据环境反馈动态决定下一步。

Loop engineering 通常位于两者之间:trigger、stop、verification、memory 是人类预先设计的;中间执行路径可以交给 agent 动态探索。

Anthropic 的建议也很克制:先用简单方案,只有当复杂度带来可测收益时再升级到 agentic system。这个原则对 loop 更重要,因为 loop 会放大成本和错误。

/goal#

Claude Code /goal 是 run-until-condition 的 session loop。它的关键点:

  • 设置 completion condition 后,Claude 会跨 turn 继续工作。
  • 每轮后由小模型检查条件是否满足。
  • 条件应该包含 measurable end state、stated check 和 constraints。
  • evaluator 根据 transcript 判断,不独立执行命令。

这意味着 /goal 的最佳写法要主动要求 Claude 展示证据:

/goal all tests in test/auth pass, npm run lint exits 0,
and the final transcript shows both command outputs and changed files.
Stop after 20 turns if the same failure repeats.

/loop#

Claude Code /loop 是 schedule / polling loop:

  • /loop 5m check the deploy:固定间隔轮询。
  • /loop check the deploy:由 Claude 动态选择下次间隔。
  • /loop:运行默认 maintenance prompt 或 loop.md
  • session-scoped,有 expiry 和调度限制。

它适合:

  • 等部署。
  • babysit PR。
  • 检查 CI。
  • 定期处理 review comments。

它不适合:

  • 需要连续思考的一次性深任务;这种更适合 /goal
  • 没有反馈改变下一步的固定摘要任务;那只是 scheduled prompt。

Stop Hook#

Claude Code 文档把 /goal/loop、Stop hook 放在同一组比较里:

  • /goal:上一 turn 结束后,由 evaluator 判断是否继续。
  • /loop:时间间隔到了再启动下一 turn。
  • Stop hook:上一 turn 结束后,由你自己的脚本或 prompt 决定。

从 loop engineering 角度看,Stop hook 是更底层的 programmable gate,适合把 Level 1 / Level 2 检查做成强约束。

oh-my-pi 中的实践#

本地 oh-my-pi 也有对应的 harness primitives。

packages/coding-agent/src/slash-commands/builtin-registry.ts 里:

  • /goalToggle goal mode (persistent autonomous objective for this session),支持 set/show/pause/resume/drop/budget
  • /guided-goal:先访谈和 refine goal,再启用 goal mode。
  • /loop:开启 loop mode,下一个 prompt 会在每次 yield 后重新提交,支持 count / duration / inline prompt。

对应实现:

  • packages/coding-agent/src/goals/runtime.ts:goal runtime,记录 objective、token budget、tokens used、time used,并渲染 continuation prompt。
  • packages/coding-agent/src/goals/tools/goal-tool.ts:给 agent 调用的 goal tool,用于 create/get/resume/complete/drop
  • packages/coding-agent/src/modes/loop-limit.ts:解析 /loop 10/loop 10m 等限制。
  • packages/coding-agent/src/modes/interactive-mode.ts:每次 yield 后约 800ms 自动重交 loop prompt。

它和 Claude Code 的差异是:

能力 Claude Code oh-my-pi
/goal completion condition + 小模型 evaluator goal runtime + hidden continuation + agent goal tool
/loop schedule / polling,按时间间隔触发 turn-level repeat,每次 yield 后重交 prompt
state session task、transcript、settings、hooks session state、goal state、todo、checkpoint、memory tools
memory CLAUDE.md、skills、hooks、scheduled tasks retain/recall/reflect、checkpoint/rewind、skills、rules

所以 oh-my-pi/loop 更像 Ralph 的同 prompt 重复执行,但它是在一个 interactive harness 里做自动重交,而不是 shell 层面 while true

Agent 中的实践映射#

Loop engineering 元素 Codex Claude Code oh-my-pi Ralph
Trigger prompt、automation、GitHub/Linear/Slack integrations prompt、/loop、cron、routines、channels slash command、loop mode、commands shell loop
Goal /goal /goal /goalgoal tool PROMPT.md + spec
Execution tools、skills、MCP、worktrees tools、skills、MCP、hooks、worktrees tools、subagents、LSP、debug、job agent CLI + repo
Verification tests、review、cookbook eval gates tests、Stop hook、evaluator、human gate tests、goal completion audit、reviewer/advisor build/test/typecheck backpressure
Stop goal complete、cancel、automation no-op goal met、clear、expiry、hook complete/drop/budget/loop limit manual stop、test pass、git tag、human intervention
Memory AGENTS.md、skills、thread、files CLAUDE.md、loop.md、skills、files Hindsight、retain/recall、checkpoint、files AGENT.md、fix_plan.md、specs
Isolation worktrees、cloud env worktrees、subagent isolation workspace/subagent patterns usually one repo/process

反模式#

While-true around a stranger#

只是把一个原始 prompt 放进无限循环,没有 skill、没有 check、没有状态。这种 loop 看起来勤奋,实际只是把不确定性放大。

Self-approving loop#

同一个 agent 写、同一个 agent 判断完成。尤其是 model-as-judge 时,这会变成 reward hacking。解决方式是 deterministic check 或 maker/checker 分离。

Pretending Level 4 is Level 1#

把 LLM review 说成“验证通过”。正确做法是标注 verification_level: 4,并加 fresh-context reviewer、rubric、抽样人工检查。

Unattended runaway#

没有 budget ceiling、没有 stagnation detector、没有 terminal states。最小修复是加:

  • max turns
  • max cost
  • repeated-failure stop
  • no-progress stop
  • human approval gate

Memory hoarding#

状态只追加不整理。长期看,memory 会污染 agent。需要周期性清理、合并、删除过期事实,并把“当前有效规则”和“历史记录”分开。

Automating before stabilizing#

还没手动跑通,就上 cron / automation / GitHub Action。结果是后台稳定制造不可审查 diff。

设计检查清单#

写 loop spec 前,先回答这些问题:

  1. 反馈会改变下一轮动作吗?如果不会,不要做 loop。
  2. 成功条件是 Level 1/2/3/4/5 中哪一级?
  3. 是否有 deterministic check?如果没有,为什么?
  4. model-as-judge 是否和 maker 分离?
  5. 每轮是否只移动一个主要变量?
  6. 失败、阻塞、无进展、预算耗尽分别怎么命名?
  7. 状态写在哪里?下一轮 fresh context 能否接上?
  8. 哪些动作必须人工批准?
  9. 如何衡量 cost per accepted change
  10. 这个 loop 应该用 /goal/loop、automation、hook,还是普通 one-shot prompt?

推荐落地模板#

# <name> loop

## Use When
- Feedback from each turn changes the next action.
- The goal has a reproducible check.

## Do Not Use When
- The task is pure taste.
- The next action is fixed regardless of result.
- The cost of repeated runs exceeds the value of accepted changes.

## Trigger
- Type: manual / scheduled / event
- Cadence:
- Preconditions:

## Goal
- Objective:
- Scope:
- Out of scope:

## Verification
- Level: 1 / 2 / 3 / 4 / 5
- Command / check:
- Required evidence:
- Who checks:

## One Turn
1. Load state.
2. Pick one highest-priority item.
3. Make the smallest useful change.
4. Run the narrow check.
5. Run broader regression if narrow check passes.
6. Update state.
7. Decide terminal state.

## Terminal States
- success:
- no-op:
- blocked:
- stalled:
- exhausted:

## Memory
- State file:
- Decision log:
- Queue:
- Rules file:

## Guardrails
- Max turns:
- Token / cost budget:
- Human approval:
- Files / systems agent may not modify:

## Actuation
- Local manual:
- `/goal ...`
- `/loop ...`
- Automation / cron / GitHub Action:

总结#

Loop engineering 的核心不是“让 agent 一直跑”,而是把 agent 的持续行动约束在一个可验证、可停止、可复盘的控制系统里

最稳的实践路径是:

  1. 从可验证目标开始。
  2. 让反馈决定下一步。
  3. 每轮只动一个主要变量。
  4. 用测试、linter、schema、field truth 做回压。
  5. maker 和 checker 分离。
  6. 把状态放到文件或外部系统。
  7. 给预算、无进展和人工审批留刹车。
  8. 先手动跑通,再上 /goal/loop、automation 或 Ralph。

/goal/loop、automations、hooks、skills、subagents、worktrees 都是 harness 提供的 loop primitives。真正的工程能力在于如何把这些 primitives 组合成一个不会自欺、不会失控、不会把 token 烧成幻觉的系统。

参考资料#