--- title: 260307-自我改进的编码智能体 description: 探索如何设计自我改进的 AI 编码智能体循环,让它在你离线时持续编写、测试并交付代码 author: Addy Osmani source: https://addyosmani.com/blog/self-improving-agents/ date: '2026-03-07' category: 02-technical-architecture tags: - 编码智能体 - 自动化编码 - 持续集成 - 智能体循环 - Claude Code --- # 自我改进的编码智能体 **作者:Addy Osmani** **原文:[查看原文](https://addyosmani.com/blog/self-improving-agents/)** 想象一下:你结束一天工作,第二天醒来,新功能已经完成编码、通过测试,并进入待审查状态。这就是自主编码智能体最吸引人的地方——借助 **Claude Code** 这类工具,把编码、验证与交付组织进一个持续循环里,即使你离线,它也能继续推进工作。 这篇文章会拆解这类“自我改进循环”怎么搭:从任务编排、上下文文件、内存持久化,到 QA 验证、扩展方式、调试方法和风险控制。 **_这篇文章也是对 Ryan Carson 那篇[《如何让你的智能体在你睡觉时学习和交付》](https://x.com/ryancarson/status/2016520542723924279)的补充。我们最近聊了很多关于智能体编码未来的想法,这篇文章主要是把其中一些技术层面的要点展开讲清楚。_** ## **“持续编码循环”(Ralph Wiggum 技术)** 这套方法的核心,是一个不断迭代的**智能体循环**,也常被称为 “Ralph Wiggum” 技术(由 Geoffrey Huntley、Ryan Carson 等人推广)。关键思路很简单:把开发工作拆成一批小任务,再让编码智能体逐个处理。 每轮迭代通常遵循同一套周期: 1. **选择下一个任务**:从待办列表里挑出尚未完成的任务(例如一个[任务 JSON 文件](https://github.com/snarktank/compound-product#:~:text=Each%20iteration%20of%20the%20loop%3A))。 2. **实现任务**:围绕这个具体功能或修复改代码。 3. **验证更改**:运行测试、类型检查或其他质量检查。 4. **提交代码**:验证通过后,把更改提交到仓库。 5. **更新任务状态**:标记完成,并记录这轮学到的内容。 6. **重置智能体上下文**:用新上下文进入下一轮,直到所有任务完成,或触发停止条件。 这种做法的关键价值,是**每轮都重新开始,但不会重新失忆**。上下文不靠一段越来越长的对话来硬撑,而是靠外部文件和结构化状态来传递。这样能有效避免长上下文不断膨胀之后的混乱,也能让每次执行都更聚焦。 与其用一个巨大提示去要求模型“一次做完整个功能”,不如不断给它一个边界清晰、目标明确的小任务。这样通常更稳,也更容易验证。 ### **把任务切得足够小,而且标准明确** 工作拆分是这类系统成败的第一步。每个任务都应该足够小,小到能在一次 AI 会话里完成;同时也要有明确的通过/失败标准。 例如,与其写“做完整个仪表板”,不如拆成类似这样的任务: “新增一个导航栏,包含首页、关于、联系三个链接;当前页面对应链接高亮显示。” 这种粒度有两个好处: - 智能体更容易知道“做完”到底长什么样 - 一旦结果不符合预期,系统也更容易回滚、修正、重试 **落地建议:先写清楚规格,再转成任务列表。** 先把功能需求写成清晰的规格说明,再把它拆成结构化任务列表,例如 `prd.json`。像 Carson 提供的 [**/prd 和 /tasks 技能**](https://github.com/snarktank/compound-product#:~:text=Two%20skills%20are%20included%20for,PRD%20creation%20and%20task%20generation) 就是在做这件事。 最终,你需要的是一份机器可读、验收标准明确、可逐步执行的待办清单。 ### **编排循环** 驱动循环本身,其实不一定复杂。[Carson 的实现](https://github.com/snarktank/ralph)本质上就是一个不断调用智能体的脚本,可能是 Bash,也可能是 Python。 下面是一个很简化的伪代码示意: ```bash while :; do amp run -s prompt.md -o progress.txt # 使用提示运行 Amp,并保存输出 if grep -q "COMPLETE" progress.txt; then break; fi done ``` 真实流程里,脚本通常会完成这些事: - 读取任务列表 - 选出下一个待办任务 - 拼装提示词与相关上下文 - 调用模型执行 - 跑验证脚本 - 更新状态文件与日志 关键点在于:**每一轮都是隔离的**。你不是让同一个对话无限延长,而是让智能体在每次迭代时带着外部上下文重新开始。 **复合循环**也是常见进阶做法。比如 [**Compound Product**](https://github.com/snarktank/compound-product#:~:text=A%20self,priority%2C%20and%20autonomously%20implements%20it) 会先跑分析循环,再跑规划循环,最后才进入执行循环。也就是说,智能体不仅负责写代码,还能先参与判断“应该先做什么”。不是每个项目都需要这么完整的自动化,但它很好地展示了:多个循环完全可以首尾相接,形成持续交付管线。 ## **上下文与内存的最佳实践:AGENTS.md 手册** 这类循环最强的机制之一,是把经验显式写进持久化文件,而不是指望长对话自己记住一切。 最常见的文件就是 **`AGENTS.md`**。它本质上是一份持续更新的运行手册:记录项目约定、踩过的坑、需要反复提醒智能体的注意事项,以及最近新增的重要上下文。 每完成一个任务,你都可以把关键信息追加进去。例如: - “这个仓库统一用某个库处理表单,不要另起一套方案。” - “更新用户模型时,记得同步更新审计日志,否则测试会失败。” - “某个旧接口已弃用,统一改走新路径。” 随着时间推移,`AGENTS.md` 会逐渐变成一个高价值的项目知识库。它不是“给人看的说明书”这么简单,更是下一轮智能体执行时的重要约束来源。 一个实用的组织方式,是把 `AGENTS.md` 拆成几类内容: - **模式和约定**:比如目录结构、组件组织方式、常用架构模式 - **陷阱**:容易遗漏、但一旦遗漏就会出错的点 - **风格与偏好**:例如测试风格、代码风格、依赖使用原则 - **最近变更**:最近踩过的坑、做过的修正和原因 这里有个很重要的原则:**条目要短、要准、要可执行。** 它不是百科,不需要写成长文。你写进去的内容,最好是一条智能体在下一轮就能直接据此行动的规则。 同时也要注意上下文大小。`AGENTS.md` 不是越长越好;如果越积越多却没人整理,最后也会变成噪声。一个更稳妥的做法是只保留当前最重要、最容易反复踩坑的信息,把过时内容清掉或归档。 ## **内存持久化与复合学习策略** 除了 `AGENTS.md`,成熟的循环通常还会维护多条“外部记忆通道”。Carson 的 Ralph 体系里,至少会用到以下几类: - **Git 提交历史**:每轮迭代都提交代码。下一轮如果需要了解之前改了什么,直接看 `git diff` 或 `git log` 就行。 - **进度日志(`progress.txt`)**:记录每轮做了什么、哪里成功、哪里失败、错误信息是什么。 - **任务状态文件(如 `prd.json`)**:记录每个需求是否完成,避免重复劳动。 - **长期知识文件(`AGENTS.md`)**:沉淀更长期、跨任务复用的约束与经验。 这些外部工件共同构成了一种“复合学习”机制。它不是机器学习意义上的在线训练,而是通过不断把结果写回系统,让后续迭代站在前面工作的基础上继续推进。 例如,一轮迭代里发现某个 API 已废弃,下次再遇到相关任务时,智能体就不必重新踩一次同样的坑;如果测试日志已经记录过某个失败模式,后续也可以直接参照处理。 你当然也可以做得更复杂,比如用向量数据库存错误模式和 diff 摘要,再在新任务开始前检索相似案例。但很多时候,只要 `AGENTS.md`、任务状态文件和日志维护得足够好,复杂记忆层并不是必需品。 一个值得反复确认的点是:**这些记忆只有在下一轮真的被注入上下文时才有价值。** 文件写在那里,不等于模型就一定会用到。你需要确保提示模板或运行脚本确实会把它们带进下一轮。 ## **质量保证:测试与验证循环** 如果没有自动验证,自主编码智能体很容易把“看起来像完成了”的东西误当成“真的完成了”。所以,测试与检查必须是循环中的一等公民。 - **单元测试与集成测试**:如果仓库里已经有稳定的测试套件,让智能体在实现任务后跑 `npm test` 或 `pytest`,这是最基础也最有效的反馈机制。 - **类型检查与 Lint**:像 `tsc`、MyPy、ESLint 这样的静态分析工具,可以快速拦住很多低成本错误。 - **模拟 CI 检查**:即便不是正式 CI 环境,你也可以在本地把构建、测试、检查串起来,当作循环的一部分。 - **必要时让智能体自己验收**:如果是 UI 改动,可以让它启动浏览器或使用相应技能做页面检查,确认交互和视觉状态是否达标。 Simon Willison 提到过一个很实用的经验:如果仓库本身已经有高质量测试,智能体通常会自然模仿这些测试风格。因此,想让智能体写出更可靠的测试,最稳妥的办法之一不是多讲大道理,而是让代码库里已经存在值得模仿的范式。 ## **扩展:从单循环到多循环** 很多人会自然想到:既然一个循环能跑,那多个循环是不是能并行跑得更快?答案是可以,但复杂度会迅速上升。 最简单的扩展方式,是让不同循环跑在不同范围里: - 一个循环专做前端 - 一个循环专做后端 - 或者多个功能分支各跑一个夜间循环 但一旦多个智能体开始同时修改同一片代码,问题就会变成典型的分布式协调问题:文件冲突、重复劳动、互相等待、任务边界不清,都会出现。 实践里更有效的一种模式,是**规划者 - 工作者**分层。一个更高层的智能体负责理解全局、拆分任务、决定优先级;下层智能体只负责执行局部任务。这样比让多个智能体自由竞争同一组任务更稳。 不过,对大多数独立开发者来说,现阶段真正高回报的通常不是把规模盲目扩大,而是把**单个循环做得足够稳、足够长、足够可恢复**。很多时候,一个可靠的夜间循环,比一群难以管理的并行循环更有价值。 ## **监控、调试与反馈仪表化** 既然你把一部分开发工作交给了智能体,就必须对它的行为保持可观察性。最常见也最有效的做法包括: - **实时日志**:让循环持续输出当前任务、测试结果和错误信息,方便你判断它有没有卡住。 - **检查点提交**:每轮都提交代码,这样你可以随时用 `git log`、`git diff` 回看最近发生了什么。 - **任务状态概览**:准备一条能快速查看所有任务状态的命令或脚本,随时判断整体进度。 - **性能指标**:记录每轮耗时、token 成本和失败重试次数,帮助你识别瓶颈。 - **停止条件**:比如最大迭代数、最长运行时间、连续多轮无提交时自动停止,避免系统空转。 必要时,你也可以让智能体输出简短的“失败原因与下一步计划”,帮助定位它为什么卡住。但这类内省信息要适度使用,太多反而会污染主循环上下文。 ## **风险管理与保障措施** 给编码智能体写权限、执行权限,确实很强大,但也一定要配套边界。 ### **防止破坏性动作** - **只在功能分支或隔离仓库里运行**:不要直接对 `main` 下手。 - **权限分级**:只读操作尽量自动放行,写操作、外部发布、删除操作则保留人工确认。 - **沙箱运行**:最好在容器或虚拟机里执行,尤其是它需要跑代码、跑测试时。 - **随时可中断**:你必须清楚知道怎么第一时间停掉循环。 ### **处理错误假设与任务偏移** 编码智能体的真实风险,往往不是“它很笨”,而是**需求约束不够清楚**,或者**长时间运行后逐渐偏离原目标**。对应的缓解方式通常包括: - **把规格写清楚**:验收标准越明确,偏移空间越小。 - **用验证抓问题**:测试、类型检查和运行反馈,能抓住很多不真实的调用、错误接口和逻辑偏差。 - **定期重新聚焦**:循环跑得太久时,可以暂停、重新规划剩余任务,再继续执行。 - **必要时多模型交叉检查**:关键节点可引入第二个模型做 diff 审查或结果复核。 这里要特别强调一点:很多“智能体没做到 X”的情况,根因并不是它能力低,而是规格、提示或上下文里根本没有把 X 说清楚。循环设计得越严谨,这类偏差就越少。 ### **上下文膨胀与优化** 随着项目增长,`AGENTS.md`、`progress.txt` 和任务文件都会越来越大,不可能每次都原样塞进上下文。常见优化方式包括: - **总结旧内容**:保留关键结论,把原始长日志归档。 - **按任务裁剪上下文**:与当前任务无关的历史内容不要强行带入。 - **依靠模型已有通用知识**:项目特有信息优先,通用文档不必一股脑重复喂给它。 例如,如果这是一个使用 React Hooks 和 Vite 的项目,你通常没必要把整份 React 文档都塞给模型;真正更值钱的是项目自己的边界、约定和坑点。 ### **人工监督与持续改进** 最后,把整个系统当作一个持续演进的过程来看。它不是“搭完就自动完美运转”的装置,而是一套需要不断调参、不断校准的工作流。 你的角色也会随之变化:你不再主要花时间逐行敲代码,而是更像在设计流程、写规格、看结果、做关键判断的那个人。 还要持续关注**成本**。循环一旦卡住,token 消耗会迅速放大,所以预算上限、停止条件和异常告警都很有必要。但如果整体工作流设计得好,回报也会非常明显:很多重复而细碎的执行工作,会被可靠地压进一个可以持续运行的系统里。 自主编码智能体已经不再只是概念。只要流程设计得足够扎实,它们确实可以承担持续编码、持续验证和持续推进交付的那部分工作。 每一轮迭代,系统和你的工作方式都会一起变得更成熟。 _这篇文章使用 Gemini 做了可读性整理。_