Ralph Loop 深度解析 — 那个不跑完 PRD 绝不停下的 AI 编程循环
Ralph 不是一个框架,不是一个库,甚至不算一个正经的 CLI 工具——至少原版不是。Ralph 是一个 Bash 循环。具体来说,就是把一个 AI 编程 agent 包在 while 循环里,给它一个任务列表,让它一直跑到所有任务完成。
这个源自 Geoffrey Huntley 社区模式的想法,已经催生了一个完整的生态系统:五个主要实现,累计超过 3 万 GitHub stars,每一层都在原始循环上叠加更多的工程智慧。我们花了一整个调研会话绘制这个生态图,阅读源码,评估哪些应该纳入 Hermes 的自主 agent 工具箱。
原始模式
核心洞察简单到几乎令人尴尬:
while [ 未完成 ]:
读取 prd.json # 还剩什么?
读取 progress.txt # 上次学会了什么?
选择下一任务 # 优先级最高的
启动全新 AI 实例 # 干净上下文,无包袱
实现一个任务 # 小到能放入上下文窗口
运行质量检查 # 类型检查、测试、lint
更新 prd.json # 标记完成
追加 progress.txt # 记录经验教训
三个设计决策让这个循环在幼稚实现必然失败的地方真正可用:
每次迭代都是全新上下文。 每个循环周期启动全新的 AI agent 实例,零对话历史。记忆通过文件系统在迭代间传递(prd.json 管理状态,progress.txt 记录经验),而非通过不断膨胀的上下文窗口。这防止了长期 agent 会话的熵增死亡——没有累积的误解,没有上下文污染,没有幻觉级联。
小任务原则。 每个 PRD 条目必须能在单个上下文窗口内完成。如果一个用户故事需要 2000 token 的对话来完成,那它的工作量就不应该超过 2000 token。这个约束强制良好的任务分解,并防止了"快做完了但上下文已满"的失败模式。
刚性质量门控。 每次迭代结束时强制执行类型检查和测试。如果一个故事引入了 bug,下一次迭代的第一件事就是修复它。bug 的生命周期不超过一个循环周期。
五个实现层级
生态系统通过五个不同的复杂度层级演进:
L1: snarktank/ralph (18.5k stars) — 原始实现
120 行 Bash 脚本。支持两个后端:Anthropic Claude Code 和 Amp。当 agent 输出 <promise>COMPLETE</promise> 标签时退出。无成本控制,无会话管理,无并行执行。这是最小可行循环——而且它真的能用。
README 明确警告:"运行这个会花钱。"在一个记录在案的案例中,一个项目跑了 10 次迭代花了 45 美元的 API 费用。缺少成本控制是 GitHub Issues 中被提及最多的担忧。
L2: frankbria/ralph-claude-code (9k stars) — 工程化版本
Ralph 到这一步才算生产可用。核心特性是双重条件退出门控,可以说是整个生态最重要的贡献:
退出需要两个条件同时满足:
completion_indicators >= 2 AND EXIT_SIGNAL == true
单独一个信号不足以退出。Agent 必须既要声明完成,又要用指标来证明——如果它说"做完了"但指标不支持,循环继续。这防止了最常见的自主 agent 失败模式:过早声称完成。
它还添加了断路器(连续三次无进展→30 分钟冷却)、每小时 API 调用限制、会话支持(24 小时过期),以及令人印象深刻的 566 个单元测试(100% 通过)。.ralph/ 目录约定保持项目根目录整洁。
L3: michaelshimeles/ralphy (2.8k stars) — 多引擎万能遥控器
Ralphy 支持八个 AI 引擎:Claude Code、OpenCode、Codex、Cursor、Qwen、Droid、Copilot 和 Gemini。它还通过 git worktree 引入了并行执行——每个 agent 有独立的分支和文件系统,结果自动合并。--sandbox 标志用符号链接隔离依赖而不重复安装 node_modules。
PRD 解析器支持多种格式:Markdown 复选框、YAML 任务列表、JSON 故事、GitHub Issues——全部输入同一个执行循环。
L4: AnandChowdhary/continuous-claude (1.3k stars) — PR 驱动
Continuous-claude 将循环直接集成到 GitHub PR 工作流。每次迭代创建 PR,等待 CI 通过,自动合并。它增加了三维成本控制(最大运行次数、最大费用美元、最大持续时间)——最先触发的条件停止循环。SHARED_TASK_NOTES.md 文件作为迭代间的接力棒。
L5: vercel-labs/ralph-loop-agent (777 stars) — SDK 化
这是架构上最优雅的实现。不用 Shell 脚本,而是将循环包装为 TypeScript 类,带有可组合的停止条件:
stopWhen: [
iterationCountIs(50),
tokenCountIs(100_000),
costIs(5.00)
]
任一条件触发即退出。内置模型定价表覆盖 Anthropic、OpenAI、Google、xAI 和 DeepSeek 模型。RalphContextManager 处理自动摘要和 token 预算管理。verifyCompletion 回调完全用户定义——你决定"完成"意味着什么。
Ralph 做对了什么(和做错了什么)
对了: 每次迭代全新上下文的模型是让一切运转的设计模式。这违反直觉——我们被训练成认为 agent 需要持久记忆——但对于任务执行,上下文隔离比上下文累积更可靠。
对了: 循环强制执行的小任务原则是良好架构的驱动力。你写不出 500 行的 PRD 条目,因为它字面上放不进上下文窗口。循环强迫分解。
错了: 成本控制在大多数实现中是事后补救。原始 snarktank/ralph 完全没有。生态系统在逐步添加(frankbria 的断路器、vercel-labs 的 costIs),但从第一天起就应该是第一优先级。
错了: Shell 脚本基础限制了可组合性。每个实现以略微不同的方式重写相同的循环逻辑,因为没有共享库。vercel-labs 的 TypeScript SDK 是解决这个问题的第一步。
将 Ralph 映射到 Hermes
Hermes 已经有基础部件——问题是如何组装:
| Ralph 概念 | Hermes 等价物 | 差距 |
|---|---|---|
| PRD 用户故事 | Kanban 卡片 + 状态跟踪 | Hermes kanban 是手动的;Ralph 自动更新状态 |
| 每次迭代全新上下文 | delegate_task + goal + context |
Hermes 任务共享父上下文;Ralph 迭代真正隔离 |
| 持续循环 | 短间隔 cronjob |
Cron 基于时间;Ralph 基于完成状态 |
| 质量门控 | 无内置等价物 | 需要 post_task_validation 钩子 |
| 成本控制 | 无内置等价物 | vercel-labs StopCondition 模式可直接移植 |
| 进度跟踪 | session_search 查询历史 | Ralph 的 progress.txt 更简单但循环中更可靠 |
对 Hermes 最有价值的借鉴:
-
双重退出门控(来自 frankbria)。在每个
delegate_task调用后增加completion_indicators检查。Agent 声称完成了?好——现在证明它。跑测试,检查文件变更,验证验收标准。 -
可组合停止条件(来自 vercel-labs)。一个可以串联的
StopCondition协议:iterationCountIs(10) | tokenCountIs(50k) | costIs(3.00)。任一触发停止循环。这自然适配 Hermes 的 cronjob 基础设施。 -
自主 kanban 驱动器。 一个 cron job 读取 kanban 面板,选取最高优先级的待办项,为其生成
delegate_task,验证完成,推进卡片状态。这是映射到 Hermes 原语的 Ralph 循环。
不应借鉴的
Shell 脚本包装模式对 Hermes 是错的。Hermes agent 有原生执行能力——不需要 shell out 到 Claude Code 或 Codex CLI。循环逻辑应该作为 Hermes 基础设施实现(新工具或 cronjob 流水线),而非外部 shell 脚本。
多引擎支持也不必要。Hermes 已经抽象了模型选择;循环不需要知道 agent 是在 Claude、GPT 还是 DeepSeek 上运行。
最终判断
Ralph 值得认真采纳——不是直接引入,而是作为设计模式。全新上下文循环、双重退出门控和可组合停止条件,应该作为 Hermes 的自主执行原语内置实现。
前进路径:将自主循环驱动器实现为 cronjob + delegate_task 流水线,添加完成验证钩子,移植停止条件模式。这给了我们 Ralph 的核心价值——持续、自验证的任务执行——却没有 Ralph 的 Shell 脚本包袱。
从小处开始。一个 kanban 卡片,一次迭代,一次验证检查。循环自然扩展。