Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

前言

这本书是写给谁的

这本书写给每一个曾经对着 AI 对话框,一遍遍粘贴代码、反复描述问题、等待 AI 回答、再手动把结果复制出去的人。

你不需要是程序员,也不需要懂 Rust 或复杂的系统架构。你只需要有一个念头:

"我希望 AI 能自己把事情做完,而不是每次都需要我在旁边盯着。"

Ralph 就是为这个念头而生的。


当前 AI 工具的局限

我们正处在一个奇妙的时代。ChatGPT、Claude、Gemini 这些 AI 助手已经足够聪明,可以写代码、分析文档、规划项目。但它们有一个共同的问题:

它们只能做"一问一答"。

你提出需求,AI 给出回答。如果回答有问题,你需要再提问。如果任务复杂,你需要把大任务拆成小任务,一步一步地"喂"给 AI,然后一步一步地把结果"收回来"。

这就像你雇了一个很聪明的助手,但他没有短期记忆,每次见面都要重新介绍自己,重新解释整个项目,重新告诉他你上次做到了哪里。

随着任务越来越复杂,这种工作方式的摩擦成本越来越高。


Ralph 改变了什么

Ralph(Ralph Orchestrator)是一个 AI 编排框架,它把 AI 的"一问一答"变成了自动循环运转的工作流水线

你只需要告诉 Ralph:"我想要什么"

Ralph 会自动:

  1. 将你的需求分解成可执行的小任务
  2. 让不同的 AI 角色("帽子")分工合作
  3. 自动检查每步的结果是否合格
  4. 在遇到问题时自动重试和修复
  5. 积累学到的经验,下次做得更好
  6. 直到任务真正完成,才停下来

整个过程你可以去喝咖啡,只需偶尔查看一下进度,或在关键节点给出指引。


本书的结构

本书分为五个部分:

第一部分:认识 Ralph——我们会先建立直觉性的理解,看懂 Ralph 背后的思考逻辑,再去学习具体操作。

第二部分:快速上手——手把手带你安装 Ralph,跑通第一个任务,感受循环编排的魔力。

第三部分:核心功能——深入了解帽子系统、事件总线、背压机制、记忆与任务这四个核心模块。

第四部分:进阶玩法——掌握可视化监控、并行工作流、人机协作等高级用法,让 Ralph 成为真正的生产力倍增器。

第五部分:实战与展望——通过完整的项目案例,看懂 Ralph 在真实场景中如何运转;再展望 AI 自动化时代的工作新范式。


阅读建议

  • 如果你是第一次接触 Ralph:请按顺序阅读,不要跳过第一至三章,那里建立的概念模型会让后面的内容豁然开朗。

  • 如果你已经安装并跑通了基础示例:可以直接从第六章开始,深入了解各个功能模块。

  • 如果你只想快速解决某个具体问题:查阅书末的"附录:常用命令速查",找到你需要的命令,再回到对应章节阅读详细说明。


这个世界上最贵的资源不是钱,而是注意力。Ralph 的终极目标,就是让你把注意力花在真正值得的地方——做决策、定方向、创造价值——而不是在 AI 对话框里反复粘贴文本。

让我们开始吧。

第一章:告别反复粘贴——AI 工作方式的革命

一个你熟悉的场景

想象一下这样的早晨:

你打开 Claude 或 ChatGPT,想让它帮你开发一个小功能——比如给你的网站添加用户登录功能。

你描述了需求,AI 给出了一段代码。你把代码复制到编辑器里,运行,报错了。

你把报错信息粘贴回 AI,AI 给出修改建议。你再次复制,再次运行,又报了新的错。

这样的循环重复了七八次,最终代码跑起来了,但你发现它缺少了输入验证——用户可以提交空表单。

你再次描述问题,AI 修改代码,你再次复制……

一个小时过去了,这个功能终于大致可用,但测试还没写,错误处理还不完善,代码风格和项目其他部分也不统一。

你还需要继续这个循环,不知道还要多久。


问题的根源

这种工作方式的问题不在于 AI 不够聪明,而在于工作流程的结构性缺陷

1. 每次对话都是全新的开始

当代的 AI 助手没有持久记忆。每次你开启新对话,它对你的项目一无所知——你需要重新介绍背景、重新解释约束条件、重新告诉它上次做到了哪里。

哪怕在同一个对话里,随着对话越来越长,AI 早期获取的上下文也会逐渐"淡出"视野,导致它忘记之前讨论过的约束条件。

2. 人是循环里的瓶颈

在"人工智能 + 人类"的协作模式里,人类是管道里最慢的那个节点

AI 生成代码可能只需要几秒钟,但你需要:

  • 阅读和理解 AI 的输出(几分钟)
  • 判断是否正确(几分钟)
  • 手动复制粘贴(几十秒)
  • 运行测试(几秒到几分钟)
  • 阅读错误信息(几分钟)
  • 再次描述问题(几分钟)

在整个流程里,AI 的实际工作时间可能不到总时间的 10%。

3. 质量靠人把关,但人很容易疲惫

你需要记住"代码需要测试"、"需要处理边界情况"、"需要符合项目风格"……但当你重复了十几次"复制-粘贴-运行-反馈"的操作之后,注意力会下降,容易漏掉重要的质量检查项。


一个更好的模型:自动化循环

现在想象一种不同的工作方式:

你描述了你的需求。然后你离开去做别的事情。

一小时后,你回来查看:AI 自动完成了功能实现,自动运行了所有测试(并在测试失败时自动修复),自动检查了代码风格,自动处理了边界情况——因为它知道这些是必须完成的。

这不是科幻,这正是 Ralph 在做的事情。


编排(Orchestration)的概念

"编排"这个词来自音乐领域,指的是指挥协调多种乐器共同演奏一首曲子。在软件领域,编排指的是协调多个自动化进程,让它们按照预定的规则协同工作。

Ralph 是一个 AI 编排框架。它的工作原理是:

把传统方式和 Ralph 方式放在一起对比,差别就清楚了:

传统方式:你是循环里的节点 你描述需求 AI 给代码 你复制到编辑器 你运行,报错 你复制报错 粘回给 AI 循环 N 次 🔴 人是瓶颈 每一步都要你亲自操作 Ralph:你在循环外 你描述需求 🚀 Ralph 启动循环 (Ralph 循环内部,自动跑) AI 写代码 自动检查 AI 自动修复 再检查 合格才继续,不合格原地修 🟢 你去做别的事 回来直接看结果 循环完成

关键的改变是:你不再是循环里的节点。你站在循环外面,在需要的时候介入和指引,而不是驱动每一个步骤。


与其他 AI 工具的对比

工具类型代表产品工作模式适合场景
对话式 AIChatGPT, Claude一问一答简单咨询、快速生成
AI 编辑器Cursor, Copilot代码补全 + 对话写代码时的辅助
AI AgentClaude Code, Kiro自主执行任务中等复杂任务
AI 编排框架Ralph循环自动编排复杂、长时间任务

Ralph 并不取代其他工具——事实上,它是在 Claude Code、Kiro 等 AI Agent 之上工作的,把这些 Agent 组织成一个自动运转的流水线。

📖 名词解释 · AI Agent(智能体)

AI Agent 是比"对话式 AI"再进一步的概念:不是你问一句它答一句,而是你给它一个目标,它自己决定要做哪些步骤、调用哪些工具(读文件、跑命令、调接口)、然后交付最终结果。Claude Code、Cursor Agent、Kiro 都属于这一类。

Ralph 的角色是它们的"上层指挥":AI Agent 自己干活,Ralph 在外面循环、审查、迭代。

进一步学习:维基百科:Intelligent agent · Anthropic:Building effective agents


这对你意味着什么

也许你不是程序员,Ralph 对你依然有价值:

产品经理:用 Ralph 的 plan 功能,把一个模糊的想法,通过 AI 问答的方式,逐步精炼成有清晰需求、明确验收标准的设计文档。

研究人员:配置 Ralph 的研究帽子(research hat),自动对某个主题进行多角度深度研究,整理成结构化报告。

内容创作者:把 Ralph 配置成写作辅助流水线,从大纲到草稿,再到润色,自动迭代到你满意。

开发者:这才是 Ralph 最核心的使用场景——从一句描述出发,自动完成功能开发、测试、代码审查的完整流程。


本章小结

  • 当前"人工智能+人类"的对话式工作方式,瓶颈在于人类每一步都需要手动参与
  • 编排框架把 AI 的工作变成自动循环流水线,人只需要在关键节点介入
  • Ralph 是一个开源的 AI 编排框架,支持多种 AI 后端(Claude、Gemini 等)
  • 下一章我们将深入了解 Ralph 的工作原理,以及它的核心创新——"帽子循环"

思考题:在你目前的工作中,有哪些重复性的"复制-粘贴-检查"流程?这些流程理论上可以被自动化编排取代吗?

第二章:Ralph 是什么——永不停歇的 AI 编排引擎

一个名字背后的故事

Ralph 这个名字来自美剧《辛普森一家》里的小男孩 Ralph Wiggum。他有一句令人捧腹的名言:

"Me fail English? That's unpossible!"(我英语不及格?那不可能!)

这句话完美地诠释了 Ralph 这个工具的核心精神:就算一次失败,只要不停重试,最终一定能成功。


Ralph Loop 的起源:一个 Bash 命令引发的革命

Ralph Orchestrator 的思想根源,来自开发者 Geoffrey Huntley 提出的 "Ralph Wiggum 技巧"

这个技巧出奇地简单。Huntley 最初的实现,只是一个 Shell 脚本:

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

就这么一个死循环——把提示词文件反复喂给 AI,直到它自己输出"完成了"为止。

Huntley 用了一句话描述这个方法的本质:

"这个方法在一个不确定的世界里,以一种确定的方式失败。"(deterministically bad in an undeterministic world

换句话说:它不保证每次都成功,但它保证失败的方式是可预测的、可调整的。给它足够多的迭代机会,它会收敛到正确答案——这就是所谓的"最终一致性"(eventual consistency)。

真实战绩

这个简单想法经过验证,已经在真实项目中取得了惊人的成果:

  • Y Combinator 黑客松:一支团队用 Ralph 循环在一夜之间交付了 6 个代码仓库
  • 合同项目:一位工程师用 $297 的 AI API 费用,完成了一份价值 $50,000 的外包合同
  • 语言开发:Geoffrey Huntley 本人用一个跑了三个月的 Ralph 循环,创造出了一门完整的编程语言(CURSED)

从 Bash 到 Ralph Orchestrator

原始的 Bash 循环虽然强大,但也有明显的局限:只有一个"全能" AI 在干所有的事,没有角色分工,没有质量检查,没有跨会话的记忆。

这正是 Ralph Orchestrator 诞生的原因——它在 Huntley 的原始思想之上,增加了:

原始 Bash 循环Ralph Orchestrator
单一 AI,全能型帽子系统:多角色分工
无质量检查背压机制:AI 自我验证
无记忆,每次从零持久记忆跨会话积累
只支持 Claude支持 8+ 种 AI 后端
纯命令行,无可视化TUI 界面 + Web 仪表盘
无人机协作Telegram 实时干预

可以说,Ralph Orchestrator 是 Ralph Loop 思想的工程化实现和功能增强版。

📖 名词解释 · CLI / 命令行 & API

**CLI(Command-Line Interface,命令行界面)**是最早的一类人机交互方式:在一个纯文字窗口(终端)里输入命令,计算机执行后返回文字结果。比鼠标点击的图形界面更高效、更容易被自动化工具(像 Ralph)调用。如果你完全没用过终端,入门最简单的方式是在 macOS 上打开 "终端" 应用、在 Windows 上装 WSL2 或打开 PowerShell,然后跟着本书敲命令——学习曲线比你想的平缓。

**API(Application Programming Interface)**是让两个软件互相"对话"的约定接口。Claude、GPT 等 AI 都是把自己的能力通过 API 开放出来,别的程序(比如 Ralph)才能调用。用 API 意味着按调用量付费——发了多少字(Token)算多少钱。

进一步学习:维基百科:命令行界面 · 维基百科:应用程序接口


Ralph 的身份:编排框架

Ralph 的全名是 Ralph Orchestrator(Ralph 编排器),版本号目前是 2.x,它是一个开源项目,用 Rust 语言编写。

但"Rust 语言"这四个字对你来说不重要——你不需要理解它的内部代码就能用好它。你只需要理解它做什么。

Ralph 做的事情

  • 接收你的任务描述
  • 调用 AI Agent(如 Claude Code、Kiro 等)来执行任务
  • 自动检查执行结果是否合格
  • 如果不合格,自动重新尝试
  • 记录过程中学到的经验
  • 任务完成后,告诉你"完工了"

Ralph 不做的事情

  • 直接写代码(那是 AI Agent 干的)
  • 存储你的代码(那是你的本地文件系统和 Git 干的)
  • 替代 AI Agent(它是在 Agent 上层协调的)

一句话总结:Ralph 是 AI Agent 的指挥官,不是 AI Agent 本身。

📖 名词解释 · Git

Git 是程序员用来管理代码版本的工具——像给文件夹开了"无限撤销"。每次改完代码执行一次 git commit,就相当于拍一张快照;以后任何时候都能翻回到某张快照。多人协作时,大家各改各的,最后用 git merge 把各自的修改并起来。

Ralph 大量依赖 Git:它把 AI 每一步的产出都在 Git 里记录,出问题时可以精确回滚;并行循环时也靠 Git Worktree(第十一章详细讲)做隔离。即使你不是程序员,只要会用 git initgit addgit commit 三个命令,也足以配合 Ralph 使用。

进一步学习:维基百科:Git · Git 官方中文教程


架构全景:三层模型

理解 Ralph 最好的方式是把它想象成三层结构:

👤 你 提需求 · 看结果 · 偶尔介入 第三层:人类 ⚙️ Ralph 编排引擎 事件循环 · 帽子协调 · 背压检查 · 记忆管理 "AI Agent 的指挥官" 第二层:编排 🤖 AI Agent Claude Code · Kiro · Gemini · Codex · Roo · ... 第一层:执行 需求 / 指引 任务 / 帽子指令 执行结果 / 事件 进度 / 结果 / 问题

你和 AI Agent 之间,多了一个 Ralph 层。这个层的核心价值是:

  • 自动化循环:不需要你每步都在场
  • 质量把关:自动拒绝不合格的结果
  • 角色分工:不同任务交给不同的 AI 角色
  • 持久记忆:跨会话保留学到的经验

支持哪些 AI 后端

Ralph 不绑定任何一个 AI 服务,它目前支持以下后端:

后端名称说明
Claude CodeAnthropic 的 Claude CLI,推荐新手使用
KiroAmazon 的 AI 编程 Agent,速度快
Gemini CLIGoogle 的 Gemini 命令行工具
CodexOpenAI 的编程 Agent
Amp专注代码的 AI Agent
Copilot CLIGitHub Copilot 命令行版
OpenCode开源 AI 编码工具
Pipi-coding-agent,轻量级本地 AI Agent
Custom自定义后端(可接入任何支持 CLI 的 AI 工具)

这意味着你可以根据任务类型、成本预算或个人偏好,选择不同的 AI 后端。同一个 Ralph 配置,换个 --backend 参数,就能切换到不同的 AI 引擎上运行。


核心创新:帽子系统

Ralph 最独特的设计是帽子系统(Hat System)

想象一个小型工作团队:

  • 有人专门负责分析需求、制定计划(规划师)
  • 有人专门负责写代码(开发者)
  • 有人专门负责挑毛病、发现问题(批评者)
  • 有人专门负责最终确认是否完工(验收者)

Ralph 里的"帽子"就对应这些不同的角色。每顶帽子是一个 AI 角色配置,包含:

  • 名字:这个角色叫什么(如"规划师 📋")
  • 触发条件:什么事件会激活这个角色
  • 工作指令:这个角色该如何工作
  • 发布事件:完成工作后通知其他角色

通过帽子系统,Ralph 可以让同一个 AI 在同一个任务里扮演多个不同角色,模拟一个小团队的协作效果。


事件驱动:AI 团队的协作机制

帽子之间如何通信?答案是事件(Events)

Ralph 有一条事件总线(可以理解为 AI 角色们的内部聊天频道)。每顶帽子完成工作后,会向总线发布一个事件,比如"任务已准备好"或"代码审查通过"。其他帽子监听这些事件,当条件满足时自动被激活。

这就像一条流水线:

设计开始 → 规划师制定计划 → 发布"任务就绪"
                              ↓
                    开发者收到"任务就绪"
                    开发者写代码 → 发布"代码就绪"
                                    ↓
                          审查者收到"代码就绪"
                          审查者检查代码 → 发布"审查通过"或"需要修改"

这个机制让复杂的工作流可以完全自动化,无需人工干预每个步骤。


持久记忆:AI 的长期学习

Ralph 解决了 AI 的记忆问题,通过两种机制:

记忆文件(memories.md):每次循环中,AI 可以把学到的规律、发现的坑、有效的解决方案,以文本形式写入这个文件。下次循环开始时,Ralph 会自动把这些记忆注入给 AI,让它"不忘初心"。

任务文件(tasks.jsonl):记录当前项目的所有子任务及其完成状态。就算你关闭电脑第二天再打开,Ralph 也知道哪些已经完成,哪些还需要继续。


自动质量保证:背压机制

Ralph 有一个特别重要的功能叫背压(Backpressure)

背压的意思是:当 AI 给出的结果不符合质量标准时,Ralph 会拒绝接受这个结果,并强制 AI 重新做,直到结果达标。

质量标准可以是:

  • 测试必须全部通过(cargo testnpm test
  • 代码格式必须符合规范(eslintcargo fmt
  • 类型检查必须通过(tscmypy

这就像一道道关卡,只有通过所有关卡的代码,才能被认为是"完成了"。


版本与状态

本书写作时,Ralph 的版本是 2.9.x。它是一个活跃开发中的开源项目,API 和配置格式可能随版本更新而变化。

注意:Ralph 目前不支持 Windows 系统,只能在 macOS 和 Linux 上运行。如果你使用 Windows,需要通过 WSL2(Windows Subsystem for Linux)来使用。


本章小结

  • Ralph 是一个 AI 编排框架,不是 AI 本身,而是 AI Agent 的指挥层
  • 它的核心创新是"帽子系统 + 事件总线 + 背压机制 + 持久记忆"
  • 支持 Claude Code、Kiro、Gemini 等多种 AI 后端
  • Ralph Wiggum 技巧的精髓:让 AI 在循环里持续工作,直到真正完成
  • 目前不支持 Windows(需要 WSL2)

下一章,我们将深入了解 Ralph 背后的六条核心哲学,这些哲学决定了 Ralph 的设计方式,也将指导你如何更好地配置和使用它。

第三章:六条黄金法则——Ralph 的核心哲学

为什么要先学哲学

很多技术书的读者都想直接跳到"怎么用",但对于 Ralph 来说,先理解它背后的设计哲学是值得的。

Ralph 的六条核心法则(Tenets)不是装饰性的口号,而是真实指导了软件每个功能的设计决策。当你在实际使用中遇到困惑——"为什么要这样配置?""为什么 AI 每次都重新读一遍文件?"——回到这六条法则,往往能找到答案。


法则一:新鲜上下文即可靠性

原文Fresh Context Is Reliability

含义:每次循环迭代,AI Agent 都从零开始读取所有信息,而不是"记住"上一次的内容。

这听起来很反直觉——重复读不是浪费时间吗?

但 Ralph 的设计者发现了一个关键规律:AI 的上下文窗口就像一个会满的桶。当对话越来越长,早期的信息会被压缩甚至丢失,AI 开始"遗忘"重要的约束条件。

📖 名词解释 · Token & 上下文窗口

Token 是大模型"数数"的单位——不是一个汉字或一个单词,而是模型内部拆分后的片段(大致 1 个英文单词 ≈ 1.3 个 Token,1 个汉字 ≈ 1~2 个 Token)。

上下文窗口(Context Window) 是模型一次能"看"多少 Token 的容量上限。比如 Claude 4.7 的上下文窗口是 20 万 Token(付费用户可到 100 万)。超过这个容量,早期的内容就会被挤出窗口——模型"忘了"。

Ralph 的"新鲜上下文"策略,本质是主动管理这个容量:与其等窗口被对话填满导致模型遗忘约束,不如每次迭代都重新装一次最相关的信息。

进一步学习:Anthropic · Context windows · 维基百科:Large language model

新鲜上下文策略解决了这个问题:每次迭代开始,AI 重新读取:

  • 任务规格说明
  • 记忆文件里积累的经验
  • 当前代码的状态
  • 上一步的结果

这样,每次 AI 做决策时,它的"视野"都是完整和最新的,不会因为"记忆混乱"而犯累积性错误。

实际意义:不要试图让 AI 在一个超长的对话里解决所有问题。Ralph 的循环机制本质上是主动管理 AI 的上下文,让每次迭代都在最佳状态下进行。


法则二:背压优于规定

原文Backpressure Over Prescription

含义:不要告诉 AI 每一步怎么做,而是设立质量关卡,拒绝不达标的结果。

两种不同的指导方式:

规定式(不推荐)

"第一步,打开文件 X。第二步,在第 47 行添加以下代码。第三步,运行测试。第四步,如果测试失败,检查变量名是否正确……"

背压式(Ralph 的方式)

"我需要这个功能能工作。以下测试必须全部通过,否则任务未完成。"

规定式方法看起来更精确,但实际上很脆弱——一旦实际情况和预设不符(比如文件路径不同、代码结构有变化),整个流程就会崩溃。

背压式方法更灵活:AI 可以自由选择实现路径,但必须满足你设定的质量标准。这让 AI 能充分发挥创造性,同时保证结果质量。

实际意义:配置 Ralph 时,把精力放在"结果验证"上(测试、格式检查、类型检查),而不是"步骤规定"上。


法则三:计划是可抛弃的

原文The Plan Is Disposable

含义:不要把计划文档当成神圣不可改动的东西。计划随时可以重新生成。

在软件开发中,人们常常花大量时间讨论和保护一份计划文档,不愿意推翻它,因为"推翻计划等于浪费了之前的努力"。

Ralph 的观点截然相反:计划很便宜,用 AI 重新生成一份只需要几分钟。与其在一份有缺陷的计划上强行推进,不如直接扔掉,重新从当前状态出发,生成更好的计划。

这背后是一个深刻的认知:当信息变化(发现了新的约束、需求有了更新、实现遇到了预料外的障碍),旧计划的价值就大幅下降了。及时更新计划的收益,远大于"浪费了之前规划工作"的损失。

实际意义:如果 Ralph 的某次循环陷入了僵局,不要想着"怎么修复这个计划",而是直接停掉循环,用新的描述重新启动。


法则四:磁盘是状态,Git 是记忆

原文Disk Is State, Git Is Memory

含义:用文件系统管理当前进行中的工作状态,用 Git 版本控制管理项目的历史和经验。

Ralph 把所有的工作状态(任务列表、记忆文件、事件日志)都存在本地文件里,而不是存在数据库或云端。这有几个好处:

  1. 简单:没有复杂的数据库或网络依赖,一个文件就是一切
  2. 透明:你可以直接打开文件查看 AI 在做什么
  3. 可调试:出了问题,直接看文件就能诊断
  4. 可控:你可以手动修改这些文件,直接影响 AI 的行为

Git 则用于长期记忆——当一个任务完成后,提交代码,让这次成功的实现成为项目历史的一部分,未来的 AI 可以通过读取代码库来"学习"这次的经验。

实际意义:了解 Ralph 把哪些文件放在哪里(.ralph/ 目录),这些文件就是你理解 AI 当前状态的窗口。


法则五:用信号导航,不用脚本控制

原文Steer With Signals, Not Scripts

含义:当 AI 反复在某个地方犯同样的错误时,不要写详细的修复脚本,而是给代码库添加一个"信号"(说明、注释、规范文件),让 AI 下次自己看懂。

举个例子:假设 AI 总是忘记在某类操作后清理资源。你有两个选择:

脚本方式:写一段复杂的指令,告诉 AI "当你做了 X 操作之后,必须做 Y 清理"。

信号方式:在代码库的相关位置添加注释或说明文档,解释为什么需要清理,清理的具体方式是什么。这样,当 AI 读取代码时,它会自然地发现这个信号并遵循。

信号方式的好处是:它是持久的,不只对当前 AI 有效,对未来所有 AI(包括人类开发者)都有效。脚本方式只能修复当前问题,信号方式提升了整个代码库的质量。

实际意义:当你发现 AI 重复犯同一个错误时,不要写更复杂的指令,而是考虑在代码库里添加更清晰的说明。


法则六:让 Ralph 自己 Ralph

原文Let Ralph Ralph

含义:你的角色是"坐在循环外面,像调音师一样偶尔调整",而不是"像指挥一样控制每一个音符"。

这是最难接受但也最重要的一条法则。

很多人习惯于对 AI 进行微管理——看着每一步输出,随时介入调整。这种方式在简单任务里可行,但在长期复杂任务里是适得其反的:你的每次介入都打断了 AI 的上下文,需要重新解释背景。

Ralph 的设计鼓励你:

  1. 启动循环后,让它跑——不要盯着每一条输出
  2. 观察结果模式——当循环结束后,看看完成了什么,失败在哪里
  3. 从失败中调整配置——如果 AI 总在某个地方卡住,调整相关的帽子指令或背压配置
  4. 再次启动——相信循环会做得更好

这种"调音师"的心态,需要一定时间才能建立。初期你会觉得不放心,但随着你对 Ralph 工作方式的熟悉,你会发现这是一种更高效、压力更小的协作模式。

实际意义:当 Ralph 在跑的时候,去做别的事。等循环结束后,检查结果,然后决定是"接受"还是"调整后重跑"。


六条法则的综合理解

把这六条法则放在一起,你会发现它们有一个共同的主题:

把注意力放在"系统设计"上,而不是"每个步骤的执行"上。

法则具体体现
新鲜上下文Ralph 自动管理每次迭代的信息量
背压优于规定你定义"什么是完成",不定义"怎么做到"
计划可抛弃不纠结于计划,关注当前状态和最终目标
磁盘是状态通过文件透明地观察和干预
信号导航通过代码库本身传递信息
让 Ralph 自己 Ralph信任循环,聚焦在系统级调整上

本章小结

Ralph 的六条核心法则是它与其他 AI 工具最本质的区别所在。掌握这些哲学,你会更自然地理解为什么 Ralph 的配置是这样的,为什么某些操作是推荐的,为什么某些直觉做法在 Ralph 里是反模式。

在进入实操之前,我们先穿插一段主角故事——认识一位自媒体人李明轩,看看这六条抽象的法则是怎么精确对应他真实工作中的六个痛点的。这位主角将贯穿本书剩下的所有章节。然后第四章正式进入实操:把 Ralph 装到他的电脑上,也装到你的电脑上。

主角故事:李明轩的一天

本章说明

从这一章开始,我们将跟随一位主角——李明轩——走完本书剩下的章节。

后面每一章的命令、每一个功能演示,都会回到李明轩身上:他想解决什么问题,他过去是怎么做的,现在用 Ralph 又是怎么做的。

如果你急着学命令,可以跳过本章;但大多数读者会发现:记住一个鲜活的使用场景,远比记住一串命令更能让知识落地。六条黄金法则看起来抽象,一旦套到一个具体的"一个人干一个团队的活"的场景上,你会瞬间理解 Ralph 的每一个设计为什么是这样。


李明轩是谁

李明轩,35 岁,独立自媒体人,运营一个叫 "明轩说" 的内容品牌,主题是"职场转型 + AI 实战"。

他的阵地:

  • 公众号(12 万订阅)
  • 小红书(8 万粉丝)
  • 知乎(6 万关注)
  • 微博(4 万粉丝)

他的变现:

  • 一个 199 元/年的付费社群(运营在企业微信客户群里,分成 8 个小群),800 位会员
  • 一套 299 元的"AI 实战 10 讲"在线课
  • 偶尔接商业合作稿件

一个现实细节:普通微信群不允许接入机器人,只能人工回复;企业微信客户群(包含外部成员的群)允许接入智能机器人和关键词小助理——这也是李明轩后面能让 AI 自动接管大部分社群答疑的前提。官方文档

他的团队:一个人。太太偶尔帮他校对错别字,除此之外所有的活他全包。

一个典型的工作日:

早上 6:30 起床回复社群问题;7:30 送孩子上学;8:30 到 18:30 还在上一份没完全脱手的全职工作;晚饭和孩子玩一会儿;21:00 开始写明天要发的稿子,经常写到凌晨 1 点。

这不是虚构。这是大多数"个人品牌 + 上班族"真实的节奏。


一个自媒体人的"铁人五项"

一个自媒体人要做的,远不止写稿。按每天要操的心排序:

  1. 选题:刷 20 个信息源找热点,抓有数据、有情绪的话题
  2. 写作:一篇深度文章至少 2 小时初稿 + 1 小时打磨
  3. 多平台适配:公众号长文、小红书短图文、知乎问答、微博段子——同一个内容要写 4 遍
  4. 销售 / 客服:付费社群问题答疑、课程咨询、退款售后、商单沟通
  5. 开发:写小脚本帮自己提效(选题抓取器、多平台发布器、粉丝看板、对账工具)

这五件事对应的恰好是运营一个小型自媒体品牌需要的三大块工作:开发、营销、销售。传统公司里会拆成三个部门、十几个人。李明轩一个人要全吃。

他过去半年的真实账

  • 2 个小工具(选题抓取器、发布器)做了 3 个月还没做完
  • 付费社群平均响应时间 2.3 天(会员开始抱怨)
  • 知乎和微博经常忘更
  • 课程问答积压 60 多条
  • 每晚睡眠不足 5 小时

他不是能力不够,是时间不够。一个人,两只手,一天 24 小时。就算 AI 能写代码、能写文案,他还是得坐在电脑前一句句粘贴、一个个确认。只要他不在场,一切都停了。


没有 Ralph 的那个周二(李明轩的工作日记)

20:45 下班到家。吃完饭、陪孩子、哄睡。

21:30 打开电脑。今天的目标:写一篇关于"35 岁转型 AI"的文章,4 平台发出去。顺便把选题抓取器的小工具再推进一点。

21:45 打开 Claude,让它帮我起草公众号版本。AI 10 分钟给了 3000 字初稿。我读了 20 分钟,改了一半。

22:30 公众号版本定稿。开始写小红书版本。让 AI 再改一遍——"改成 800 字左右的口语风格,带 emoji,分 5 段"。AI 改出来后风格不太对,我又改了 10 分钟。

23:15 知乎版本:AI 把它改成问答体。我在"为什么 35 岁更难转"这段卡住了,AI 说了一堆正确的废话。手动重写。

23:55 微博版本:140 字摘要三条。终于 4 个平台都定稿了。

00:10 开始发布。公众号后台粘贴——图要单独上传——小红书要手动配 9 张图——知乎发出来发现 markdown 格式没渲染,回头修——微博发现链接带参数没缩短,又回头搞。

01:05 全部发布完。选题抓取器的工具?今天又没时间碰了。

01:30 躺下。脑子还在转明天的选题。孩子 6:30 又要起。

06:30 起床。打开手机,社群里有 12 条问题。"李老师这节课的代码我跑不通……"、"退款流程怎么走?"、"合作报价方便私信吗?"——先挑最急的回。

08:30 到公司,本职工作。脑子里一直想着:那个选题抓取器还差多少?课程答疑还没回,社群里那个商单对方等了两天了。

20:45 下班。重复昨天。

一周这样过去,他写了 4 篇文章,发了 16 条内容。但:

  • 2 个小工具还是没进展
  • 社群积压问题还有 8 条没回
  • 课程售后堆到了 20 多条
  • 一个 8000 元的商单因为 3 天没回复被对方取消了

问题不是 AI 不够强——AI 早就能写出漂亮的公众号文章了。问题是"人必须一直在场"。

AI 生成 10 分钟,人审改 1 小时,发布半小时。AI 是加速器,但人是瓶颈。


Ralph 之后:一个人顶一个团队的新剧本

在下一章,李明轩会把 Ralph 装到自己的电脑上。从此,他的一周变成这样——

周一晚上 23:00:他写完今天最后一句话,启动 4 个并行的 Ralph 循环:

  • 循环 A:让"选题帽"把今天积累的 20 个热点话题筛成 5 个候选
  • 循环 B:让"撰写帽 + 审校帽"把昨天定稿的内容改成 4 个平台的差异化版本
  • 循环 C:让"客服帽"接上企业微信客户群的消息接口(普通微信群不允许机器人,客户群可以),把今天的 12 条问题分类,常见的直接拟回复,涉及金钱 / 商务的打标签等他本人处理
  • 循环 D:让"开发帽"继续推进选题抓取器小工具

他关上笔记本,去睡觉。

周二早上 6:30:手机亮了。Telegram 推送了 Ralph 的总结:

  • 循环 A:✅ 完成,5 个候选选题已写入 .ralph/agent/ideas/
  • 循环 B:✅ 完成,4 个平台版本已进入"待审核"队列
  • 循环 C:✅ 完成,9 条常见问题(课程跑不通、报错排查等)AI 已在企业微信客户群里自动应答;3 条涉及退款 / 商单的留在"待你本人回"队列
  • 循环 D:⚠️ 卡在一个第三方 API 认证上,需要你看一下

他刷牙的时候,用手机回了一句:"D 循环用 cookie 方式,不要用 API key"。循环自动继续。

周二早上 7:30:送孩子时在地铁上刷了 5 分钟,审核通过了 4 个平台的文案。mx publish --all 一键发布。

周二上午 10:30 的茶水间:用手机瞄一眼 mx dashboard 网页,昨晚发布的 4 条内容数据已经出来了。知乎那条互动明显更高,他顺手让 Ralph 起草一篇相同话题的后续文章。

周二晚上 21:00 回家:打开电脑,今天的事已经完成 80%。他第一次有时间坐下来读一本书。

一周盘点

  • 小工具:选题抓取器上线了,粉丝看板开工了
  • 企业微信客户群平均响应时间:从 2.3 天 → 4 小时(AI 代答常规问题 + 他只看业务类)
  • 课程答疑积压:清零
  • 新接两个商单

他的工作量没少,但 AI 把他晚上睡觉的 8 小时和白天上班的 8 小时也利用了起来。

这就是 Ralph 给一个人带来的放大器效应:把时间从"只有你醒着时才能干活"变成"24 小时都在推进"


后续章节地图

接下来 12 个章节,会逐一回答"李明轩是怎么做到的"。这里给你一张提前透露的地图:

章节李明轩面对的问题Ralph 给出的解法维度
第四章怎么把 Ralph 装到自己的电脑上ralph init、后端选择环境
第五章第一个小工具:mx add——记录一个选题灵感ralph run -p "..."开发
第六章撰稿需要"选题 / 写稿 / 审校 / 发布 / 客服"不同角色帽子系统营销+销售
第七章"草稿 → 审校 → 定稿 → 排期 → 发布"的状态流转事件总线营销
第八章发布前必须过"错别字 + 敏感词 + 配图齐全"三道关背压机制营销
第九章昨晚没写完的稿子,今晚怎么接着写记忆与任务全维度
第十章白天上班时怎么瞄一眼昨晚循环的进展可视化仪表盘全维度
第十一章4 个平台并行生成差异化内容并行工作流营销
第十二章地铁上怎么给正在跑的循环发指令Telegram 人机协作全维度
第十三章从一个选题到 4 平台全面上线的完整一天端到端实战营销+销售
第十四章把"明轩说的文风 + 审校规则"沉淀成可复用资产自定义预设开发
第十五章半年后他靠这套机制做到了什么展望

本章小结

  • 李明轩代表一类真实读者:一个人,既做开发、又做营销、又做销售
  • 他们的瓶颈不是 AI 能力,而是一天只有 24 小时,一个人只有一双手
  • Ralph 把"AI 辅助"升级成"AI 在无人值守时继续推进",让人的睡眠时间也变成生产力
  • 接下来的章节,都是这个故事的展开

一句话记住本章:Ralph 不是让你干得更快,而是让你在不干活的时候也有进展。

第四章:安装与初始化——五分钟让 Ralph 就位

📌 本章李明轩在做什么:在前面"主角故事"那一篇里,他决定把 Ralph 引入自己的自媒体工作流。这一章,我们陪他——也陪你——把 Ralph 装到电脑上。

准备工作

在安装 Ralph 之前,先确认你有以下前提条件:

操作系统要求

Ralph 目前支持:

  • macOS(推荐)
  • Linux(完全支持)
  • Windows with WSL2(通过 Windows 子系统运行)

Windows 用户注意:Ralph 需要 Unix 系统调用,不能在原生 Windows 上运行。你需要先安装 WSL2(Windows Subsystem for Linux 2),然后在 WSL2 环境里安装 Ralph。微软的官方文档有详细的 WSL2 安装指南。

需要预先安装的工具

1. 一个 AI 后端(二选一或多选)

最简单的选择是 Claude Code(Anthropic 的 CLI 工具):

# 安装 Node.js(如果还没有):去 nodejs.org 下载安装包

# 安装 Claude Code
npm install -g @anthropic-ai/claude-code

# 验证安装(会要求你登录 Anthropic 账户)
claude --version

或者使用 Kiro(速度更快,需要 AWS 账户):

# 前往 kiro.dev 按照指引安装

本书后续的示例默认使用 Claude Code 作为后端。

2. Git(大多数 Mac/Linux 系统已预装):

git --version
# 如果没有,macOS 用户:xcode-select --install
# Ubuntu/Debian:sudo apt-get install git

安装 Ralph

Ralph 提供三种安装方式,任选其一:

方式一:通过 npm 安装(推荐)

npm install -g @ralph-orchestrator/ralph-cli

安装完成后验证:

ralph --version
# 应该输出类似:ralph 2.9.x

方式二:通过 Cargo 安装(适合 Rust 用户)

如果你的电脑安装了 Rust 工具链:

cargo install ralph-cli

方式三:下载预编译二进制(最快)

前往 GitHub Releases 页面,下载适合你系统的二进制文件,解压后放到 PATH 路径里。

# 解压后
chmod +x ralph
sudo mv ralph /usr/local/bin/

运行健康检查

安装完成后,先运行 Ralph 的诊断命令,确保环境配置正确:

ralph doctor

这个命令会检查:

  • Ralph 是否正确安装
  • AI 后端(如 Claude Code)是否可以调用
  • 当前目录是否是 Git 仓库

示例输出(一切正常时):

Doctor checks for ralph.yml

  OK   config         Configuration valid
  OK   hats           No custom hats configured (solo mode)
  OK   backend:claude claude CLI available (claude)
  OK   hooks          Hooks disabled (skipping)
  OK   telegram       RObot disabled (skipping)
  OK   git            Git repository detected
  OK   paths          Workspace paths accessible
  OK   tools          Required tools available (git)
  OK   specs          No spec files found (skipping)

Result: PASS

只需看最后一行 Result: PASS/FAIL 就知道结论;上方 WARN/FAIL 行会告诉你具体哪一项需要处理。如果看到 FAIL,按提示修复再继续下一步。


在项目里初始化 Ralph

进入你想要用 Ralph 管理的项目目录(如果是新项目,先创建一个目录):

# 新项目
mkdir my-awesome-project
cd my-awesome-project
git init

# 或者进入已有的项目
cd /path/to/your/project

然后运行初始化命令:

ralph init --backend claude

这个命令只做一件事:在当前目录生成默认的 ralph.yml 配置文件。

your-project/
└── ralph.yml                  ← Ralph 配置文件

📖 名词解释 · YAML

YAML(发音 /ˈjæməl/)是一种给人类读写的配置文件格式,用缩进表达层级,不需要大括号和引号。比 JSON 更适合写配置(更易读、能写注释),Ralph 的 ralph.yml、帽子配置(第六章会讲)都用 YAML。

阅读技巧:看到冒号就是"键 = 值",看到减号开头就是列表项,缩进表示"属于上一层"。

进一步学习:维基百科:YAML

其它 Ralph 工作目录(.ralph/agent/memories.md.ralph/agent/tasks.jsonl.ralph/events-*.jsonl 等)不会立即生成,而是在第一次运行 ralph runralph tools memory add 等命令时按需自动创建。如果你希望把 Ralph 的工作状态从 Git 仓库里排除,可以手动在 .gitignore 里加一行 .ralph/


了解默认配置文件

打开生成的 ralph.yml,你会看到类似这样的内容:

# Ralph Orchestrator Configuration
# Generated by: ralph init --backend claude

cli:
  backend: "claude"                    # AI 后端选择

event_loop:
  prompt_file: "PROMPT.md"             # 默认提示词文件
  completion_promise: "LOOP_COMPLETE"  # 循环结束信号
  max_iterations: 100                  # 最多迭代次数
  # max_runtime_seconds: 14400         # 最长运行时间(秒),默认 4 小时

文件末尾还有一段被注释掉的可选配置(core.scratchpadcore.specs_dir、自定义帽子示例等),需要时再解开注释修改。

现阶段你不需要修改这个文件。我们会在第十四章详细介绍每个配置项的含义和用法。


使用预设(Preset)快速开始

Ralph 内置了多个预设工作流(Presets),这些是专家配置好的帽子组合,开箱即用:

预设名称适用场景
code-assist从任务描述或规格文档实现代码功能
pdd-to-code-assist从模糊想法出发,经过设计到代码的完整流程
review代码审查工作流
debug调试工作流
research自动研究某个主题
autoresearch更深度的自动研究

要使用预设,推荐用 -H builtin:<预设名>-H--hats 的缩写),Ralph 会从安装包自带的内置预设中直接加载:

# 使用内置的代码辅助预设
ralph run -H builtin:code-assist --prompt "添加用户登录功能"

如果你想对内置预设做定制(例如修改某个帽子的指令),可以先把上游仓库 https://github.com/mikeyobrien/ralph-orchestrator/tree/main/presets 里对应的 .yml 文件下载到本地(例如放到 presets/ 目录),然后用 -H 指向这个本地副本(-H 既接受 builtin:<name>,也接受本地文件路径或 URL):

ralph run -H presets/code-assist.yml --prompt "添加用户登录功能"

这种"下载-改-指路径"的做法适合团队沉淀自己的标准流程;新手入门时用 -H builtin:xxx 即可。

注意:旧版本里曾经流行 ralph run --config presets/code-assist.yml 这种用 --config 加载预设的写法,新版本里 --config / -c 只用于加载主配置(如 ralph.yml),预设统一走 -H。如果你看到老教程仍是 --config,请改成 -H

注意:旧版的 ralph init --preset 写法已经移除,请使用上面任一种方式在 ralph run 时指定预设。


设置你的第一个别名(可选但推荐)

为了日常使用方便,你可以在 shell 配置文件里添加一些别名:

# 在 ~/.bashrc 或 ~/.zshrc 里添加:

# 快速运行代码辅助
alias rchat='ralph run -H ~/.ralph/presets/code-assist.yml'

# 快速规划功能
alias rplan='ralph plan'

# 查看循环状态
alias rls='ralph loops'

验证安装

让我们用一个极简的测试确认 Ralph 工作正常:

# 进入一个有 git 的目录
cd /tmp && mkdir ralph-test && cd ralph-test && git init

# 初始化 Ralph
ralph init --backend claude

# 运行 preflight 检查
ralph preflight

如果 preflight 输出没有错误,说明 Ralph 已经完全就绪。


常见安装问题

问:运行 ralph 提示"command not found"

检查 npm 的全局安装路径是否在你的 PATH 里:

npm config get prefix
# 如果输出 /home/user/.npm-global,确保 /home/user/.npm-global/bin 在 PATH 里

问:ralph doctor 提示 claude 后端不可用

确保 Claude Code 已经安装并登录:

claude --version
claude login  # 如果没有登录

问:在 macOS 上提示权限问题

sudo npm install -g @ralph-orchestrator/ralph-cli

或者先配置 npm 不需要 sudo 的全局安装路径(推荐)。


本章小结

  • Ralph 支持 macOS、Linux 和 WSL2(Windows)
  • 通过 npm、Cargo 或二进制包安装
  • ralph init 在项目里创建工作空间和配置文件
  • 内置多个预设工作流,开箱即用
  • 遇到问题先运行 ralph doctor 诊断

下一章,我们陪李明轩跑通他的第一个 Ralph 任务——让 AI 写出"明轩说"工具箱的第一个命令。你也会亲身感受一次"让 AI 自己跑完"的体验。

第五章:你的第一个任务——从一句话到完整代码

本章目标

通过一个具体的实例,完整体验 Ralph 的工作流程:从你输入一句需求描述,到 Ralph 自动完成功能实现、测试、代码审查的全过程。

📌 本章李明轩在做什么:装好 Ralph 后,他决定给自己的"明轩说"工具箱(命令名 mx)写下第一个子命令——mx add,把脑子里临时冒出来的选题灵感秒速记到本地。本章我们陪他把这一条命令从一句话需求跑成可用代码。

示例任务:创建一个命令行工具 mx add,接受选题标题(可选标签),把灵感追加到本地 JSON 文件里,能够跨次运行持久化

这个任务足够简单(不需要数据库、网络等复杂依赖),但也足够完整(需要参数解析、文件读写、错误处理、单元测试)。

📖 名词解释 · JSON / JSONL

JSON(JavaScript Object Notation)是一种几乎所有编程语言都能读写的数据格式,用 {} 包住的键值对表达结构化信息:

{"title": "明天的选题", "tags": ["ai", "职场"]}

JSONL(JSON Lines)是它的"多行版":每行一条独立 JSON 记录,适合追加式写入(往文件末尾加一行,不用重写整个文件)。mx add 选这个格式就是因为每次只新增一条灵感。

进一步学习:维基百科:JSON · JSON Lines 规范


方式一:最简单的直接提示

最快的方式是直接用 ralph run 加上你的需求描述:

# 创建一个干净的项目目录
mkdir mx && cd mx
git init
ralph init --backend claude

# 直接运行
ralph run -p "创建一个 Python 命令行工具 mx,第一个子命令是 add:
接受一个位置参数(选题标题)和一个可选参数 --tag(逗号分隔的标签),
把一条灵感追加到当前目录下的 ideas.jsonl 文件里(每行一条 JSON),
每条记录包含:自动生成的 id、标题、标签列表、创建时间。
需要包含完整的错误处理和单元测试。"

-p--prompt 的缩写,后面跟你的需求描述。

Ralph 启动后会进入 TUI 观察模式,你会看到类似这样的输出(此处为示意输出,真实排版会随版本演进,重点是"迭代号 / 活跃帽子 / 事件流向"这三点):

📖 名词解释 · TUI

TUI(Text-based User Interface,文字用户界面)是在终端窗口里画出来的"可视化界面"——用字符拼接的边框、表格、进度条,支持键盘快捷键操作。比单纯滚动日志直观,又比网页 UI 轻量。Ralph 的 TUI 让你能实时看到当前哪顶帽子在工作、迭代号多少、运行了多久。

进一步学习:维基百科:Text-based user interface

===============================================================================
 ITERATION 1 | 📋 planner | 0s elapsed | 1/100
===============================================================================
  → tasks.ready

===============================================================================
 ITERATION 2 | ⚙️ builder | 1m 42s elapsed | 2/100
===============================================================================
  → review.ready  (tests=5/5 pass)

===============================================================================
 ITERATION 3 | 🧪 critic | 3m 5s elapsed | 3/100
===============================================================================
  → review.passed

===============================================================================
 ITERATION 4 | 🏁 finalizer | 4m 5s elapsed | 4/100
===============================================================================
  → LOOP_COMPLETE

Completion event LOOP_COMPLETE detected.

整个过程你不需要做任何事,喝杯水回来就完成了。


方式二:使用规划功能(推荐用于复杂任务)

对于更复杂的任务,Ralph 提供了一个专门的规划功能——ralph plan。这个功能会让 AI 通过问答方式,把你的模糊想法变成清晰的设计文档。

ralph plan "我想要一个本地网页,看到 mx add 记录的所有选题灵感,
按时间倒序显示,支持按标签筛选,双击某条可以打开详情编辑"

Ralph 的"审问者(Inquisitor)"角色会开始向你提问,一次一个,帮助澄清需求:

🎯 Inquisitor: 你希望这个看板在哪里打开?
   本地浏览器,还是做成桌面应用?

> 本地浏览器,自己电脑上看就好

🎯 Inquisitor: 灵感数量大概会到多少?
   几百条还是可能积累到上万条?

> 一个月 100 条左右,一年 1000 条到头了

🎯 Inquisitor: "详情编辑"里可以改哪些字段?
   删除功能要不要做?

> 标题、标签都能改,删除也要

... (继续问答直到需求清晰)

问答结束后,Ralph 会生成一份设计文档,保存在 .agents/scratchpad/ 目录里。然后你可以用这份文档启动实现阶段:

ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/ideas-board/"

理解 Ralph 的实时输出

Ralph 启动后会进入一个终端界面(TUI),由三个区域组成(下图为示意,实际格式随版本略有不同):

 ITERATION 3 | 🧪 critic | 3m 5s elapsed | 3/100
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
(AI 实时输出的内容在这里滚动显示)

Running tests...
  test_add_basic ... ok
  test_add_with_tags ... ok
Writing tests/test_add.py
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
:(输入 : 可以发送实时指引给 AI)

三个区域说明:

  • 顶部 HeaderITERATION 当前 · 当前活跃帽子名称(带 emoji)· 本次迭代已用时间 · 当前/最大 迭代计数
  • 中间内容区:AI 的实时输出流,可以用 j/k 上下滚动,g/G 跳到顶部/底部
  • 底部 Footer:输入 : 可以输入指引消息实时发给 AI;! 发送紧急指引(AI 必须先处理完才能继续)

实际键盘快捷键(来自内置帮助 ?):

按键功能
h / ←查看上一次迭代的输出
l / →查看下一次迭代的输出
j / ↓向下滚动输出内容
k / ↑向上滚动输出内容
g滚动到顶部
G滚动到底部(最新)
m切换鼠标模式(选择/滚动)
/开始在输出里搜索
n / N搜索结果的下一个/上一个
:发送实时指引(下次迭代时 AI 会看到)
!发送紧急指引(阻塞直到 AI 确认)
w进入波浪并行工作者视图
q退出 TUI(循环继续在后台运行)
?显示帮助

检查完成的工作

循环结束后,让我们看看 Ralph 都做了什么:

# 查看创建的文件
ls -la

应该能看到:

mx/                      # Python 包
├── __init__.py
├── __main__.py          # python -m mx 的入口
├── cli.py               # 命令行参数解析
└── storage.py           # JSONL 存储逻辑
tests/
└── test_add.py          # 单元测试
README.md                # 使用说明(如果 AI 生成了的话)
# 运行测试,验证代码质量
python -m pytest tests/ -v
tests/test_add.py::test_add_basic PASSED
tests/test_add.py::test_add_with_tags PASSED
tests/test_add.py::test_add_empty_title_fails PASSED
tests/test_add.py::test_add_persists_across_runs PASSED
tests/test_add.py::test_add_unique_ids PASSED

5 passed in 0.18s

📖 名词解释 · pytest

pytest 是 Python 里最常用的测试框架——把"这段代码的预期行为"写成一个个以 test_ 开头的函数,pytest 自动找到并逐一运行,结果用 PASSED / FAILED 标记。Ralph 依赖测试来"证明代码真的能跑":没通过测试的代码,审查者帽会拒绝接受。

进一步学习:pytest 官方文档 · 维基百科:单元测试

# 试用一下
python -m mx add "35 岁转型 AI 要避开的三个陷阱"
# ✓ 已记录(ID: 01HV5T3K2W,创建于 2026-04-21 23:18)

python -m mx add "大模型时代 RAG 到底还值不值得学" --tag ai,rag
# ✓ 已记录(ID: 01HV5T4G8Z,标签: ai, rag)

python -m mx add ""
# Error: 标题不能为空

检查 Ralph 的工作轨迹

Ralph 保存了完整的工作记录,你可以查看:

# 查看 AI 学到了什么(记忆文件)
cat .ralph/agent/memories.md

注:memories.md 不一定每次跑完都会生成——AI 只在它判断"这个经验值得跨会话记住"时才写入。如果本次只是简单功能实现,没有踩到坑,可能看不到这个文件,属正常现象。

如果 AI 确实学到了什么,你会看到类似:

# Memories

## Patterns

### mem-1776737169-c8c1
> 这个项目用 pytest 做测试,测试统一放在 tests/;灵感记录采用 JSONL(每行一条 JSON)便于追加,不用数据库
<!-- tags:  | created: 2026-04-21 -->

## Fixes

## Decisions
# 查看任务完成记录
cat .ralph/agent/tasks.jsonl
{"id":"task-1776737453-8ee8","title":"Implement mx add subcommand","description":"...","key":"code-assist:mx:step-01:implement-add","status":"closed","priority":3,"blocked_by":[],"loop_id":"primary-20260421-020921","created":"2026-04-21T02:10:53Z","started":"2026-04-21T02:11:39Z","closed":"2026-04-21T02:14:41Z"}

任务 ID 格式是 task-<Unix 时间戳>-<4 位 16 进制>,由系统生成;你在命令里引用时直接复制这个完整 ID 即可。


使用 PDD-to-Code 完整工作流

如果你想体验 Ralph 最完整的工作流——从模糊想法到可提交代码——可以使用 pdd-to-code-assist 预设:

ralph run -H builtin:pdd-to-code-assist \
  --prompt "为 mx 工具箱新增 list 子命令:
  按创建时间倒序列出所有灵感,
  支持 --tag 按标签筛选,
  支持 --limit N 限制显示条数。"

这个预设会调用 11 个不同的帽子角色,经历完整的流程:

审问者(Inquisitor)→ 架构师(Architect)→ 设计批评者(Design Critic)
→ 探索者(Explorer)→ 规划师(Planner)→ 任务写手(Task Writer)
→ 构建者(Builder)→ 批评者(Fresh-Eyes Critic)→ 终结者(Finalizer)
→ 验证者(Validator)→ 提交者(Committer)

整个流程可能需要 30 分钟到几小时,但会产出:

  • 完整的设计文档
  • 有测试覆盖的实现代码
  • 通过质量检查的代码
  • 格式规范的 Git 提交

如果任务失败了怎么办

有时候 Ralph 会遇到无法自动解决的问题,比如:

  • 需要安装某个依赖但没有权限
  • 需要你提供某个 API 密钥
  • 任务描述太模糊,AI 不知道往哪个方向走

这时候 Ralph 会输出 build.blocked 事件并停止,告诉你具体卡在了哪里:

⚠️  Loop blocked: build.blocked
Reason: "Cannot install 'click' without pip. Please run:
         pip install click
         Then resume with: ralph run -p 'continue'"

按照提示操作后,用同样的提示词重新运行,Ralph 会从记忆里知道之前做了什么,继续从断点处推进。


快速命令速览

# 基本运行
ralph run -p "你的需求描述"

# 指定预设
ralph run -H builtin:code-assist -p "需求"

# 规划模式
ralph plan "模糊的想法"

# 查看所有运行中的循环
ralph loops

# 查看任务状态
ralph tools task list

# 查看事件历史
ralph events

# 清理工作状态,重新开始
ralph clean

本章小结

你已经完成了第一次 Ralph 体验。关键的感受应该是:

  1. 你只需要描述"想要什么",不需要告诉 AI "怎么做"
  2. 循环是自动的,你可以去做别的事情
  3. 质量是有保证的,测试必须通过才算完成
  4. 过程是透明的,所有工作记录都保存在文件里

李明轩把这个套路记下了。但他很快发现:一个"通才帽子"干所有事,在自媒体场景里并不够用——选题要策划思维,写稿要文案思维,审校要挑剔思维,发布要细心执行。下一章我们介绍 Ralph 的帽子系统,让不同的 AI 角色各司其职。

第六章:帽子系统——给 AI 分配专属角色

📌 本章李明轩在做什么:他注意到一个怪现象——让一个 AI 既当选题人又当写作者又当审校,AI 会给自己的稿子打满分。他需要把创作流程拆成不同角色,让角色之间互相制衡。这就是帽子系统要解决的问题。

为什么需要角色分工

想象你在一家公司工作,有一个同事承担了所有工作:他同时是策划、开发、测试、审计、项目经理。

这种安排有一个致命的问题:没有制衡。开发者很难客观地审查自己写的代码,策划者在设计方案时很难避免自己的偏见,执行者在验收时很容易对自己已经完成的工作"手下留情"。

Ralph 的帽子系统解决了这个问题:同一个 AI,通过扮演不同角色,实现了内部制衡


帽子是什么

在 Ralph 里,一顶"帽子"(Hat)是一个 AI 角色配置,包含:

hats:
  planner:                           # 帽子的内部 ID
    name: "📋 Planner"              # 显示名称
    description: "制定实现计划"      # 角色描述
    triggers: ["work.start"]         # 触发条件(监听哪些事件)
    publishes: ["tasks.ready"]       # 完成后发布什么事件
    default_publishes: "tasks.ready" # 默认发布的事件
    instructions: |                  # 角色指令(告诉 AI 怎么工作)
      你是规划师。你的职责是...

每顶帽子定义了一个 AI 的工作边界

  • 在什么条件下被激活(triggers)
  • 应该做什么(instructions)
  • 完成后触发什么(publishes)

内置预设中的帽子角色

Ralph 的 code-assist 预设包含四顶核心帽子:

🎩 规划师(Planner)

触发条件work.start(循环刚开始)或 queue.advance(需要推进任务队列)

职责

  • 读取你的需求描述
  • 把需求分解成有编号的实现步骤
  • 为当前步骤创建具体的运行时任务
  • 把任务信息传递给构建者

典型输出:一个 plan.md 文件,包含像这样的内容:

# 实现计划

1. 步骤一:创建项目骨架
   - 创建入口文件
   - 配置依赖
   - 演示目标:程序能启动并显示帮助信息

2. 步骤二:实现核心功能
   - 实现文字转换逻辑
   - 添加参数解析
   - 演示目标:核心命令能正常执行

3. 步骤三:完善和测试
   - 添加错误处理
   - 编写单元测试
   - 演示目标:所有测试通过

关键约束:规划师只能规划,不能实现。这个角色分离防止了"规划者思维定势"影响实现决策。


⚙️ 构建者(Builder)

触发条件tasks.ready(有新任务),或 review.rejected(被审查者打回来了),或 finalization.failed(终结者判定需要继续)

职责:严格遵循 TDD(测试驱动开发)流程:

RED   → 先写失败的测试
GREEN → 写最少的代码让测试通过
REFACTOR → 清理代码,保持测试绿色

关键约束

  • 每次只做一个任务,不允许批量做
  • 测试必须先于实现
  • 不能添加需求以外的功能

构建者的每个输出都要经过审查者的检验,不能绕过。


🧪 审查者(Critic)

触发条件review.ready(构建者完成了一个任务)

职责:以"全新眼光"(Fresh Eyes)审查构建者的工作:

  1. 需求符合度:实现是否真的满足了任务要求?
  2. 代码质量:是否有多余的代码(违反 YAGNI)?是否过度复杂(违反 KISS)?
  3. 验证:自己重新运行测试,不相信构建者的"测试通过了"声明
  4. 实际测试:运行实际的程序,而不只是看代码

关键约束

  • 必须假设构建者没有检查过"显而易见"的东西
  • 不允许"有小问题但以后再修"的审查结论
  • 必须实际运行程序,不能只做静态代码审查

审查者可以发布两种结果:

  • review.passed:这个任务合格,交给终结者判断是否整体完成
  • review.rejected:不合格,打回给构建者重做,并附上具体原因

🏁 终结者(Finalizer)

触发条件review.passed(某个任务通过了审查)

职责:做出最终判断:整体任务是否完成?

终结者比审查者要求更严格,因为它看的是全局,不只是最后一个任务:

  1. 检查所有任务是否都完成了
  2. 运行完整的测试套件
  3. 检查代码质量(YAGNI/KISS/代码风格)
  4. 判断是否还有需求没有实现

可能的结论

  • queue.advance:这个步骤完成了,推进到下一步
  • LOOP_COMPLETE:全部完成,循环结束
  • finalization.failed:还有工作没做完,发回给构建者

PDD 预设中的完整帽子团队

如果你使用 pdd-to-code-assist 预设,会有一支更完整的帽子团队(11 顶帽子)参与工作:

设计阶段:
  🎯 审问者(Inquisitor)  → 问你问题,明确需求
  💭 架构师(Architect)   → 根据回答设计方案
  ⚖️ 设计批评者(Design Critic) → 挑战设计方案

探索阶段:
  🔍 探索者(Explorer)    → 研究代码库,找出模式和约束

实现阶段:
  📋 规划师(Planner)     → 制定测试策略和实现计划
  📝 任务写手(Task Writer)→ 把计划转成代码任务文件
  ⚙️ 构建者(Builder)     → TDD 实现
  🧪 审查者(Critic)      → 每个任务的代码审查
  🏁 终结者(Finalizer)   → 任务队列管理

验收阶段:
  ✅ 验证者(Validator)   → 最终质量关卡
  📦 提交者(Committer)   → 创建规范的 Git 提交

帽子的工作流程图

把两种预设放在一张图上对比——code-assist 只跑中间的"实现阶段",pdd-to-code-assist 跑完整的四阶段

需求 描述 📐 设计阶段 🎯 审问者 ↓ 问答澄清需求 💭 架构师 ↓ 生成设计 ⚖️ 设计批评者 仅 PDD 流程 🔭 探索 🔍 探索者 研究代码库 仅 PDD 流程 ⚙️ 实现阶段(核心) 📋 规划师 → 📝 任务写手 ⚙️ 构建者 ↕ 审查循环 🧪 审查者 🏁 终结者 code-assist 只有这一段 📦 验收阶段 ✅ 验证者 ↓ 最终质量关 📦 提交者 规范 git commit 仅 PDD 流程 code-assist 预设(4 顶帽子) pdd-to-code-assist 额外阶段(11 顶帽子)

实现阶段内部的事件环(两种预设共享)

上图里的"实现阶段"是两种预设共有的核心,内部还有一个小循环:

📋 规划师 分解任务 ⚙️ 构建者 TDD 实现 🧪 审查者 挑错 🏁 终结者 全局判断 tasks.ready review.ready review.passed DONE review.rejected(打回返工) queue.advance(推进下一步任务)

这张图只是"实现阶段"内部的放大视图。完整的事件流细节(包括所有 9 个事件名和 4 顶帽子的 triggers / publishes)在第七章会逐行从 yaml 源码里拆解。


查看可用帽子

讲了这么多帽子,怎么知道你这台电脑上现在能用哪些?Ralph 提供了一组"帽子目录"命令。

列出所有内置预设

ralph init --list-presets

会输出当前 Ralph 版本官方支持的内置帽子集(5 个核心 + 一些内部 / 实验性预设):

Supported built-in hat collections:
  code-assist          — 默认的 TDD 实现(planner / builder / critic / finalizer)
  debug                — 根因调试(investigator / tester / fixer / verifier)
  research             — 只读研究(researcher / synthesizer)
  review               — 对抗式代码审查(reviewer / analyzer)
  pdd-to-code-assist   — 从想法到代码的完整管道(11 顶帽子)

上游仓库 presets/ 目录里其实还有 bugfixdeploydocsfeaturefresh-eyespr-reviewrefactorspec-drivenwave-review 等更多预设。它们没进官方推荐清单(避免文档膨胀),但同样可以用——直接 -H builtin:<name> 试,跑得通就能用;或者把仓库里对应的 .yml 下载到本地按需修改。

列出当前配置激活的帽子

ralph hats list
ralph hats list --format json   # 给脚本读

读取当前目录 ralph.yml-H 指定的预设,告诉你这次循环会用到哪些帽子(含内置 + 你自定义的)。

查看某顶帽子的完整指令

ralph hats show planner

打印这顶帽子的 emoji、触发事件、发布事件、完整 instructions——相当于"翻开这个角色的剧本看一眼"。当你想知道某个内置帽子背后的提示词到底是怎么写的,这是最直接的方式。

把帽子工作流可视化成图

ralph hats graph                     # 默认 ASCII / Unicode 流程图
ralph hats graph --format mermaid    # 输出 Mermaid 文本,贴到任何支持 Mermaid 的工具里渲染

这是理解"事件在帽子之间怎么流动"最快的方式,比逐行读 yaml 直观得多。

验证帽子配置

ralph hats validate

不实际启动循环,只检查事件连线是否完整:有没有"发布的事件没人订阅"、"订阅的事件没人发布"、"循环开不起来"这类配置错误。改完帽子配置后第一时间跑这个,能省掉一晚上 debug。


自定义帽子

除了使用内置预设,你也可以创建自己的帽子集合——这是 Ralph 适配你个人工作流的关键能力。比如李明轩想给"明轩说"加一顶"敏感词审校帽",或者把内容流水线的 6 顶帽子打包复用,就需要写自己的帽子文件。

第一步:写一个帽子集合文件

帽子集合是一个 YAML 文件,至少包含两个部分:event_loop(这个集合的入口和出口事件)和 hats(具体的帽子定义)。

最小可用例子:

# .ralph/hats/compliance.yml

event_loop:
  starting_event: "build.start"        # 循环从哪个事件开始
  completion_promise: "LOOP_COMPLETE"  # 收到哪个事件就算完工

hats:
  compliance_reviewer:
    name: "📜 合规审查者"
    triggers: ["review.ready"]
    publishes: ["compliance.passed", "compliance.failed"]
    instructions: |
      你是合规审查者。检查以下几点:
      1. 所有用户输入是否经过了 SQL 注入防护
      2. 敏感信息(密码、API 密钥)是否绝不出现在日志里
      3. 错误信息是否对终端用户安全(不暴露系统信息)

      只有三项全部通过,才能发布 compliance.passed。
      任何一项失败,发布 compliance.failed 并说明原因。

第二步:放在哪里

Ralph 不会自动扫描任何目录去发现你的帽子文件——你必须用 -H 显式告诉它去哪里加载。但社区惯例是把帽子文件放在以下两个位置之一:

位置适合
.ralph/hats/<name>.yml项目级帽子(跟着仓库走,团队共享)
~/.ralph/hats/<name>.yml个人级帽子(你自己常用,跨项目共用)

这只是约定,Ralph 不强制。你想放在 presets/ 或者别的目录都可以——重要的是 -H 后面写对路径。

第三步:加载它

-H 接受三种来源:内置名(builtin:<name>)、本地文件路径、URL。每次只能指定一个 -H

# 加载项目级自定义帽子集合
ralph run -c ralph.yml -H .ralph/hats/mx-content.yml -p "你的需求"

# 加载个人级自定义帽子集合
ralph run -c ralph.yml -H ~/.ralph/hats/mx-content.yml -p "你的需求"

⚠️ 想在内置预设之上"加补丁"?没有这种叠加机制

-H 在命令行里是单值参数(不像 -c 可以多个)。而且 -H 文件的 hats: 段会整体替换 -c 里的 hats: 段,不是逐帽子合并。所以 ralph run -H builtin:code-assist -H my.yml 这种写法不能让两边的帽子共存。

要"在内置预设之上加东西",正确做法是——把 上游仓库.yml 文件下载到本地,在本地文件里加自己的帽子并改相关帽子的 triggers(这一点第七章最后一节会详细讲——仅仅加一顶新帽子是不够的,需要重新连线事件流),然后用这个 fork 出来的文件作为唯一的 -H 源:

curl -L -o .ralph/hats/mx-review.yml \
  https://raw.githubusercontent.com/mikeyobrien/ralph-orchestrator/main/presets/code-assist.yml
# 编辑 mx-review.yml,加新帽子 + 改下游 triggers
ralph run -c ralph.yml -H .ralph/hats/mx-review.yml -p "..."

第四步:验证再上场

写完帽子文件后,先验证再启动循环:

# 检查事件连线是否合理
ralph hats validate -H .ralph/hats/compliance.yml

# 用图直观确认事件流
ralph hats graph -H .ralph/hats/compliance.yml --format mermaid

想每次都自动带上某个自定义帽子?

如果你不想每次 ralph run 都重复打 -H,有两种办法:

办法 A:单文件模式(向后兼容写法)——直接把 event_loop / hats 写进 ralph.yml 里:

# ralph.yml
event_loop:
  starting_event: "build.start"
  completion_promise: "LOOP_COMPLETE"

hats:
  my_custom_hat:
    name: "..."
    triggers: [...]
    # ...

这样直接 ralph run -p "..." 就会用 ralph.yml 里的帽子,不再需要 -H

办法 B:写一个 shell 别名

# ~/.zshrc 或 ~/.bashrc
alias mxrun='ralph run -H ~/.ralph/hats/mx-content.yml'

之后 mxrun -p "..." 就等于自动带上了那顶帽子。

实际怎么用:李明轩的 "明轩说" 帽子集

李明轩为自己的内容流水线写了 6 顶帽子,全部放在项目下的 .ralph/hats/mx-content.yml

.ralph/hats/
└── mx-content.yml      # 选题 / 撰写 / 审校 / 排版 / 发布 / 客服 6 顶帽子

平时跑:

ralph run -H .ralph/hats/mx-content.yml -p "把今天的草稿改成 4 平台版本"

如果某次他想用内置的 code-assist 来给 mx 工具本身加功能,就不带 -H mx-content.yml,临时换成 -H builtin:code-assist——同一个项目可以根据当下的工作类型切换不同的帽子集,互不冲突。


帽子配置的关键参数

除了基本的触发和发布,帽子还支持一些高级配置:

并发数(concurrency):允许同一顶帽子同时处理多个任务(并行执行,详见第十一章):

hats:
  reviewer:
    concurrency: 4  # 同时审查 4 个文件

聚合(aggregate):等待所有并行工作完成后再激活:

hats:
  synthesizer:
    aggregate:
      mode: wait_for_all
      timeout: 300  # 最多等待 300 秒

本章小结

  • 帽子是 Ralph 里的 AI 角色配置,每顶帽子有明确的职责边界
  • code-assist 预设有四顶帽子:规划师、构建者、审查者、终结者
  • pdd-to-code-assist 预设有 11 顶帽子,覆盖从想法到提交的完整流程
  • 帽子通过事件总线协作,每顶帽子只能做自己"职责内"的事
  • 可以自定义帽子来实现特定业务需求

李明轩的"选题 / 撰写 / 审校 / 排版 / 发布 / 客服"六顶帽子已经配好。但他马上遇到下一个问题:这些帽子之间怎么知道谁做完了、该谁接手?下一章讲事件总线——帽子们的"共享公告板"。

第七章:事件总线——AI 团队的内部通讯机制

📌 本章李明轩在做什么:他设计了明轩说的内容流水线——一条稿子要经过"草稿 → 审校 → 定稿 → 排期 → 发布"五个状态。他需要一个机制让每个状态变化自动触发下一环。这就是事件总线。

事件的比喻:一个繁忙的厨房

想象一个餐厅后厨:

  • 服务员把点餐单放到一个共享的架子上
  • 厨师 A 专做冷菜,看到冷菜订单就开始工作,完成后挂上 "冷菜就绪" 的标签
  • 厨师 B 专做热菜,看到 "冷菜就绪" 就知道可以开始配搭
  • 传菜员看到 "出餐就绪" 就把菜端出去

这个 "共享架子" 就是 Ralph 里的事件总线,"订单"、"就绪标签" 就是事件。每个角色(帽子)只关注和自己相关的事件,不需要知道整个厨房在做什么。


帽子和事件的三角关系

这是理解 Ralph 最关键的一张图。每顶帽子在 yaml 里都有两个核心字段:

  • triggers——这顶帽子订阅哪些事件(事件流入)
  • publishes——这顶帽子完成后会发出哪些事件(事件流出)
🎩 某顶帽子 一个 AI 角色 事件 A 事件 B 事件 C 事件 D triggers(订阅) 任一事件出现,帽子被激活 publishes(发布) 激活后产出这些事件

加上 event_loop 里的两个锚点:

  • starting_event——Ralph 启动时自动发出的第一个事件,整个循环从这里开始
  • completion_promise——收到这个事件,Ralph 就认为任务完成,停止循环

整个事件系统就是靠这四个字段拼出来的——triggers / publishes / starting_event / completion_promise。理解了这个三角关系,再去看任何一个预设的 yaml,你都能当场画出它的流程图。


事件的结构

每个在总线上流动的事件都包含以下信息:

事件名称:review.ready          ← 发生了什么
来源帽子:builder               ← 谁触发的
目标帽子:critic                ← 谁来处理(可以是通配符)
时间戳:2026-04-21 10:23:41    ← 什么时候发生的
载荷(Payload):               ← 附带的数据
  {
    "task_id": "task-003",
    "task_key": "code-assist:mx:step-02:impl",
    "files_changed": ["src/main.py", "tests/test_main.py"],
    "summary": "Implemented text conversion with all tests passing"
  }

下面一节,我们从真实的预设代码出发,把这套关系在一个具体例子里走一遍。


拆解 code-assist:四顶帽子如何用事件串起来

code-assist 是 Ralph 的默认预设,包含 4 顶帽子。从官方 presets/code-assist.yml 里把每顶帽子的 triggers / publishes 抽出来(指令正文省略):

event_loop:
  starting_event: "build.start"       # 循环一启动就发这个事件
  completion_promise: "LOOP_COMPLETE" # 收到这个事件就结束

hats:
  planner:
    triggers:  ["build.start", "queue.advance"]
    publishes: ["tasks.ready"]

  builder:
    triggers:  ["tasks.ready", "review.rejected", "finalization.failed"]
    publishes: ["review.ready", "build.blocked"]

  critic:
    triggers:  ["review.ready"]
    publishes: ["review.passed", "review.rejected"]

  finalizer:
    triggers:  ["review.passed"]
    publishes: ["queue.advance", "finalization.failed", "LOOP_COMPLETE"]

把这些关系连起来,就是一张完整的状态流程图:

⚠️ 人工介入 Telegram / 终端 ralph run 启动 📋 Planner 规划师 ⚙️ Builder 构建者 🧪 Critic 审查者 🏁 Finalizer 终结者 ✅ 完成 build.start tasks.ready review.ready review.passed LOOP_COMPLETE review.rejected(审查打回) finalization.failed(全局未完成,继续改) queue.advance(当前步完,推进下一步) build.blocked happy path 审查 / 终结打回 循环推进 人工介入

读图:四条路径

1. 主路径(灰色实线)ralph run 发出 build.start,触发 Planner;Planner 分解任务后发 tasks.ready,触发 Builder;Builder 写完代码发 review.ready,触发 Critic。这条路径是一次任务默认会走的顺序。

2. Happy path(绿色实线):Critic 审过了,发 review.passed,触发 Finalizer;Finalizer 确认整个任务全部交付,发 LOOP_COMPLETE,Ralph 停止循环。

3. 返工(红色):有两个返工来源——

  • Critic 审不过:发 review.rejected(红色实线),触发 Builder(注意 Builder 的 triggers 里正好有 review.rejected,这就是事件如何"找到"回去的路径)
  • Finalizer 判定全局还差事:发 finalization.failed(红色虚线),也是触发 Builder(Builder 同样订阅了它)

4. 循环推进(灰色虚线):Finalizer 判定当前步骤完成但还有后续步骤,发 queue.advance触发 Planner(Planner 订阅了 build.startqueue.advance 两个事件,所以从头来和从中间推进都能工作)。

特殊路径(橙色):Builder 遇到无法自主解决的问题,发 build.blocked,触发人工介入流程(Telegram 推送等)。


关键观察:事件和帽子是多对多的关系

重点看 Builder 那一行:

builder:
  triggers: ["tasks.ready", "review.rejected", "finalization.failed"]

Builder 同时订阅 3 个事件。这就是为什么"新任务""审查打回""终结打回"都能让 Builder 开工——它们都是合法的激活入口。

再看 Planner:

planner:
  triggers: ["build.start", "queue.advance"]

Planner 订阅"启动"和"推进"两个事件——第一次由 build.start 唤醒,之后每步完成都由 queue.advance 再次唤醒。

这也是为什么"帽子 + 事件"比"函数调用"更有表达力:函数调用只有一个入口,而帽子可以有任意多个入口,只要事件名对得上就会被触发。


对比:research 预设的极简循环

code-assist 有点复杂。再看一个简单的——research 预设,只有 2 顶帽子:

event_loop:
  starting_event: "research.start"
  completion_promise: "RESEARCH_COMPLETE"

hats:
  researcher:
    triggers:  ["research.start", "research.followup"]
    publishes: ["research.finding"]

  synthesizer:
    triggers:  ["research.finding"]
    publishes: ["research.followup", "RESEARCH_COMPLETE"]
ralph run 启动 🔍 Researcher 研究者 📊 Synthesizer 综合者 ✅ 完成 research.start research.finding RESEARCH_COMPLETE research.followup(还有未答的问题,回去再研究)

读图:Researcher 研究完一轮,发 research.finding;Synthesizer 综合后判断——如果还有未答的问题,发 research.followup(触发 Researcher 再研究一轮);如果答完了,发 RESEARCH_COMPLETE,Ralph 停止循环。

两顶帽子,一个往返循环,靠 research.followup 这个事件把"Synthesizer 决定再来一轮"的指令传回给 Researcher——这就是事件总线最纯粹的样子。


时间线:一次循环里事件真实的流动顺序

时间线 ───────────────────────────────────────────────►

t=0     ralph run 发布 build.start
t=30s   Planner 激活,读需求,分解任务 → 发 tasks.ready
t=90s   Builder 激活,写测试 → 写代码 → 重构 → 发 review.ready
t=150s  Critic 激活,复跑测试,挑错 → 发 review.rejected
        (Critic 发现测试少了一个边界条件)
t=180s  Builder 再次激活(因为订阅了 review.rejected)
        补上边界测试和实现 → 发 review.ready
t=240s  Critic 再次激活,审查通过 → 发 review.passed
t=270s  Finalizer 激活,检查整体 → 发 LOOP_COMPLETE
t=271s  Ralph 收到 completion_promise,停止循环

注意 Builder 在 t=90s 和 t=180s 都被激活——第一次由 tasks.ready 触发,第二次由 review.rejected 触发。同一个帽子,不同的触发源,做的事情略有不同(一次是写新代码,一次是修旧代码)——这种行为差异由帽子的 instructions 里根据 <pending event> 判断。


查看实时事件流

Ralph 运行时按 e 键可以看到实时的事件流:

Events History
──────────────────────────────────────────────────────────────
[10:23:00] build.start              (source: ralph)
[10:23:31] tasks.ready              (source: planner)
           payload: {"task_id":"task-001","task_key":"step-01:scaffold"}
[10:25:42] review.ready             (source: builder)
           payload: {"task_id":"task-001","files":["main.py","test_main.py"]}
[10:27:15] review.rejected          (source: critic)
           payload: {"reason":"Missing error handling for empty input"}
[10:29:38] review.ready             (source: builder)
[10:30:52] review.passed            (source: critic)
[10:31:10] queue.advance            (source: finalizer)
[10:31:11] tasks.ready              (source: planner)
──────────────────────────────────────────────────────────────

也可以在循环结束后用命令回溯:

ralph events                 # 查看全部事件
ralph events --file <path>   # 查看指定 events 文件(每个循环都有自己的)

人工事件注入

Ralph 最强大的功能之一:你可以在循环运行时,手动向事件总线注入事件,实现对循环的实时干预。

# 在另一个终端窗口,向正在运行的循环注入指引
# 语法:ralph emit <事件名> "<载荷>"
ralph emit human.guidance "注意:这个项目不允许使用 requests 库,请改用内置的 urllib"

AI 会在下次迭代时收到这个指引,并调整工作方向。这就是第十二章 "人机协作" 功能的基础:你不需要停掉循环,在恰当的时候发送一个事件,AI 就会 "知道" 你的新要求。


事件与 Telegram

如果你配置了 Telegram 机器人(第十二章详细讲),事件系统会变得更强大:

  • human.interact:AI 可以通过 Telegram 向你提问,循环暂停等待你回答
  • human.response:你在 Telegram 上的回答会被注入回循环
  • human.guidance:你在 Telegram 上发的任何消息都会成为 AI 的 ## ROBOT GUIDANCE

自定义事件:给默认流插一顶帽子

假设李明轩用的是 code-assist 预设,但他想加一道额外的"合规审查"关卡——每次 Builder 写完代码,除了 Critic 挑技术错,他还想让另一顶帽子专门检查"是否在日志里泄漏了 API 密钥""是否有 SQL 注入风险"。

先纠正一个陷阱:并行订阅 ≠ 并行门禁

你的第一反应可能是:让 Compliance 也订阅 review.ready,和 Critic 并行跑。这是一个诱人的陷阱——它能跑,但拦不住不合规的代码

🔬 事件扇出的真实语义(来自 Ralph 源码 event_bus.rs

review.ready 被发布时,事件总线确实会把它复制到所有订阅者的待办队列里——这点没错。但每次循环迭代只激活一顶帽子(按 hat ID 字母序挑一个),所以 Compliance 和 Critic 实际是依次跑的,不是真正并行。

更关键的一点——没有"等所有订阅者都跑完"的内置机制。Critic 一跑完就发 review.passed,Finalizer 订阅的正是这个事件,立刻被触发——哪怕下一次迭代 Compliance 才开始跑,哪怕 Compliance 最后发了 compliance.failed,Finalizer 根本不看那个事件。

aggregate: wait_for_all 字段是为"一顶帽子开 N 个并行实例"(波浪机制,第十一章)设计的,不是用来做"多顶帽子的 AND 门"

所以"让 Compliance 也订阅 review.ready"这种改法,Compliance 只能做旁观式日志 / 事后通知,不能真的拦下任何东西。要真的门禁,必须把 Compliance 串进事件流里。

正确做法:串行插入 + 改下游 triggers

让 Compliance 订阅 Critic 发出的 review.passed,做完合规后发一个新事件 compliance.passed,然后把 Finalizer 的 triggers 从 review.passed 改成 compliance.passed。这样下游只有等合规也过了才会推进。

⚙️ Builder 构建者 🧪 Critic 内置 · 技术审 📜 Compliance 新增 · 合规审 🏁 Finalizer 内置 ⚠️ trigger 改过 ✅ 完成 review.ready review.passed compliance.passed LOOP_COMPLETE review.rejected(技术不过) compliance.failed(合规不过,也要让 Builder 订阅它) ⚠️ 关键改动:把 Finalizer 的 triggers 从 [review.passed] 改成 [compliance.passed], 并把 Builder 的 triggers 补上 compliance.failed,否则合规失败就成孤儿事件。 这两步动了下游 hat 的订阅关系,门禁才真正生效。

对应的 yaml:

hats:
  # Critic 保持内置不变
  critic:
    triggers: ["review.ready"]
    publishes: ["review.passed", "review.rejected"]

  # 新增:Compliance 串在 Critic 之后
  compliance:
    triggers:  ["review.passed"]          # ← 只在技术审过之后才跑
    publishes: ["compliance.passed",
                "compliance.failed"]
    instructions: |
      你是合规审查者。检查:
      1. 日志 / 错误信息里有没有泄漏密钥、token、密码
      2. 用户输入有没有 SQL / 命令注入风险
      3. 敏感字段是否加密

      全过发 compliance.passed;任一不过发 compliance.failed。

  # 关键改动 ①:Finalizer 改成等合规事件
  finalizer:
    triggers: ["compliance.passed"]       # ← 原本是 review.passed,改了
    publishes: ["queue.advance", "finalization.failed", "LOOP_COMPLETE"]

  # 关键改动 ②:Builder 要订阅 compliance.failed,不然合规不过就没人接
  builder:
    triggers: ["tasks.ready", "review.rejected",
               "finalization.failed", "compliance.failed"]
    publishes: ["review.ready", "build.blocked"]

什么时候"并行订阅"才有意义

如果新帽子只做日志 / 统计 / 通知(不拦流程),那并行订阅就很合适。比如:

hats:
  stats_logger:
    triggers:  ["review.ready", "review.passed", "review.rejected"]
    publishes: []                         # 不发任何事件,纯粹旁观
    instructions: |
      把每次 review 事件的时间戳和结果写进 .ralph/review-stats.jsonl,用来后续分析。

这种"旁观者"帽子不需要下游等它,因为它根本不是决策链的一环——它是挂在事件总线上的一个 tap(取样点)。区分"旁观者"还是"门禁",是设计自定义帽子的第一件事

加载方式的真相:-H 不能叠加

另一个容易踩坑的地方——-H 每次只能指定一个源。而且 -Hhats: 段会整体替换 -c 里的 hats: 段,不是逐帽子合并。所以你不能这样"打补丁":

# ❌ 这样写不会"code-assist + compliance"叠加——
# -H 只接受一个值,多余的 -H 会被丢弃;即使生效,后面的也会整体替换前面的 hats 段
ralph run -H builtin:code-assist -H .ralph/hats/compliance.yml -p "..."

正确做法是把内置预设 fork 到本地,在本地文件里直接改:

# 第一次:下载内置 preset 作为起点
curl -L -o .ralph/hats/mx-review.yml \
  https://raw.githubusercontent.com/mikeyobrien/ralph-orchestrator/main/presets/code-assist.yml

# 然后打开 .ralph/hats/mx-review.yml,按上面那段 yaml 加 compliance 帽 + 改 finalizer / builder 的 triggers

# 启动时只用这一个 -H
ralph run -c ralph.yml -H .ralph/hats/mx-review.yml -p "..."

进阶:完全自定义的事件链

你也可以不沿用内置事件名,从头发明自己的事件链,约定用 主题.动作 格式:

event_loop:
  starting_event: "content.start"
  completion_promise: "CONTENT_PUBLISHED"

hats:
  writer:
    triggers:  ["content.start"]
    publishes: ["draft.ready"]
  reviewer:
    triggers:  ["draft.ready"]
    publishes: ["draft.approved", "draft.rejected"]
  publisher:
    triggers:  ["draft.approved"]
    publishes: ["CONTENT_PUBLISHED"]

这里的 content.startdraft.readydraft.approved 都是自创的——Ralph 不关心事件叫什么,只关心谁订阅了它、谁会发出它。事件名是帽子之间的"约定接口",想怎么命名都可以。

命名的实用建议:

  • . 分隔主题和动作(draft.approved 而不是 draft_approved
  • 动作尽量用过去分词或形容词(ready / passed / approved / failed),读起来像"某件事刚发生"
  • 全大写保留给终止信号LOOP_COMPLETE / RESEARCH_COMPLETE / CONTENT_PUBLISHED)——让 Ralph 一眼看出这是出口事件

事件的可靠性保证

一个常见问题:如果 AI 崩溃或超时,事件会丢吗?

不会。Ralph 把所有事件持久化保存在 .ralph/events*.jsonl 里。如果循环意外中断,重启时 Ralph 会从磁盘把上次的事件流读回来,从中断处继续,而不是从头来过。

这正是"磁盘是状态,Git 是记忆"法则的具体体现——事件总线的全部历史都可以在磁盘上追溯,没有任何"只在内存里"的临时状态。


本章小结

  • 帽子和事件是多对多的关系——每顶帽子订阅多个事件,发布多个事件,事件通过 triggers / publishes 把帽子连成网络
  • event_loop.starting_eventcompletion_promise 是网络的入口和出口
  • 默认的 code-assist 预设里,4 顶帽子通过 build.start / tasks.ready / review.ready / review.passed / review.rejected / queue.advance / finalization.failed / LOOP_COMPLETE / build.blocked 这 9 个事件连成一张状态机
  • 多顶帽子可以订阅同一个事件——这是插自定义补丁的核心机制
  • 所有事件都写磁盘,循环中断可恢复

李明轩的内容流水线通畅地跑起来了。但他立刻想到一个问题:如果 AI 把一篇有错别字、配图残缺的稿子当成"定稿"发出来,会毁了他的粉丝口碑。他需要硬门禁。下一章讲背压机制——让不合格的内容根本无法通过。

第八章:背压机制——让 AI 学会自我纠错

📌 本章李明轩在做什么:他给自己的发布流程立了三条铁律——错别字零容忍、敏感词必须过审、4 个平台的配图必须齐全。这一章的背压机制就是把这些铁律"硬塞"进 AI 的工作流里,不合格就打回重做。

一个关于关卡的比喻

想象一个工厂的流水线,生产汽车零件。每个工序之间,有一个质检员:

  • 零件到达质检站
  • 质检员检查是否符合规格
  • 符合:零件继续进入下一道工序
  • 不符合:零件被打回,重新加工,不合格的零件永远不会流向下一工序

这就是"背压"(Backpressure)的物理含义:上游的压力被限制,不符合质量的东西不会向下游传递

在 Ralph 里,背压机制确保:不合格的代码不会被当成"任务完成"接受

⚙️ AI 产出 写代码 / 改文稿 🚦 质量关卡(背压) ☑️ 跑测试(pytest) ☑️ 跑 lint / 格式检查 ☑️ 跑类型检查 ☑️ 跑项目自定义门禁 ✅ 放行 进入下一顶帽子 ❌ 打回 附上失败原因 下一步 (审查 / 提交) 完成 全过 任一项不过 同一顶帽子再做一轮,直到通过

关卡的设计哲学是——Ralph 不告诉 AI "怎么做对",只告诉它 "什么算做对"。AI 有完全自由去决定怎么实现,但交付物必须能过关。过不了的那一刻,压力传回给 AI,它必须自己修。


背压的实现方式:通过帽子指令,而非自动执行

Ralph 的背压机制不是由 Ralph 框架直接拦截并执行命令行检查——而是通过帽子指令告诉 AI:在发出"完成"信号之前,必须自己运行验证命令,并把命令的实际输出结果附在事件载荷里作为证据。

这种设计哲学正是"背压优于规定"原则的体现:

  • 规定式(脆弱):Ralph 框架在特定节点运行固定命令
  • 背压式(健壮):AI 自己负责验证,把证据附在事件里,审查者帽子再核实证据

在帽子指令里定义验证要求

hats:
  builder:
    name: "⚙️ 构建者"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现分配的任务。

      ## 背压要求

      在发出 review.ready 之前,你必须已完成:
      - tests: 通过(运行 python -m pytest)
      - lint: 通过(运行 flake8 .)
      - typecheck: 通过(运行 mypy src/)

      在事件载荷里附上证据:
      "tests: pass, lint: pass, typecheck: pass"
      
      不要仅声称"测试通过",要提供实际的命令输出摘要。

在事件载荷里携带证据

AI 在完成工作后,用 ralph emit 发出完成信号,并附上验证证据:

# AI 运行这条命令来完成背压验证并发出事件
ralph emit "review.ready" "tests: pass (5/5), lint: pass, typecheck: pass"

审查者帽子核实证据

审查者帽子(Critic)被设计为不信任构建者的自我声明——它会重新运行验证命令来独立确认:

hats:
  critic:
    name: "🧪 审查者"
    triggers: ["review.ready"]
    instructions: |
      不要相信构建者说"测试通过了"。
      重新运行测试,自己验证。
      如果测试失败,发出 review.rejected 并说明原因。

一个实际的背压流程

让我们用例子看看背压是如何工作的:

场景:AI 实现了一个功能,但测试实际上没有全部通过。

[Iteration 6/150]

⚙️ 构建者 完成工作:
   → 实现了 validate_email() 函数
   → 运行 pytest,声称"通过"(实际边界测试失败了)
   → 发出 review.ready 事件,载荷:"tests: pass"

[Iteration 7/150]

🧪 审查者 独立检查:
   → 自己运行 python -m pytest
   → 发现:
     FAILED tests/test_validate.py::test_empty_email
     FAILED tests/test_validate.py::test_none_input
   → 发出 review.rejected
     原因:"声称测试全部通过,但边界情况测试失败"

[Iteration 8/150]

⚙️ 构建者 重新工作:
   → 读取 review.rejected 的具体原因
   → 修复 validate_email() 的边界情况处理
   → 重新运行测试,实际全部通过(5/5)
   → 发出 review.ready,载荷:"tests: pass (5/5)"

[Iteration 9/150]

🧪 审查者 再次独立验证:
   → 运行 pytest:5 passed
   → 发出 review.passed ✅

整个背压循环完全自动,不需要你介入。


背压验证的常见类型

在帽子指令里,你可以要求 AI 运行任何类型的验证命令:

测试类

hats:
  builder:
    instructions: |
      完成实现后,在发出完成事件前必须通过:
      - Python 项目:python -m pytest -v
      - Node 项目:npm test
      - Rust 项目:cargo test --all
      把实际输出结果附在事件载荷里。

格式与 Lint 类

instructions: |
  代码格式必须通过检查:
  - Python:black --check . && isort --check-only .
  - JavaScript:npm run lint
  - Rust:cargo fmt --check && cargo clippy -- -D warnings

类型检查类

instructions: |
  类型检查必须通过:
  - Python:mypy src/
  - TypeScript:tsc --noEmit
  - Rust:cargo check(无 warnings)

综合验证示例(Rust 项目)

下面是 ralph-orchestrator 项目本身的实际使用方式——注意背压验证要求写在 Builder 帽子的 instructions 里:

hats:
  builder:
    name: "⚡ Builder"
    instructions: |
      Before emitting subtask.done, ALL must pass:
      1. cargo fmt --all -- --check — formatting
      2. cargo clippy --all-targets --all-features -- -D warnings — lints
      3. cargo test -p <target-crate> — targeted tests

      Include actual pass/fail output in scratchpad Notes.
      Do not claim "pass" without running.

好的验证指令 vs. 坏的

好的(要求实际输出):

instructions: |
  验证要求(发出 review.ready 之前):
  - tests: 运行 pytest,把通过数/总数附在载荷里
  - lint: 运行 flake8,确认 0 个错误
  
  如果任何一项失败,先修复,再发出事件。
  不要在测试失败的情况下发出 review.ready。

坏的(只是声明,没有要求证据):

instructions: |
  完成后发出 review.ready。
  (AI 可能直接发出而不实际运行测试)

什么情况下背压会无法自动修复

有些问题 AI 无法自动修复,背压会一直失败,直到:

  1. 达到最大迭代次数(默认 150 次):循环会停止,并告诉你卡在了哪里

  2. AI 主动发布 build.blocked:AI 自己判断无法继续,需要人工介入

  3. 循环超时(默认 4 小时):超过配置的最长运行时间

这时你需要:

  1. 查看最后一次失败的具体信息
  2. 手动修复无法自动解决的问题(比如安装缺少的依赖)
  3. 重新启动循环,从断点继续
# 查看为什么卡住了
ralph events --topic blocked
cat .ralph/agent/memories.md  # AI 可能记录了遇到的问题

# 手动修复后重新运行
ralph run -p "继续上次的任务,已经修复了 xxx 问题"

LLM-as-Judge:用 AI 评判主观质量

有些质量标准很难用命令行工具检查,比如:

  • 代码的可读性
  • 错误消息是否对用户友好
  • 文档是否清晰

这类主观标准可以交给审查者帽子来判断,把它设计成专门针对这类问题的角色:

hats:
  ux_reviewer:
    name: "💬 UX 审查者"
    triggers: ["review.ready"]
    publishes: ["ux.passed", "ux.rejected"]
    instructions: |
      你是用户体验审查者。检查代码里的错误消息是否对普通用户友好:
      
      判断标准:
      - 不包含技术栈信息(如 'NullPointerException'、堆栈跟踪)
      - 告诉用户如何解决问题,而不只是说"出错了"
      - 语言清晰,不使用编程行话
      
      如果全部通过,发出 ux.passed。
      如果有不符合的,发出 ux.rejected 并列出具体的问题消息。

为什么背压比详细指令更有效

还记得第三章的"背压优于规定"原则吗?这里是一个具体的对比:

规定式(容易失效)

instructions: |
  第一步,写测试文件
  第二步,运行测试,确认它失败
  第三步,写实现代码
  第四步,运行测试,确认它通过
  第五步,运行 flake8 检查格式
  第六步,如果格式不通过,运行 black 修复
  第七步,再次运行 flake8...

(如果 AI 跳过了某一步,或者文件路径不同,整个指令就失效了)

背压式(更健壮)

hats:
  builder:
    instructions: |
      实现功能。
      发出 review.ready 之前,必须已通过:
      tests: pytest 全部通过
      lint: flake8 0 个错误
      
      把实际命令输出附在载荷里作为证据。

(不管 AI 怎么实现,最终都要提供可核实的验证证据)

背压机制关注结果,而不是过程,这让它对各种实现方式都有效。


本章小结

  • 背压关卡是自动运行的质量检查点,不合格的代码不会被"通过"
  • 可以配置测试、格式检查、类型检查、安全扫描等各类关卡
  • 好的 on_fail 消息能大大提高 AI 自动修复的成功率
  • 关卡按顺序执行,建议快速检查放前面
  • 背压比详细规定更健壮,关注结果而不是过程
  • 支持 LLM-as-Judge 检查主观质量标准

质量门禁搞定了,但李明轩遇到新情况:付费社群周报今晚没写完,明晚接着写时 AI 已经把上下文全忘光了。他需要一个跨会话的"AI 笔记本"。下一章讲记忆与任务系统——让 AI 把学到的东西留在磁盘上。

第九章:记忆与任务——AI 的跨会话笔记本

📌 本章李明轩在做什么:付费社群每周要发一篇周报,要引用本周社群里讨论过的话题。一周横跨 7 天,他不可能让 AI 在一次会话里搞定。他需要让 AI 把"本周已经引用过哪些话题"、"会员最常问的问题"这些经验记到磁盘上,下次会话自动读回来。

为什么 AI 需要记忆

在第三章里,我们提到了"新鲜上下文即可靠性"原则——每次迭代 AI 都从零开始读取信息。这引出了一个矛盾:

  • 新鲜上下文意味着每次 AI 都要重新理解环境
  • 但重要的经验和决策不应该在每次迭代后消失

Ralph 通过两套持久化机制解决这个矛盾:

  1. 记忆文件(memories.md):AI 跨会话的"学习笔记"
  2. 任务系统(tasks.jsonl):工作进度的"代办清单"
📅 会话 1(周一晚) 上下文窗口(新鲜) 装入本轮任务上下文…… 会话结束 → 上下文清空 💨 窗口里的东西全没了 📅 会话 2(周二晚) 上下文窗口(新鲜) 装入本轮任务上下文…… 会话结束 → 上下文清空 📅 会话 3(周三晚) 上下文窗口(新鲜) 装入本轮任务上下文…… 会话结束 → 上下文清空 💾 磁盘(永久保存) 📝 .ralph/agent/memories.md 项目模式 / 已修复的坑 / 重要决策 📋 .ralph/agent/tasks.jsonl 待办 / 进行中 / 已完成的任务 写入经验 读回经验

一句话上下文窗口每次都清空(保证新鲜),磁盘每次都保留(保证不遗忘)——两者配合才能既避免老对话的遗忘,又积累项目经验。


记忆文件:AI 的学习笔记本

记忆文件位于 .ralph/agent/memories.md,是一个普通的 Markdown 文本文件,由 AI 自己维护。

记忆的内容

AI 会把以下类型的信息写入记忆:

项目模式(Patterns)

## Project Patterns
- 这个项目使用 pytest 进行测试,测试文件放在 tests/ 目录
- 数据库查询使用 SQLAlchemy ORM,不直接写 SQL
- API 响应格式:{"status": "success|error", "data": {...}, "message": "..."}
- 所有新功能需要在 CHANGELOG.md 里添加条目

已修复的问题(Fixes)

## Fixes Applied
- 导入 requests 库时,需要先激活虚拟环境:source .venv/bin/activate
- pytest-asyncio 版本问题:在 pyproject.toml 里固定到 0.21.x
- 数据库迁移前必须先运行 alembic upgrade head

重要决策(Decisions)

## Decisions
- 选择 FastAPI 而不是 Flask,原因:需要原生 async 支持
- 用户认证使用 JWT,不用 session,原因:支持移动端
- 配置文件使用环境变量,不硬编码,原因:安全考虑

重复出现的错误(Recurring Issues)

## Recurring Issues
- 在这个项目里,datetime 对象必须带时区信息,否则比较会报错
- API 测试时记得先启动 mock 服务器:make mock-server

记忆是如何被使用的

每次迭代开始时,Ralph 会把 memories.md 的内容注入到 AI 的上下文里,放在一个特殊的 <memories> 标签里。AI 在做决策时会参考这些记忆,避免重复犯同样的错误。

手动添加记忆

不只是 AI,你也可以手动向记忆文件添加内容:

# 用命令行添加记忆
ralph tools memory add "注意:这个项目的 API 密钥不能出现在任何测试文件里"

# 或者直接编辑文件
vim .ralph/agent/memories.md

这是"用信号导航"法则的直接体现:当 AI 反复在某个地方犯错时,把正确的做法写入记忆,比在帽子指令里写复杂规则更有效。

记忆的清理

随着项目进行,记忆文件会越来越长。记忆文件是普通的 Markdown 文本,直接用编辑器打开删除不再相关的条目即可:

# 直接编辑记忆文件,删除过时的条目
vim .ralph/agent/memories.md

如果想清理整个 .ralph/ 工作目录(例如重新开始一个项目),可以使用:

# 预览会删除什么(不实际删除)
ralph clean --dry-run

# 清理诊断日志
ralph clean --diagnostics

注意:ralph clean 只会清理 .ralph/agent/ 下的记忆与任务文件;.ralph/ 下的事件日志(events-*.jsonl)、循环注册表(loops.json)、锁文件(loop.lock)等不会被它动到,更不会删除你的项目代码。


任务系统:进度跟踪的代办清单

任务系统通过 .ralph/agent/tasks.jsonl 文件跟踪所有工作的进度。

任务的生命周期

pending(待开始)
    ↓
in_progress(进行中)
    ↓
closed(完成)
    或
reopened(重新打开,需要修改)

任务文件的结构

每行一个任务,完整字段示例(真实输出,略作格式化):

{"id":"task-1705300801-a3f2","title":"创建项目骨架","description":"scaffold the repo","key":"code-assist:my-project:step-01:scaffold","status":"closed","priority":3,"blocked_by":[],"loop_id":"primary-20240115-100001","created":"2024-01-15T10:00:01+00:00","started":"2024-01-15T10:00:05+00:00","closed":"2024-01-15T10:12:44+00:00"}
{"id":"task-1705301453-7c01","title":"实现核心功能","description":"core logic","key":"code-assist:my-project:step-02:core","status":"open","priority":3,"blocked_by":[],"loop_id":"primary-20240115-100001","created":"2024-01-15T10:10:53+00:00","started":"2024-01-15T10:11:39+00:00"}
{"id":"task-1705302021-bb44","title":"完善测试","description":"write tests","key":"code-assist:my-project:step-03:tests","status":"open","priority":3,"blocked_by":["task-1705301453-7c01"],"created":"2024-01-15T10:20:21+00:00"}

任务 ID 格式是 task-<Unix 时间戳>-<4 位 16 进制>,由 Ralph 运行时生成;后文示例里出现 task-1705301453-7c01 这类 ID,都是占位符,实际使用时请用 ralph tools task list 看到的真实 ID 替换。

查看任务状态

运行时任务通过 ralph tools task 子命令管理(注意:ralph task 是生成 .code-task.md 文件的命令,功能不同):

# 列出所有任务
ralph tools task list

# 只列出待处理的任务
ralph tools task ready

# 查看某个任务的详细信息(把示例 ID 换成你本地的真实 ID)
ralph tools task show task-1705301453-7c01 --format json

任务在恢复中的作用

假设你的电脑在任务运行到一半时断电了。重新启动后:

# 重新启动 Ralph
ralph run -p "继续上次的任务"

Ralph 会读取任务文件,知道哪些已经完成、哪些正在进行,从断点处继续,而不是从头开始。


记忆与任务的协作:一个完整的例子

让我们看看在一个多天的项目里,记忆和任务如何协同工作:

第一天

你:ralph run -p "为这个 Python 项目添加邮件发送功能"

Ralph 运行了 5 次迭代:
- 任务1:安装 smtplib 配置 (完成)
- 任务2:实现发送函数 (完成)  ← 在这里遇到了 SSL 证书问题,
- 任务3:添加重试机制 (完成)    AI 记录到记忆里
- 任务4:编写测试 (完成)
- 背压检查:全部通过
- 循环完成

.ralph/agent/memories.md 现在包含:

## Fixes Applied
- 发送邮件时需要设置 ssl_context=ssl.create_default_context(),
  否则在某些服务器上会有 SSL 错误
- SMTP 测试使用 unittest.mock.patch('smtplib.SMTP') 模拟,
  不要真正发送邮件

第二天(新的会话)

你:ralph run -p "添加邮件发送的队列功能,异步处理"

Ralph 在新的迭代里,自动读取了第一天的记忆:
- 知道测试要用 mock,不会真的发邮件
- 知道 SSL 的处理方式,不会再踩同样的坑

代码任务文件(.code-task.md)

除了运行时任务(存在 .jsonl 文件里),Ralph 还支持另一种任务形式:代码任务文件.code-task.md)。

这是一个 Markdown 格式的任务规格文档,适合用于较复杂的功能:

---
status: pending
created: 2024-01-15
started: null
completed: null
---
# 任务:添加邮件验证功能

## 描述
实现一个邮件地址验证函数,用于用户注册时的输入验证。

## 背景
目前注册接口不验证邮件格式,导致脏数据进入数据库。

## 技术要求
1. 验证 RFC 5322 标准格式
2. 检查域名是否存在(可选,可关闭)
3. 返回详细的错误信息(不只是"格式错误")

## 验收标准

1. **基本格式验证**
   - 给定:一个标准格式的邮件地址
   - 当:调用 validate_email() 函数
   - 则:返回 True

2. **无效格式拒绝**
   - 给定:各种格式错误的邮件地址
   - 当:调用 validate_email() 函数
   - 则:返回 False 和具体的错误说明

3. **测试覆盖**
   - 给定:完整的测试套件
   - 当:运行 pytest
   - 则:所有测试通过,覆盖率 > 90%

把这个文件放在 .ralph/tasks/ 目录里,然后运行:

ralph run -H builtin:code-assist \
  --prompt ".ralph/tasks/validate-email.code-task.md"

Ralph 会按照这个文档里的验收标准来判断任务是否完成。


任务的手动管理

在某些情况下,你可能需要手动管理任务状态:

# 创建/更新一个任务(ensure:存在则更新,不存在则创建)
# 语法:ralph tools task ensure --key <KEY> <TITLE> [--description <DESCRIPTION>]
ralph tools task ensure --key "fix:login-css" "修复登录页 CSS" \
  --description "修复登录页面的 CSS 问题"

# 以下示例里的 task-id 形如 task-1776737176-532e(Ralph 生成),
# 复制你在 `ralph tools task list` 看到的完整 ID 替换即可
# 手动关闭一个任务
ralph tools task close task-1776737176-532e

# 重新打开一个已关闭的任务(发现了新问题)
ralph tools task reopen task-1776737176-532e

# 查看任务详情
ralph tools task show task-1776737176-532e

什么不应该存入记忆

记忆文件的价值在于跨会话的持久学习,以下内容不适合放入记忆:

  • 临时的调试信息正在调试 issue #123(这是当前会话的临时状态)
  • 已经修复并提交的 bug:这些信息在代码和 commit message 里已经有了
  • 可以从代码库里直接读取的信息:比如"使用 Python 3.11"(代码里有 pyproject.toml)

记忆里应该存的是那些不写下来 AI 就容易忘记或弄错的东西:隐性约束、踩过的坑、反常识的决策。


本章小结

  • memories.md 是 AI 的跨会话学习笔记,自动积累项目经验
  • tasks.jsonl 是工作进度的代办清单,支持跨会话恢复
  • .code-task.md 文件提供结构化的任务规格,适合复杂功能
  • 可以手动向记忆添加内容,作为"信号"指导 AI 行为
  • 记忆越精准有用,AI 在这个项目里的工作质量越高

记忆和任务系统让 AI 的工作可以跨夜延续。但李明轩还有个现实问题——白天上班时他没法打开终端看循环跑到哪里了。他需要一个手机上能看的面板。下一章讲可视化仪表盘。

第十章:可视化监控——实时掌握 AI 工作进度

📌 本章李明轩在做什么:早上 10:30 公司茶水间,他想瞄一眼"昨晚启动的 4 个循环现在跑成什么样了"。他不可能掏出 MacBook,只能掏手机。Ralph 的 Web 仪表盘就是为这种"人在别处"的场景准备的。

为什么需要可视化

当你告诉 Ralph"去实现这个功能",然后去做别的事情,你心里可能会有些不安:

  • AI 现在在做什么?
  • 进行到哪一步了?
  • 有没有遇到什么问题?
  • 什么时候能完成?

Ralph 提供了两种监控方式:终端界面(TUI)和 Web 仪表盘。


终端界面(TUI)

当你运行 ralph run 时,默认会进入终端界面模式。TUI 由三个区域组成:

[iter 8/150]  [LIVE]  ⚙️ Builder  12:34  main
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
(AI 实时输出内容在这里滚动显示)

Running: python -m pytest...
  test_upper_conversion ... ok
  test_lower_conversion ... ok
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
:(输入 : 可以发送实时指引给 AI)
  • 顶部 Header[iter 当前/最大] 迭代计数 · [LIVE] 实时运行 · 当前活跃帽子 · 已用时间 · Git 分支
  • 中间内容区:AI 的实时输出流,用 j/k 上下滚动,g/G 跳顶部/底部
  • 底部 Footer: 输入指引发给 AI;! 发送紧急指引(AI 必须先确认才能继续)

TUI 快捷键

按键功能
h / ←查看上一次迭代的输出
l / →查看下一次迭代的输出
j / ↓向下滚动输出内容
k / ↑向上滚动输出内容
g滚动到顶部
G滚动到底部(最新)
m切换鼠标模式
/开始搜索输出内容
n / N搜索结果的下一个/上一个
:发送实时指引(下次迭代时 AI 会看到)
!发送紧急指引(阻塞直到 AI 确认)
w进入波浪并行工作者视图
q退出 TUI(循环继续在后台运行)
?显示帮助

不想用 TUI?

如果你只想让 Ralph 跑完再收结果(比如写脚本跑在 CI、或者无头服务器上),可以关掉 TUI 观察模式:

# 方式一:headless 自治模式,命令跑完才返回
ralph run --autonomous -p "任务描述"

# 方式二:只关 TUI,但保留交互通道
ralph run --no-tui -p "任务描述"

⚠️ --autonomous--no-tui互斥的,不要同时加;Ralph 会直接报错。 --autonomous 适合完全无人值守的流水线,--no-tui 适合你仍想通过事件注入等方式干预但不要终端花屏幕的场景。


Web 仪表盘(Alpha 功能)

除了终端界面,Ralph 还提供了一个基于 Web 的可视化仪表盘(目前标记为 Alpha 版本,功能仍在积极开发中)。

启动 Web 仪表盘

# 在一个单独的终端窗口启动仪表盘
ralph web

# 输出:
# 🌐 Ralph Web Dashboard starting...
# 📡 API server: http://localhost:3000
# 🖥️  Dashboard: http://localhost:5173
# 
# Dashboard opened in browser automatically.

Ralph 会自动打开浏览器,显示仪表盘界面。

常用选项

# 不自动打开浏览器
ralph web --no-open

# 使用自定义端口
ralph web --backend-port 4000

# 指定监控的工作区
ralph web --workspace /path/to/your/project

仪表盘的主要功能

循环概览

仪表盘首页显示所有正在运行或已完成的循环:

┌────────────────────────────────────────────────────────────────┐
│  Ralph Dashboard                           🟢 2 active loops   │
├────────────────────────────────────────────────────────────────┤
│  Loop #1                                   Active  [8 iter]    │
│  Prompt: "实现用户登录功能"                                      │
│  Backend: claude                                               │
│  Current: ⚙️ Builder (step-02:auth-logic)                     │
│  Started: 12 min ago                                           │
│  ─────────────────────────────────────────────────────         │
│  Loop #2                                   Active  [3 iter]    │
│  Prompt: "修复 CSS 样式问题"                                     │
│  Backend: kiro                                                 │
│  Current: 📋 Planner (analyzing)                               │
│  Started: 5 min ago                                            │
└────────────────────────────────────────────────────────────────┘

事件流图

点击某个循环,可以看到事件流的可视化图表,用 XYFlow 渲染的流程图,清晰展示哪个帽子激活过、事件是如何流动的:

work.start ──► 📋 Planner ──► tasks.ready ──► ⚙️ Builder ──► review.ready
                                                                    │
                                                                    ▼
                                                           ❌ review.rejected
                                                                    │
                                                                    ▼
                                                           ⚙️ Builder (retry)
                                                                    │
                                                                    ▼
                                                           ✓ review.ready
                                                                    │
                                                                    ▼
                                                           🧪 Critic ──► review.passed
                                                                                │
                                                                                ▼
                                                                       🏁 Finalizer

记忆查看器

在仪表盘里可以直接查看和编辑记忆文件,不需要打开终端:

Memories Editor
─────────────────────────────────────────────
## Project Patterns                    [编辑]
- 使用 FastAPI + SQLAlchemy
- 测试使用 pytest-asyncio

## Fixes Applied                       [编辑]
- SSL 证书配置...

[+ 添加新记忆]  [清理旧记忆]

任务管理

Tasks
─────────────────────────────────────────────
✓ step-01:scaffold        完成  2m前
⟳ step-02:auth-logic      进行中
○ step-03:tests           等待中
○ step-04:deployment      等待中

[手动关闭]  [重新打开]  [删除]

后台运行与监控

有时候你想启动 Ralph 后完全离开终端(比如晚上下班前启动一个长任务,第二天回来检查结果):

# 在后台运行 Ralph(使用 nohup 或 screen/tmux)
nohup ralph run -p "重构整个认证模块" > ralph.log 2>&1 &

# 或者用 screen(推荐)
screen -S ralph-session
ralph run -p "重构整个认证模块"
# Ctrl+A, D 脱离 screen 会话

# 第二天回来查看
screen -r ralph-session
# 第二天早上查看循环状态
ralph loops

# 输出示例:
# ID         STATUS     ITERATIONS  RUNTIME   DESCRIPTION
# loop-abc   ✓ complete 47          2h 13m    重构整个认证模块
# 
# Last event: LOOP_COMPLETE
# Output in: .ralph/loops/loop-abc/

诊断模式

当你遇到问题,需要深入了解 Ralph 在做什么时,可以启用诊断模式:

RALPH_DIAGNOSTICS=1 ralph run -p "你的任务"

这会在 .ralph/diagnostics/ 目录里保存三种详细日志:

.ralph/diagnostics/2024-01-15T10-30-00/
├── agent-output.jsonl      ← AI 的完整输出(文字、工具调用、结果)
├── orchestration.jsonl     ← 帽子激活、事件发布、背压检查的记录
└── errors.jsonl            ← 解析错误、验证失败的详细信息

分析这些日志:

# 查看所有工具调用
jq 'select(.type == "tool_call")' .ralph/diagnostics/*/agent-output.jsonl

# 查看所有帽子激活记录
jq 'select(.type == "hat_activation")' .ralph/diagnostics/*/orchestration.jsonl

# 查看所有错误
cat .ralph/diagnostics/*/errors.jsonl

通知集成

不想一直盯着仪表盘?Ralph 可以在循环完成(或失败)时发送通知:

macOS 系统通知(通过 shell 钩子配置,参见第十四章):

# 在 ralph.yml 里配置循环结束时的通知
hooks:
  on_complete:
    - command: "osascript -e 'display notification \"Ralph 任务完成!\" with title \"Ralph\"'"
  on_blocked:
    - command: "osascript -e 'display notification \"Ralph 需要你的帮助\" with title \"Ralph ⚠️\"'"

Telegram 通知(第十二章详细介绍):

如果你配置了 Telegram 机器人,Ralph 会自动通过 Telegram 发送关键状态更新:

  • 循环开始时发送"开始工作了"
  • 遇到阻塞时发送"我需要帮助"
  • 任务完成时发送"完成了,请查看结果"

清理旧的循环记录

随着时间推移,会积累一些历史记录。可以定期清理:

# 预览会删除什么(不实际删除)
ralph clean --dry-run

# 清理诊断日志
ralph clean --diagnostics

# 查看 .ralph/ 目录的磁盘使用
du -sh .ralph/

对于已完成的并行循环,使用 ralph loops 子命令管理:

# 查看所有循环(包括已完成的)
ralph loops list --all

# 废弃某个循环,清理它的 worktree
ralph loops discard loop-abc

本章小结

  • TUI(终端界面)是 Ralph 运行时的实时监控界面,提供快捷键操作
  • Web 仪表盘提供更友好的可视化界面,支持流程图、记忆编辑、任务管理
  • 可以用 nohup/screen/tmux 在后台长时间运行 Ralph
  • 诊断模式(RALPH_DIAGNOSTICS=1)保存详细日志,方便排查问题
  • 支持配置完成/失败通知,不需要一直盯着屏幕

能随时看到进度让李明轩安心了不少。但他很快贪心起来——既然 AI 能跑,为什么不让它同时跑 4 个?微信、小红书、知乎、微博 4 个平台的差异化文案完全可以并行。下一章讲并行工作流——全书的高潮,也是"一个人顶一个团队"承诺的兑现。

第十一章:并行工作流——让多个 AI 同时协作

📌 本章李明轩在做什么:这是他最期待的一章。4 个平台 4 个循环并行跑——他睡 8 小时相当于 AI 干了 32 小时。本书开篇那个"一个人顶一个团队"的承诺就在这一章兑现。

一个人 vs 一个团队

想象两种场景:

场景A:一个工人,按顺序完成三件事:修前门锁、刷厨房墙、修后花园篱笆。需要 6 小时。

场景B:三个工人同时工作,各做一件事。同样的工作,2 小时完成。

Ralph 支持两种维度的并行工作:

  1. 循环级并行:多个独立的 Ralph 循环同时运行(适合完全独立的任务)
  2. 波浪级并行:单个循环内,同一顶帽子处理多个任务(适合"批量审查"类工作)

循环级并行:多个 AI 同时工作

基本概念

Ralph 支持在同一个项目里同时运行多个循环,每个循环处理一个独立的任务。Ralph 使用 Git Worktree(工作树)机制确保这些循环在隔离的文件系统环境里工作,互不干扰。

📖 名词解释 · Git Worktree(工作树)

Git 传统上只允许你同时在"一个分支"上工作——想看另一个分支的代码,就得先把当前的改动藏起来或提交。Worktree 打破了这个限制:同一个仓库,可以在不同目录里同时检出多个分支,互不打扰。

比喻:一本小说有三个改写版本,传统 Git 像"只有一张桌子,想看 B 版要先把 A 版收起来";Worktree 像"把三张桌子一字排开,三个版本同时摊着,各改各的"。

Ralph 用它实现并行循环的"安全隔离":每个循环各占一个 worktree,各自改各自的文件,最后再合并回主工作树——不会出现"循环 A 写了一半,循环 B 把它改没了"的混乱。

进一步学习:Git 官方文档:git-worktree · Atlassian 中文教程

📁 项目仓库(同一份 Git 历史) 🏠 主工作树(main) 处理:添加用户登录 API 持有 .ralph/loop.lock (标识这是主循环) 循环完成后 负责合并其他结果 🌳 .worktrees/loop-abc 处理:修 CSS 性能问题 独立文件系统 (各改各的,互不干扰) 🌳 .worktrees/loop-def 处理:加单元测试覆盖 独立文件系统 (各改各的,互不干扰) 🌳 .worktrees/loop-xyz ……(更多可以继续开) 📬 合并队列(.ralph/merge-queue.jsonl) 每个 worktree 循环完成后,把自己的改动"排队"等主循环合并 主循环最后一步按顺序合并,自动解决简单冲突 ✅ 最终成果 主工作树合并所有改动 作为一次统一的 commit 产出 完成后入队 完成后入队 主循环按队列合并 主工作树(1 个) 工作树循环(N 个) 合并队列(文件) 最终成果 同一份 Git 历史 + 多个隔离的工作目录 = 并行不打架

启动并行循环

在不同的终端窗口,分别启动不同的任务:

# 终端 1 - 主循环
ralph run -p "添加用户注册和登录 API,包括 JWT 认证"

# 终端 2 - 工作树循环(同时启动)
ralph run -p "修复用户列表页面加载缓慢的性能问题" --max-iterations 30

# 终端 3 - 另一个工作树循环
ralph run -p "添加单元测试覆盖 user_service.py 里的所有函数"

所有循环同时跑,互不干扰。

查看所有循环的状态

ralph loops

# 输出:
# ID         STATUS     ITER   RUNTIME   DESCRIPTION
# loop-main  ✓ Active   12     15m       添加用户注册和登录 API
# loop-abc   ✓ Active   5      8m        修复性能问题
# loop-def   ✓ Complete 18     22m       添加单元测试

结果如何合并

每个工作树循环完成后,会把自己的修改排队到合并队列(merge queue)。当主循环完成时,Ralph 会自动按照完成顺序合并所有工作树循环的结果:

loop-def 完成 → 排队等待合并
loop-abc 完成 → 排队等待合并

主循环完成 → 开始合并:
  合并 loop-def 的修改
  合并 loop-abc 的修改
  处理可能的冲突
  最终提交

一个测试并行循环的实验

如果你想动手体验并行循环,可以用这个贴近李明轩真实场景的实验——把同一篇文章并行改写成两个平台版本:

# 创建一个干净的测试目录
mkdir /tmp/ralph-parallel-test
cd /tmp/ralph-parallel-test
git init

# 准备一篇假的源文稿(你可以用任何一段长文字顶替正文)
cat > article.md <<'EOF'
# 35 岁转型 AI 的三个陷阱

这是一篇 3000 字左右的深度稿,主题是职场中年人想转做 AI 相关工作时
最容易踩的三个陷阱:过度追新、忽视数据基础、低估工程化难度。
……(正文省略)……
EOF

git add . && git commit -m "initial"
ralph init --backend claude

# 终端 1:主循环,生成公众号版本
ralph run -p "读取 article.md,改写成 2000 字左右的公众号版本,
保留原文结构但更流畅有代入感,保存为 wechat.md" \
  --max-iterations 5

# 终端 2(同时启动):工作树循环,生成小红书版本
ralph run -p "读取 article.md,改写成 800 字左右的小红书短图文版本,
口语化、分段短、带适当 emoji,保存为 xiaohongshu.md" \
  --max-iterations 5

完成后,目录下会同时出现 wechat.mdxiaohongshu.md——两种截然不同的风格,两个循环互不干扰地并行产出。把这个实验扩展到 4 个终端,就是李明轩每天晚上真正在做的事。


波浪级并行:批量处理多个文件

第二种并行方式是波浪(Wave):单个帽子在一次迭代里同时处理多个工作单元。

最典型的场景是代码审查:你有 20 个文件需要审查,与其一个一个审查(20 次迭代),不如同时审查(1 次迭代,20 个并行工作者)。

波浪的配置

在帽子配置里,设置 concurrency 参数来启用波浪:

hats:
  file_reviewer:
    name: "🔍 文件审查者"
    triggers: ["review.file"]
    publishes: ["review.done"]
    concurrency: 4               # 同时最多 4 个并行工作者
    instructions: |
      审查指定的文件,检查:
      1. 是否有安全漏洞
      2. 是否有性能问题
      3. 代码风格是否统一
      输出审查报告。
      
  synthesizer:
    name: "📊 综合分析者"
    triggers: ["review.done"]
    publishes: ["analysis.complete"]
    aggregate:
      mode: wait_for_all         # 等待所有并行审查完成
      timeout: 300               # 最多等待 5 分钟
    instructions: |
      综合所有文件的审查结果,生成总体报告。

波浪的触发

AI 在工作时,可以用命令触发波浪,同时提交多个工作单元:

# 在帽子的指令里,AI 会运行这个命令来触发波浪
ralph wave emit review.file \
  --payloads "src/auth.py" "src/user.py" "src/admin.py" "src/api.py"

这会同时启动 4 个 AI 实例,各自审查一个文件,然后把结果汇总给 synthesizer 帽子。

使用 wave-review 预设

Ralph 官方仓库里提供了 wave-review.yml 预设,专门用于并行代码审查。它不随 npm 包发布,需要你手动从上游仓库下载再本地引用:

# 下载预设到本地 presets/ 目录(只做一次)
mkdir -p presets
curl -L -o presets/wave-review.yml \
  https://raw.githubusercontent.com/mikeyobrien/ralph-orchestrator/main/presets/wave-review.yml

# 对整个 src/ 目录进行并行代码审查
ralph run -H presets/wave-review.yml \
  --prompt "审查 src/ 目录下的所有 Python 文件,重点关注安全性"

同一个仓库的 presets/ 目录下还有 autoresearch.ymlcode-assist.ymldebug.ymlpdd-to-code-assist.ymlresearch.ymlreview.yml 等,后面六个同时也通过 -H builtin:<name> 作为内置预设提供;wave-review.yml 目前只能走下载这条路。


并行工作的注意事项

避免任务冲突

并行循环处理的任务最好是完全独立的:

适合并行

  • 添加新功能 A(不影响功能 B 的文件)
  • 修复 bug X(不影响 bug Y 的文件)
  • 为模块 M 添加测试(不影响模块 N)

不适合并行

  • 两个循环都要修改同一个核心文件
  • 一个循环的输出是另一个循环的输入
  • 两个循环都要修改配置文件

如果并行循环修改了相同的文件,合并时会产生冲突。Ralph 会尝试自动处理简单冲突,但复杂冲突可能需要你手动介入。

资源消耗

每个并行循环都会调用 AI 后端,产生费用。在启动多个并行循环前,先评估:

  • AI API 的费用(Claude、Gemini 等都是按 token 计费)
  • 本地系统资源(CPU、内存)
  • AI 服务的请求速率限制

通常,2-3 个并行循环是一个合理的起点。


实用场景:并行研究

Ralph 的 autoresearch 预设支持并行研究,同时从多个角度研究同一个主题:

ralph run -H builtin:autoresearch \
  --prompt "研究 WebAssembly 在 2024 年的应用现状:
  从性能、生态系统、实际案例三个维度分别研究,
  然后综合成一篇深度报告"

这会启动三个并行的研究帽子,分别研究三个维度,最后由综合者帽子整合成统一报告。


查看并行进度

# 查看所有循环(含状态、迭代次数、运行时间)
ralph loops list

# 查看特定循环的事件历史
ralph loops history loop-abc

# 查看特定循环的实时输出
ralph loops logs loop-abc --follow

本章小结

  • 循环级并行:多个 Ralph 循环同时运行,使用 Git Worktree 隔离,完成后自动合并
  • 波浪级并行:单个帽子同时处理多个工作单元,用于批量审查等场景
  • 并行最适合完全独立的任务,避免修改相同文件
  • wave-review.yml 预设提供开箱即用的并行代码审查
  • 考虑 AI API 费用和速率限制再决定并行程度

并行让李明轩的晚上产能提高了 4 倍。但他很快碰到一个新情况:周三早上地铁上,他看到昨晚一个循环卡在"微博签名算法"问题上,离公司还有 15 分钟——他能用的只有手机。下一章讲 Telegram 人机协作:怎么用手机给正在跑的循环发指令。

第十二章:人机协作——用 Telegram 实时介入

📌 本章李明轩在做什么:他希望在地铁上、在饭桌上、在茶水间也能给正在跑的 Ralph 循环"塞一句话"进去。这一章讲怎么通过 Telegram 和 Ralph 实时对话,随时随地把自己变成循环的一部分。

自动化的边界

Ralph 的设计哲学鼓励你"让 Ralph 自己 Ralph"——启动循环,然后去做别的事。但现实中总有一些情况,AI 需要你的输入:

  • AI 遇到了不确定的设计决策:两种方案都可行,它不知道哪个更符合你的偏好
  • AI 需要一个只有你知道的信息:特定的业务规则、某个系统的访问权限
  • 你突然有了新的想法,想在循环中途调整方向

当你不在电脑旁边,这些情况就很麻烦。

**RObot(Robot Operator)**是 Ralph 的人机协作功能,通过 Telegram 把你连接到正在运行的循环上,无论你在哪里,都可以实时介入。


配置 Telegram 机器人

第一步:创建 Telegram 机器人

  1. 在 Telegram 里搜索 @BotFather
  2. 发送 /newbot
  3. 按照提示设置机器人名称和用户名
  4. BotFather 会给你一个 Token,类似 1234567890:ABCdefGHI...

记下这个 Token,稍后需要用到。

第二步:配置 Ralph

运行引导配置命令:

# Ralph 目前的 bot 就是 Telegram 机器人,onboard 无需额外 flag
ralph bot onboard

这个命令会引导你:

  1. 输入刚才得到的 Telegram Bot Token
  2. 给机器人发送第一条消息(这样 Ralph 就知道你的 Chat ID)
  3. 测试连接是否正常

或者直接编辑 ralph.yml

RObot:
  enabled: true
  timeout_seconds: 300       # 等待你回复的最长时间(秒)
  telegram:
    bot_token: "1234567890:ABCdefGHI..."   # 或用环境变量

更安全的方式是使用环境变量,避免 Token 出现在配置文件里:

export RALPH_TELEGRAM_BOT_TOKEN="1234567890:ABCdefGHI..."
RObot:
  enabled: true
  timeout_seconds: 300
  telegram:
    # bot_token 会自动从 RALPH_TELEGRAM_BOT_TOKEN 环境变量读取

第三步:验证配置

ralph bot status   # 检查连接状态
ralph bot test     # 发送测试消息到你的 Telegram

三种交互模式

RObot 支持三种交互事件,覆盖了不同的人机协作场景:

⚙️ Ralph 循环 在你的电脑上跑 帽子 / 事件 / 背压 (无人值守) 🤖 Ralph Telegram Bot 主循环持有 .ralph/telegram-state.json 连接两端 📱 你的手机 / PC Telegram 客户端 地铁 / 茶水间 / 家里 随时都能看 human.interact (推送问题) (你的回复) human.response ① 模式一:AI 提问(阻塞) 你主动发 human.guidance ② 模式二:你主动发指引(非阻塞) progress(无需回复) (推送进度) ③ 模式三:进度通知(单向) 阻塞等待 非阻塞注入 单向通知 ——超时 5 分钟则走默认值,不会把循环卡死

模式一:AI 提问,人类回答(human.interact

当 AI 遇到需要你做决策的情况时,它会发出 human.interact 事件,循环会暂停等待你的回答

AI 端(在帽子执行中发出):

ralph emit "human.interact" "Decision needed: REST API vs GraphQL for multi-client support.
Options: (A) REST — simpler, wider support; (B) GraphQL — flexible for multiple frontends.
Default if no response in 5 min: REST."

你会收到这条 Telegram 消息:

🤖 Ralph 需要你的输入:

应该使用 REST API 还是 GraphQL?
项目需要支持多种前端(Web、iOS、Android)。
回复 'REST' 或 'GraphQL',或者简单说明你的偏好。

⏰ 将在 5 分钟后超时(使用默认值)

你回复后,循环自动继续,AI 拿到你的答案继续工作。

如果超时没有回复,Ralph 会选择"安全默认值"(比如选择更简单的方案)并继续,不会卡死。

模式二:人类主动发消息(human.guidance

你可以随时向正在运行的循环发送指导消息,不需要等 AI 提问。

在 Telegram 里给机器人发任何消息,比如:

注意:这个项目不允许使用第三方库,只用标准库

这条消息会被注入到循环里,在下次迭代时作为"指引"出现在 AI 的上下文中:

## ROBOT GUIDANCE
1. 注意:这个项目不允许使用第三方库,只用标准库

AI 会在后续工作中遵循这个指引。

模式三:非阻塞进度通知(ralph tools interact progress

AI 可以发送不需要回复的进度更新:

ralph tools interact progress "All tests passing — starting integration phase"

这条消息会发送给你,让你了解进度,但不会暂停循环。适合阶段完成、里程碑提示等 FYI 类通知。

该命令依赖 Telegram 通道:必须先跑过 ralph bot onboard 完成配置,并在 ralph.yml 里启用 RObot(或设置 RALPH_TELEGRAM_BOT_TOKEN),否则命令本身不会报错,但消息不会真正发出去。


实际使用场景

场景一:设计决策咨询

你启动了一个功能开发任务,Ralph 在设计阶段遇到了架构问题:

收到来自 Ralph 的消息:

🤖 遇到设计决策需要确认:

我在规划用户通知系统时,有两个方案:

方案A:实时推送(WebSocket)
- 优点:实时性好
- 缺点:服务器需要维持长连接,资源消耗较大

方案B:轮询(每隔 30 秒检查一次)
- 优点:实现简单,服务器资源消耗小
- 缺点:通知有延迟

请问你更倾向哪种方案?如果用户量不大(<1000人),我建议方案B。

你回复:用方案A,用户体验更重要

循环继续,AI 按照你的选择实现 WebSocket 方案。

场景二:在外出时监控并干预

你在公司外面开会,Ralph 在你的电脑上跑着一个复杂的重构任务。你收到通知:

🤖 Ralph 进度更新:
已完成 step-01(重构数据层)
已完成 step-02(重构业务逻辑层)
当前正在进行 step-03(重构 API 层)
预计还需要 30 分钟

你看到消息,觉得进展顺利,不需要干预。继续开会。

20 分钟后:

⚠️ Ralph 遇到问题,需要你的帮助:

在重构 API 层时,发现有一个旧的认证中间件(legacy_auth.py)
被很多地方引用,但注释显示它"不应该在新代码里使用"。

我有两个选择:
A. 保留旧中间件,只在新代码里用新认证方式
B. 迁移所有调用到新认证方式(工作量更大,但更彻底)

你的偏好?默认 5 分钟后我会选择方案A。

你在会议间隙快速回复:选B,做彻底一点

循环继续按你的指示完成迁移。

场景三:紧急调整方向

循环跑到一半,你突然想到一个重要的约束条件:

你直接给机器人发消息:

紧急:用户认证部分绝对不能用第三方库,
这是法律合规要求,只能用系统自带的 hashlib。

AI 在下次迭代时会看到这个指引,立刻调整实现方向。


多循环场景下的消息路由

当你同时运行多个并行循环时,Telegram 的消息路由规则是:

  • 发给主循环:直接发消息(默认路由到主循环)
  • 发给特定循环:消息开头加 @loop-id,如 @loop-abc 改用方案B
  • 广播给所有循环:消息开头加 @all(谨慎使用)
# 查看所有循环的 ID
ralph loops

# 输出:
# loop-main  (主循环) - 添加登录功能
# loop-abc              - 修复性能问题
# loop-def              - 添加测试

安全注意事项

Telegram 机器人 Token 是敏感信息,需要妥善保管:

  1. 不要把 Token 提交到代码库:确保 ralph.yml 里没有硬编码的 Token,用环境变量
  2. 不要分享 Token:任何人拿到 Token 都能发消息给你的机器人
  3. 必要时轮换 Token:如果 Token 泄露,通过 BotFather 生成新的 Token
  4. 检查 Chat ID:确保只有你的 Chat ID 能与机器人交互

不使用 Telegram 的替代方案

如果你不想配置 Telegram,也可以用更简单的方式手动注入指引:

# 在另一个终端,手动注入事件
ralph emit human.guidance "请用中文写代码注释"

# 查看所有循环的状态
ralph loops list

本章小结

  • RObot 通过 Telegram 把你连接到正在运行的 Ralph 循环上
  • 三种交互模式:AI 提问(阻塞)、人类主动发指引(非阻塞)、进度通知
  • 超时没有回复时,循环会用"安全默认值"继续,不会卡死
  • 支持多循环场景下的消息定向路由
  • Token 等敏感信息用环境变量存储,不要写进配置文件

第四章到第十二章,李明轩的每个痛点都一个个被解掉了。下一章我们把这些碎片重新拼起来:跟着李明轩跑完从一个选题到 4 平台全面上线的完整一天,看看前面所有机制是怎么协同工作的。

第十三章:全流程实战——李明轩一晚上搞定 mx publish

案例背景

第五章里,李明轩让 Ralph 写出了"明轩说"工具箱的第一个命令 mx add——把选题灵感快速记到本地。那是一道小甜点。真正让他每晚凌晨 1 点睡不了觉的,是另一件事:

每写完一篇文章,他都要在 4 个平台(公众号、小红书、知乎、微博)上反复复制粘贴、手动配图、各自调整格式——一套流程下来一小时。

这一章,我们陪他用一晚上把这个痛点解决掉。目标:建一个 mx publish 命令,接受一篇 Markdown 源文稿,自动生成 4 个平台的差异化版本,并通过各平台的 API 或浏览器自动化一键发布

这是全书的集大成案例。前面 12 章学的所有机制——帽子、事件、背压、记忆、并行、人机协作——你都会在这一个过程里看到它们协同工作。


第一步:环境准备

李明轩在第五章已经建好了 mx 项目目录,这一章直接在里面开工:

cd ~/code/mx
git status   # 确认工作区是干净的

他上次的 mx add 命令已经提交到 main 分支。现在他开启新的 Ralph 会话——Ralph 会自动从 .ralph/agent/memories.md 读回上次积累的项目经验("项目用 pytest 做测试、灵感用 JSONL 存储"等),不需要重新介绍项目背景。


第二步:用 PDD 把想法问清楚(ralph plan

模糊的想法不能直接交给 AI 实现,先问清楚。

ralph plan "我需要一个 mx publish 命令,读一篇 markdown 源文稿,
自动生成公众号、小红书、知乎、微博 4 个平台的差异化版本并发布"

审问者帽子开始工作。李明轩在键盘前一边回答,一边意识到很多细节他自己以前也没想清楚。


问题 1

🎯 4 个平台的差异化规则你心里有固定套路吗? 比如字数、语气、emoji、配图数量——还是每次看情况?

李明轩:有固定套路。公众号保持原长度、正式一些;小红书 800 字、口语化、带 emoji、分 5 段;知乎 1500 字、问答体;微博 3 条 140 字段子。


问题 2

🎯 发布渠道你希望怎么对接? 官方 API、还是用浏览器自动化(Playwright 之类)?

李明轩:优先官方 API。公众号、微博都有开放接口。小红书、知乎官方接口不对个人开放,这两个用浏览器自动化。


问题 3

🎯 4 个平台并行发还是串行发? 并行快,但一旦某个平台失败,另外三个已经发出去了,回滚会很麻烦。

李明轩:并行跑,但先加一个 --dry-run 模式:本地出 4 份成稿给我审一遍,确认无误再真正发布。


问题 4

🎯 配图怎么处理? 源文稿的图片引用,自动同步到 4 个平台,还是每个平台单独上传?

李明轩:源文稿的图片先统一存到本地 assets/,发布时各平台各自上传一次,返回各自的 CDN 地址。


问题 5

🎯 失败处理:某个平台发失败了,怎么通知你? 命令行报错、还是通过你配好的 Telegram?

李明轩:Telegram 推送。我发完基本就睡觉了,命令行看不到。


问答继续了十来轮。10 分钟后,架构师帽接过设计工作,生成了设计文档:

.agents/scratchpad/implementation/mx-publish/
├── requirements.md   # 澄清后的需求
├── design.md         # 架构设计
└── tasks.md          # 实现步骤分解

设计批评者帽又审查了一轮,提出"配图统一存入 assets/ 之前先做一次压缩,不然 4 平台重复上传大图太慢"。李明轩确认采纳,最终设计获批。


第三步:查看设计文档

花 5 分钟扫一遍设计文档(节选):

概览:读一篇 markdown 源文稿,并行生成 4 个平台的差异化版本,通过官方 API 或浏览器自动化一键发布。

架构

📄 article.md 源文稿 🔄 加载器 读文稿 + 图片 4 个并行改写器(每平台一个) 📮 公众号版本 保原长度 · 正式语气 (走 API) 📕 小红书版本 800 字 · 5 段 · emoji (走 Playwright) ❓ 知乎版本 1500 字 · 问答体 (走 Playwright) 🐦 微博版本 3 条 × 140 字段子 (走 API) 4 个并行发布器 📤 发布到公众号 📤 发布到小红书 📤 发布到知乎 📤 发布到微博 📲 Telegram 结果推送

命令规格

命令说明
mx publish <file.md>一次发到全部 4 平台
mx publish <file.md> --dry-run只生成 4 份本地成稿,不真正发布
mx publish <file.md> --platforms wechat,weibo只发指定平台

平台差异化规则(节选):

  • wechat: 字数 ≈ 原长,正式语气,图片原尺寸
  • xiaohongshu: 800 字左右,口语 + emoji,分 5 段,段段配图
  • zhihu: 1500 字左右,问答体,引用原文数据要标来源
  • weibo: 3 条 140 字段子,第一条带链接,最后一条带话题

验收标准

  1. --dry-run 能本地生成 4 份成稿,风格符合规则
  2. 4 个平台各自有单元测试(mock 接口调用)
  3. 任一平台失败不影响其他平台,失败原因推送到 Telegram
  4. 4 平台并行,整个流程预期 2 分钟内完成

第四步:启动并行实现(ralph run

设计文档准备好了。李明轩决定动用 Ralph 的并行能力——4 个平台各自是相对独立的模块,正好一个循环写一个。

他在项目里开 4 个终端,分别启动 4 个循环:

# 终端 1:主循环,实现公共框架(命令解析 / 调度 / 报告)
ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/mx-publish/ 的 step-1-core"

# 终端 2:工作树循环,实现公众号平台(走 API)
ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/mx-publish/ 的 step-2-wechat"

# 终端 3:工作树循环,实现小红书平台
ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/mx-publish/ 的 step-2-xiaohongshu"

# 终端 4:工作树循环,实现知乎 + 微博两个平台
ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/mx-publish/ 的 step-2-zhihu-weibo"

启动完最后一个,他关上屏幕去洗澡。晚上 23:10


第五步:中途介入(Telegram)

23:45,他洗完澡躺下,顺手打开 Telegram。循环 3(小红书)推了一条:

⚠️  xiaohongshu loop blocked:
    Reason: "小红书没有公开的发帖 API。需要你确认改用 Playwright
    浏览器自动化,还是放弃这个平台?"

他在床上回了一句:

用 Playwright。另外把"小红书永远不要尝试走 API,直接浏览器自动化"写进记忆里,下次别再问了。

循环 3 自动继续。下一次迭代里它不仅切换到了 Playwright 方案,还把这条经验写进了 .ralph/agent/memories.md——日后任何涉及小红书的循环都会读到。

他关灯睡觉。


第六步:早上收割

06:45 起床,打开 Telegram:

✅ mx-publish main loop: 完成,8 次迭代,耗时 58 分钟
✅ wechat platform: 完成,12 次迭代,测试 9/9 通过,已合并
✅ xiaohongshu platform: 完成(中途切到 Playwright),测试 7/7 通过,已合并
✅ zhihu + weibo platform: 完成,18 次迭代,测试 13/13 通过,已合并

到电脑前查看结果:

ls -R mx/publish/
mx/publish/
├── __init__.py
├── cli.py                   # mx publish 命令解析
├── orchestrator.py          # 并行调度 + 结果收集
├── platforms/
│   ├── __init__.py
│   ├── base.py              # 平台抽象基类
│   ├── wechat.py            # 公众号(走 API)
│   ├── xiaohongshu.py       # 小红书(走 Playwright)
│   ├── zhihu.py             # 知乎(走 Playwright)
│   └── weibo.py             # 微博(走 API)
├── rewriters/
│   ├── wechat_rewriter.py
│   ├── xiaohongshu_rewriter.py
│   ├── zhihu_rewriter.py
│   └── weibo_rewriter.py
└── notifier.py              # Telegram 推送

tests/
├── test_wechat.py           # 9 个测试
├── test_xiaohongshu.py      # 7 个测试
├── test_zhihu.py            # 8 个测试
├── test_weibo.py            # 5 个测试
└── test_orchestrator.py     # 6 个测试

跑一遍完整测试:

python -m pytest
# 35 passed in 2.8s ✓

第七步:真·试用

李明轩拿昨晚定稿的一篇 3000 字文章测试:

# 先 dry-run,看 4 个平台的成稿对不对味
python -m mx publish articles/ai-transition.md --dry-run

# ✓ wechat: dist/ai-transition.wechat.md (2180 字)
# ✓ xiaohongshu: dist/ai-transition.xiaohongshu.md (790 字, 5 段, emoji ✅)
# ✓ zhihu: dist/ai-transition.zhihu.md (1480 字, 问答体 ✅)
# ✓ weibo: dist/ai-transition.weibo.json (3 条段子 ✅)

他 5 分钟扫完 4 份稿,两处小改后真发:

python -m mx publish articles/ai-transition.md
# ✓ wechat 发布成功:https://mp.weixin.qq.com/s/xxx
# ✓ xiaohongshu 发布成功:https://xiaohongshu.com/explore/xxx
# ✓ zhihu 发布成功:https://zhuanlan.zhihu.com/p/xxx
# ✓ weibo 发布成功:3 条 Thread
# 耗时:1 分 47 秒

以前要 1 小时的活,现在不到 2 分钟


第八步:迭代加新功能——定时发布

第二天晚上,他想到一个新需求:定时发布——晚上写好,早上 8 点自动发出,这样早高峰能拿到更多自然流量。

他没有重新规划整个项目,直接用新需求启动增量循环:

ralph run -H builtin:code-assist \
  -p "为 mx publish 加一个 --schedule 参数,接受 HH:MM 格式,
  表示延迟到当天(或次日)那个时间点再真正发布。
  延迟期间用文件 + cron(或 apscheduler)实现,不要长驻进程。"

Ralph 读回已有代码和记忆里的项目经验("小红书用 Playwright""测试放 tests/"),在已有基础上加了一个 scheduler 模块。35 分钟后完成,7 个新测试全部通过。整个增量迭代李明轩只在边上刷手机


复盘:与手工方式对比

环节手工方式Ralph 方式
需求澄清脑子里过一遍,常漏细节问答式,10 分钟想清 10 个细节
设计跳过,直接开写有架构图、验收标准的设计文档
实现串行写 4 个平台,精力耗尽4 个循环并行,晚上睡觉时写完
测试常常忘每个平台都有覆盖测试
代码审查自己审独立的 Critic 角色挑剔
边界处理漏掉(如小红书没 API)中途 Telegram 提问,写进记忆
时间约 2 天全投入一晚上 + 早上 1 小时确认
物理在场时间全程 10+ 小时问答 10 分钟 + TG 2 分钟 + 审核 5 分钟 + 启动 ≈ 1.5 小时

一晚上,他一个人完成了过去两天的工作量,而且睡够了 7 小时。


什么时候 Ralph 表现最好

通过这个案例,可以总结出 Ralph 最适合的场景:

最适合

  • 能分解成多个独立模块的项目(4 个平台、N 个子命令)
  • 有明确验收标准的功能开发
  • 需要测试覆盖的代码
  • 任务较为独立,不需要频繁的主观判断

需要更多人工介入

  • 需要大量创意和主观判断的工作(比如稿件最终定稿的文字取舍)
  • 依赖外部系统鉴权的任务(账号密码要你亲自过)
  • 需求非常模糊,连你自己也不清楚想要什么

本章小结

通过这个李明轩的真实案例,你见证了 Ralph 完整工作流的威力:

  1. ralph plan:把模糊需求问成清晰设计
  2. ralph run -H builtin:code-assist:多循环并行实现不同模块
  3. 循环内部:规划 → 构建 → 审查 → 终结,有测试、有质量门禁
  4. Telegram 介入:关键决策远程回一句话即可
  5. 记忆机制:中途得到的经验(如"小红书不用 API")自动沉淀,下次循环自动继承
  6. 增量迭代:新功能在已有代码上继续长,不用推翻重来

最关键的感受:这个项目从提需求到可用,李明轩物理在场时间不超过 1.5 小时。其余 8 个小时,Ralph 在他的电脑上一个人干了 4 个人的活。

下一章,我们深入 ralph.yml 配置文件,学习怎么把"明轩说的文风 + 审校规则"这类独特资产沉淀成自定义预设,让未来每一次循环都自动带上你的项目 DNA。

第十四章:高级配置——打造专属工作流

配置文件全解析

ralph.yml 是 Ralph 的核心配置文件。一个完整的配置文件有以下几个顶级部分:

event_loop:    # 循环控制参数
cli:           # 命令行和后端配置
core:          # 核心运行时参数
hats:          # 帽子角色定义
events:        # 自定义事件元数据
RObot:         # 人机协作配置

下面逐一解析每个部分的关键参数。


event_loop:循环控制

event_loop:
  # 触发循环结束的信号名称(保持默认即可)
  completion_promise: "LOOP_COMPLETE"
  
  # 最大迭代次数
  # 默认 150,复杂项目可以调高,简单任务可以调低
  max_iterations: 150
  
  # 最长运行时间(秒),防止循环永远跑下去
  # 默认 14400(4小时)
  max_runtime_seconds: 14400
  
  # 每隔多少次迭代保存检查点(用于中断恢复)
  checkpoint_interval: 5
  
  # 循环开始时发布的第一个事件
  starting_event: "work.start"
  
  # 必须出现过的事件,才允许 LOOP_COMPLETE(质量保证)
  # 确保完整工作流走完,防止某些帽子被跳过
  required_events: ["review.passed"]
  
  # 提示词文件路径(替代命令行 -p 参数)
  prompt_file: "PROMPT.md"

实际调优建议

# 快速原型(不需要完整质量保证)
event_loop:
  max_iterations: 20
  required_events: []

# 高质量生产代码
event_loop:
  max_iterations: 200
  max_runtime_seconds: 28800  # 8 小时
  required_events: ["review.passed", "validation.passed"]

cli:后端和提示词配置

cli:
  # AI 后端选择
  # 可选:claude, kiro, gemini, codex, amp, copilot, opencode, pi, custom
  backend: "claude"
  
  # 提示词传递方式
  # "arg":通过命令行 -p 参数传入
  # "file":从 prompt_file 指定的文件读取
  prompt_mode: "arg"

切换后端

# 使用 Kiro(速度更快,支持 AWS Bedrock)
cli:
  backend: "kiro"

# 使用 Gemini
cli:
  backend: "gemini"

core:运行时参数

core:
  # 规格文档目录(设计文档、需求文档放在这里)
  specs_dir: ".agents/scratchpad/"
  
  # 全局守则(注入到所有帽子的上下文里)
  guardrails:
    - "新鲜上下文每次迭代——把学到的东西保存到记忆里供下次使用"
    - "验证是必须的——测试/类型检查/lint 必须通过"
    - "YAGNI 原则——不写需求以外的功能"
    - "KISS 原则——最简单的能工作的方案"

guardrails 是最强大的自定义手段之一。它的内容会出现在每一顶帽子的上下文里,相当于给整个团队的全体成员都贴上了行为准则。

为不同项目定制守则

# 安全敏感的项目
core:
  guardrails:
    - "任何用户输入都必须经过严格验证,防止注入攻击"
    - "敏感信息(密码、密钥)绝不能出现在日志里"
    - "所有 SQL 操作必须使用参数化查询"

# 面向初学者的教学代码
core:
  guardrails:
    - "代码必须有详细中文注释,面向初学者"
    - "避免复杂的设计模式,用最直接的实现"
    - "每个函数不超过 20 行"

背压验证:通过帽子指令实现

已在第八章详细介绍。背压验证不是通过 ralph.yml 里的 backpressure: 配置节来实现——这个配置节并不存在。正确的方式是在帽子的 instructions 里声明验证要求,AI 自己负责运行验证并附上证据:

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现分配的任务。

      ## 背压要求
      在发出 review.ready 之前,你必须已完成:
      - tests: 运行 python -m pytest,全部通过
      - lint:  运行 flake8 .,0 个错误
      
      把实际输出结果附在事件载荷里。
      不要仅声称"测试通过",要运行并提供输出摘要。

core.guardrails 可以用来把验证要求全局化,让它出现在所有帽子的上下文里:

core:
  guardrails:
    - "发出任何完成事件前,必须运行 pytest 并确认全部通过"
    - "不要声称测试通过——要实际运行,并把输出附在事件载荷里"

hats:自定义帽子

除了使用预设帽子,你可以添加专属帽子来满足特定需求:

示例:添加文档生成帽子

hats:
  # 在所有代码任务完成后,自动生成文档
  doc_writer:
    name: "📚 文档写手"
    triggers: ["LOOP_COMPLETE"]    # 在循环快结束时触发
    publishes: ["docs.complete"]
    instructions: |
      你是文档写手。检查本次实现的所有代码,
      更新 README.md,确保包含:
      1. 新增功能的使用说明
      2. API 变更说明
      3. 安装/运行命令(如有变化)
      
      文档语言:中文
      风格:简洁,面向技术用户

示例:添加安全审计帽子

hats:
  security_auditor:
    name: "🔒 安全审计"
    triggers: ["review.passed"]
    publishes: ["security.approved", "security.rejected"]
    default_publishes: "security.approved"
    instructions: |
      你是安全审计者。检查最近提交的代码是否有安全漏洞:
      
      必查项:
      - SQL 注入风险(确认所有 DB 查询使用参数化)
      - 命令注入风险(确认所有 shell 调用已转义)
      - 敏感信息泄露(确认没有 API key 硬编码)
      - 不安全的反序列化
      
      只有所有必查项通过,才发布 security.approved。
      否则发布 security.rejected 并说明具体问题。

配置继承:基础配置 + 项目配置

对于有多个项目的用户,可以建立一套"基础配置",然后在各项目里继承和覆盖:

创建全局基础配置 ~/.ralph/base.yml

# 个人通用设置
event_loop:
  max_iterations: 150
  max_runtime_seconds: 14400

cli:
  backend: claude

core:
  guardrails:
    - "代码注释用中文"
    - "发出完成事件前,必须运行测试并确认通过"

然后在项目的 ralph.yml 里只写差异:

# 继承基础配置
extends: "~/.ralph/base.yml"

# 覆盖项目特定设置
cli:
  backend: kiro  # 这个项目用 Kiro

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现任务。发出 review.ready 前必须通过:
      - python -m pytest(全部通过)
      - mypy src/(0 个错误)
      把实际输出附在载荷里。

使用多个预设

你可以为不同场景准备多个预设文件:

项目根目录/
├── ralph.yml                    # 默认配置(日常开发用)
├── presets/
│   ├── quick-fix.yml            # 快速修复(减少迭代,不要求完整测试)
│   ├── full-feature.yml         # 完整功能开发(最严格)
│   ├── code-review.yml          # 代码审查
│   └── research.yml             # 研究调查

使用时:

# 日常开发
ralph run -p "添加搜索功能"

# 快速修复一个小 bug
ralph run -H presets/quick-fix.yml -p "修复登录按钮不响应的问题"

# 完整功能,要求最高质量
ralph run -H presets/full-feature.yml -p "实现支付功能"

常用配置速查

以下是一些常用的配置模式:

极简快速循环(原型阶段)

event_loop:
  max_iterations: 10
  required_events: []

hats:
  # 只用构建者,不用审查者和终结者
  builder:
    name: "⚙️ 快速构建者"
    triggers: ["work.start"]
    publishes: ["LOOP_COMPLETE"]
    instructions: |
      快速实现请求的功能,不需要完整的测试覆盖,
      确保代码能运行即可。

严格质量配置(生产代码)

event_loop:
  max_iterations: 200
  required_events: ["review.passed", "validation.passed"]

core:
  guardrails:
    - "测试覆盖率必须 > 80%"
    - "所有公共 API 必须有类型注解"
    - "没有 TODO 注释留在代码里"

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现任务。发出 review.ready 前必须通过:
      - pytest --cov=src --cov-fail-under=80
      - mypy src/ --strict
      - black --check . && isort --check-only .
      - 确认没有 TODO/FIXME 残留:grep -rn 'TODO\|FIXME' src/ 应为空
      把实际输出附在载荷里。

本章小结

  • event_loop 控制迭代次数、超时和必须经历的事件
  • cli 配置 AI 后端和提示词传递方式
  • core.guardrails 是全局行为准则,对所有帽子生效
  • 背压验证通过帽子的 instructions 实现,而非独立配置节
  • 自定义帽子让 Ralph 适应任何工作流
  • 建议为不同场景(快速原型、生产质量)维护不同的预设文件

下一章,我们展望 AI 自动化时代的工作新范式,以及 Ralph 在其中扮演的角色。

第十五章:展望——AI 自动化时代的工作新范式

一个值得思考的问题

在学完这本书之后,有一个问题值得你认真思考:

当 AI 可以自动完成越来越多的工作时,"工作"这件事的本质是什么?

这不是一个遥远的哲学问题。Ralph 已经能够在没有人工干预的情况下,完成相当复杂的软件开发任务。随着 AI 能力的提升,这个边界还会继续扩大。


当前的现实:AI 在工作中的位置

让我们诚实地看现状:

AI 目前做得很好的事

  • 根据规格说明生成代码
  • 运行测试,修复失败
  • 代码审查和质量检查
  • 文档生成
  • 研究和信息整合

AI 目前还需要人类的事

  • 定义"应该做什么"(需求的本质)
  • 判断是否符合业务价值(不只是技术正确性)
  • 处理模糊性和矛盾(现实世界充满了这些)
  • 建立与用户的信任关系
  • 负责任(当出了问题,是你负责,不是 AI)

Ralph 的设计非常清楚地体现了这个分工:人类做决策,AI 做执行。你定义"完成"的标准(背压关卡),AI 想办法达到这个标准。


一个正在演变的工作模型

在过去几年里,软件开发的工作方式已经发生了一个悄然的转变:

2020 年以前:开发者 → 直接写代码

2021-2023 年:开发者 + 代码补全 AI → 写代码更快

2024-2025 年:开发者 + AI Agent → 描述任务,AI 完成

现在和未来:开发者 + AI 编排框架(如 Ralph)→ 定义目标,AI 团队完成

每一步,开发者的角色都在向更高层次抽象:从"执行者"变成"决策者",从"写代码的人"变成"定义代码应该做什么的人"。


这对你意味着什么

如果你是开发者

你的核心价值不再只是"会写代码",而是:

系统思考能力:理解一个功能在整个系统里的影响,判断哪些设计决策是好的,哪些是坏的——这是 AI 很难模仿的判断力。

需求提炼能力:把模糊的业务需求转化成清晰的、可验证的技术规格。就像 Ralph 的 plan 功能演示的那样,把"我想要一个 XX 工具"变成"这个工具需要满足以下 10 个具体的验收标准"。

系统调优能力:不是调优具体的代码,而是调优整个 AI 工作流系统——哪些帽子需要更好的指令?哪些关卡太严格或太宽松?如何配置才能让 AI 团队工作得更好?

信任与风险管理:知道在什么时候信任 AI 的结果,什么时候需要深度检查,什么时候需要完全手动处理。

如果你不是开发者

Ralph 今天主要服务于软件开发场景,但它代表的工作模型——定义目标、设立质量标准、让 AI 团队自动完成——适用于更广泛的知识工作:

研究员:定义研究问题和评判标准,让 AI 研究团队收集资料、分析数据、生成初稿,你负责最终的学术判断。

产品经理:把用户需求变成清晰的需求文档(类似 Ralph 的设计文档),然后让 AI 生成技术规格、测试用例、甚至用户故事。

内容创作者:定义写作目标、风格标准、受众特征,让 AI 完成草稿和迭代,你负责最终的编辑判断和品牌声音把控。


Ralph 正在发展的方向

作为一个活跃开发中的开源项目,Ralph 还在快速演进。从当前的版本和社区讨论中,可以看到几个方向:

更智能的循环控制:未来的 Ralph 可能能够根据任务复杂度自动调整迭代策略,不需要手动设置 max_iterations

更丰富的集成:与 IDE、项目管理工具(Jira、Linear)、CI/CD 流水线更深度的集成,让 Ralph 成为整个开发流水线的一部分。

更低的使用门槛:更好的 Web 界面、更直观的配置方式,让非技术用户也能配置和使用 Ralph。

多模态工作流:不只是代码,而是代码 + 图形设计 + 文档 + 测试的综合工作流。


一个关于"控制感"的平衡

学完这本书,你可能有一个隐隐的不安:

把工作交给 AI 自动完成,我还有控制感吗?

这是一个真实的、值得认真对待的问题。

Ralph 的设计哲学提供了一个答案:控制感不在于参与每一步,而在于定义规则

当你:

  • 定义了清晰的需求(ralph plan
  • 设立了质量关卡(backpressure
  • 设计了帽子角色(hats
  • 积累了项目记忆(memories.md

你对工作的控制力,实际上比手动完成每一步更强——因为你定义了系统,而不只是执行了步骤


最后的建议

从小任务开始:不要第一次就用 Ralph 处理最关键的生产代码。从一个独立的小功能开始,感受循环是如何工作的,建立信任感。

投入时间学习配置:Ralph 的威力在配置里。一个精心调优的背压关卡,比模糊的帽子指令有效 10 倍。

积累记忆文件:最有价值的记忆是项目里那些"反常识但重要"的约束。每当你发现 AI 重复犯某个错误,就是该向记忆文件添加一条的时候了。

保持审计习惯:即使 Ralph 说"任务完成",定期检查生成的代码,保持对代码库的理解。AI 很强,但它不是你,也不了解你的产品用户。

拥抱迭代:Ralph 让迭代变得廉价。一个方向不对?停掉循环,调整需求,重新跑。不要害怕扔掉一次循环的结果,重新来过。


结语

我们正处在一个工具能力快速扩张、工作方式快速演变的时代。

Ralph 代表的不只是一个工具,而是一种新的工作思维:把 AI 当成一个可编程的团队,而不只是一个聪明的助手

这要求你建立新的技能:定义目标、设立标准、设计系统、调优流程。这些技能比"会用 AI 工具"更深,也更持久。

AI 会一直进步,但懂得如何与 AI 协作的人,永远都是稀缺的。

希望这本书是你探索这个新世界的一个起点。


"我们要一直做,直到做完为止。"——Ralph Wiggum(《辛普森一家》)

有时候,最深刻的智慧来自最简单的话。

附录:常用命令速查

基本命令

命令说明
ralph --version查看版本号
ralph doctor环境诊断,检查是否配置正确
ralph preflight运行前检查,验证配置文件
ralph --help查看所有命令

初始化

# 在当前目录初始化 Ralph(使用 Claude 后端)
ralph init --backend claude

# 使用 Kiro 后端
ralph init --backend kiro

# 使用内置预设(通过 run 命令指定)
ralph run --hats builtin:code-assist -p "任务描述"

运行循环

# 直接用提示词运行
ralph run -p "你的任务描述"

# 使用内置预设(推荐)
ralph run -H builtin:code-assist -p "任务描述"

# 或使用本地下载的预设文件
ralph run -H presets/code-assist.yml -p "任务描述"

# 从文件读取提示词
ralph run --prompt-file PROMPT.md

# 限制最大迭代次数
ralph run -p "任务" --max-iterations 20

# 指定 AI 后端(覆盖配置文件)
ralph run -p "任务" --backend kiro

# 记录会话(用于调试或创建测试 fixture)
ralph run -p "任务" --record-session session.jsonl

规划(PDD)

# 通过问答方式把想法变成设计文档
ralph plan "你的想法描述"

# 查看生成的设计文档
cat .agents/scratchpad/implementation/*/design.md

循环管理

# 查看所有活跃循环
ralph loops list

# 查看所有循环(含已完成)
ralph loops list --all

# 停止特定循环
ralph loops stop loop-abc

# 查看某个循环的事件历史
ralph loops history loop-abc

# 查看某个循环的实时输出
ralph loops logs loop-abc --follow

# 废弃循环并清理 worktree
ralph loops discard loop-abc

任务管理

# 列出所有任务
ralph tools task list

# 列出待处理的任务
ralph tools task ready

# 查看任务详情(task-id 示例:task-1776737176-532e,由 Ralph 生成)
ralph tools task show task-1776737176-532e

# 手动确保任务存在(create or update;签名:--key <KEY> <TITLE> [--description <DESC>])
ralph tools task ensure --key "my-key" "任务标题" --description "任务描述"

# 手动关闭/重开任务
ralph tools task close task-1776737176-532e
ralph tools task reopen task-1776737176-532e

记忆管理

# 列出所有记忆
ralph tools memory list

# 添加记忆
ralph tools memory add "重要说明:这个项目不允许使用 X 库"

# 查看记忆文件
cat .ralph/agent/memories.md

# 手动编辑记忆
vim .ralph/agent/memories.md

事件系统

# 查看所有事件历史
ralph events

# 查看最近 20 个事件
ralph events --last 20

# 按话题过滤
ralph events --topic review

# 手动注入事件(向正在运行的循环发送指引)
ralph emit human.guidance "请用中文写注释"

# 触发波浪(并行处理多个工作单元)
ralph wave emit review.file \
  --payloads "src/a.py" "src/b.py" "src/c.py"

帽子管理

# 列出配置的帽子
ralph hats

# 查看某个帽子的详细配置
ralph hats show builder

Web 仪表盘

# 启动 Web 仪表盘(自动打开浏览器)
ralph web

# 不自动打开浏览器
ralph web --no-open

# 指定端口
ralph web --backend-port 4000

# 指定工作区
ralph web --workspace /path/to/project

Telegram 机器人

# 引导式配置(Ralph 的 bot 目前就是 Telegram,无需额外 flag)
ralph bot onboard

# 查看连接状态
ralph bot status

# 发送测试消息
ralph bot test

清理

# 预览会删除什么(不实际删除)
ralph clean --dry-run

# 清理诊断日志
ralph clean --diagnostics

# 手动编辑记忆(直接编辑文件,删除不再相关的条目)
vim .ralph/agent/memories.md

# 废弃并清理某个并行循环的 worktree
ralph loops discard loop-abc

诊断和调试

# 开启诊断模式(保存详细日志)
RALPH_DIAGNOSTICS=1 ralph run -p "任务"

# 查看诊断日志
ls .ralph/diagnostics/

# 查看工具调用记录
jq 'select(.type == "tool_call")' \
  .ralph/diagnostics/*/agent-output.jsonl

# 查看帽子激活记录
jq 'select(.type == "hat_activation")' \
  .ralph/diagnostics/*/orchestration.jsonl

# 运行 E2E 测试(模拟模式)
ralph run -p "任务" --dry-run

MCP 服务器(IDE 集成)

# 在当前目录启动 MCP 服务器
ralph mcp serve

# 指定工作区
ralph mcp serve --workspace-root /path/to/project

# 使用环境变量指定工作区
RALPH_API_WORKSPACE_ROOT=/path/to/project ralph mcp serve

常用工作流命令

完整功能开发流程

# 1. 规划(可选,适合复杂功能)
ralph plan "功能描述"

# 2. 实现
ralph run -H builtin:pdd-to-code-assist -p "功能描述"
# 或
ralph run -H builtin:code-assist \
  --prompt ".agents/scratchpad/implementation/feature-name/"

# 3. 监控进度
ralph loops

# 4. 查看结果
ralph events --last 20
ralph tools task list

快速 bug 修复

ralph run -p "修复:[具体描述 bug 的现象和位置]" \
  --max-iterations 10

代码审查

ralph run -H builtin:review \
  --prompt "审查最近的修改,检查安全性和代码质量"

并行任务

# 终端 1
ralph run -p "任务 A"

# 终端 2(同时)
ralph run -p "任务 B"

# 监控
ralph loops

配置文件速查模板

最简配置

event_loop:
  max_iterations: 50

cli:
  backend: claude

标准配置(Python 项目)

event_loop:
  max_iterations: 150
  max_runtime_seconds: 7200

cli:
  backend: claude

core:
  guardrails:
    - "代码注释用中文"

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现任务。发出 review.ready 前必须通过:
      - python -m pytest(全部通过)
      - black --check .(0 个格式错误)
      把实际输出附在载荷里。

标准配置(Node.js 项目)

event_loop:
  max_iterations: 150

cli:
  backend: claude

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现任务。发出 review.ready 前必须通过:
      - npm test
      - npm run lint
      - tsc --noEmit
      把实际输出附在载荷里。

标准配置(Rust 项目)

event_loop:
  max_iterations: 200

cli:
  backend: claude

hats:
  builder:
    name: "⚙️ Builder"
    triggers: ["tasks.ready"]
    publishes: ["review.ready"]
    instructions: |
      实现任务。发出 review.ready 前必须通过:
      - cargo fmt --all -- --check
      - cargo clippy --all-targets --all-features -- -D warnings
      - cargo test --all
      把实际输出附在载荷里。

.ralph/ 目录结构说明

.ralph/
├── agent/
│   ├── memories.md          ← AI 的跨会话记忆(可手动编辑)
│   ├── tasks.jsonl          ← 运行时任务状态
│   └── decisions.md         ← AI 的决策记录(置信度 < 80 时)
├── diagnostics/             ← 诊断日志(每次运行一个目录)
│   └── 2024-01-15T10-30-00/
│       ├── agent-output.jsonl
│       ├── orchestration.jsonl
│       └── errors.jsonl
├── loops.json               ← 所有循环的注册表
├── loop.lock                ← 主循环的 PID 和提示词
├── tasks/                   ← 代码任务文件(.code-task.md)
└── specs/                   ← 规格文档(设计文档等)

环境变量

变量名说明
RALPH_TELEGRAM_BOT_TOKENTelegram 机器人 Token
RALPH_DIAGNOSTICS=1开启诊断模式
RALPH_API_WORKSPACE_ROOTMCP 服务器工作区路径
RALPH_BACKEND覆盖配置文件中的后端设置
RALPH_LOG_LEVEL日志级别(debug/info/warn/error)