自我改进的编码智能体
作者:Addy Osmani
原文:查看原文
想象一下:你结束一天工作,第二天醒来,新功能已经完成编码、通过测试,并进入待审查状态。这就是自主编码智能体最吸引人的地方——借助 Claude Code 这类工具,把编码、验证与交付组织进一个持续循环里,即使你离线,它也能继续推进工作。
这篇文章会拆解这类“自我改进循环”怎么搭:从任务编排、上下文文件、内存持久化,到 QA 验证、扩展方式、调试方法和风险控制。
这篇文章也是对 Ryan Carson 那篇《如何让你的智能体在你睡觉时学习和交付》的补充。我们最近聊了很多关于智能体编码未来的想法,这篇文章主要是把其中一些技术层面的要点展开讲清楚。
“持续编码循环”(Ralph Wiggum 技术)
这套方法的核心,是一个不断迭代的智能体循环,也常被称为 “Ralph Wiggum” 技术(由 Geoffrey Huntley、Ryan Carson 等人推广)。关键思路很简单:把开发工作拆成一批小任务,再让编码智能体逐个处理。
每轮迭代通常遵循同一套周期:
- 选择下一个任务:从待办列表里挑出尚未完成的任务(例如一个任务 JSON 文件)。
- 实现任务:围绕这个具体功能或修复改代码。
- 验证更改:运行测试、类型检查或其他质量检查。
- 提交代码:验证通过后,把更改提交到仓库。
- 更新任务状态:标记完成,并记录这轮学到的内容。
- 重置智能体上下文:用新上下文进入下一轮,直到所有任务完成,或触发停止条件。
这种做法的关键价值,是每轮都重新开始,但不会重新失忆。上下文不靠一段越来越长的对话来硬撑,而是靠外部文件和结构化状态来传递。这样能有效避免长上下文不断膨胀之后的混乱,也能让每次执行都更聚焦。
与其用一个巨大提示去要求模型“一次做完整个功能”,不如不断给它一个边界清晰、目标明确的小任务。这样通常更稳,也更容易验证。
把任务切得足够小,而且标准明确
工作拆分是这类系统成败的第一步。每个任务都应该足够小,小到能在一次 AI 会话里完成;同时也要有明确的通过/失败标准。
例如,与其写“做完整个仪表板”,不如拆成类似这样的任务:
“新增一个导航栏,包含首页、关于、联系三个链接;当前页面对应链接高亮显示。”
这种粒度有两个好处:
- 智能体更容易知道“做完”到底长什么样
- 一旦结果不符合预期,系统也更容易回滚、修正、重试
落地建议:先写清楚规格,再转成任务列表。 先把功能需求写成清晰的规格说明,再把它拆成结构化任务列表,例如 prd.json。像 Carson 提供的 /prd 和 /tasks 技能 就是在做这件事。
最终,你需要的是一份机器可读、验收标准明确、可逐步执行的待办清单。
编排循环
驱动循环本身,其实不一定复杂。Carson 的实现本质上就是一个不断调用智能体的脚本,可能是 Bash,也可能是 Python。
下面是一个很简化的伪代码示意:
while :; do
amp run -s prompt.md -o progress.txt # 使用提示运行 Amp,并保存输出
if grep -q "<promise>COMPLETE</promise>" progress.txt; then break; fi
done真实流程里,脚本通常会完成这些事:
- 读取任务列表
- 选出下一个待办任务
- 拼装提示词与相关上下文
- 调用模型执行
- 跑验证脚本
- 更新状态文件与日志
关键点在于:每一轮都是隔离的。你不是让同一个对话无限延长,而是让智能体在每次迭代时带着外部上下文重新开始。
复合循环也是常见进阶做法。比如 Compound Product 会先跑分析循环,再跑规划循环,最后才进入执行循环。也就是说,智能体不仅负责写代码,还能先参与判断“应该先做什么”。不是每个项目都需要这么完整的自动化,但它很好地展示了:多个循环完全可以首尾相接,形成持续交付管线。
上下文与内存的最佳实践: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 做了可读性整理。
