概述编码代理框架的结构,以及如何通过记忆、技能和可扩展循环实现自进化。
AI translation, not an official translation. Refer to the original for technical details.
Adapted from @mem0ai# 具有记忆能力的自进化框架 如何在不训练模型的情况下,让你的编码代理在处理下一张 Linear 工单或任务时表现得更好? 我的意思是,我们留下一些备注?在 AGENTS.md 中添加一条规则?为这个使用场景创建一项技能?我们大多数人都在做这些事,只是没有给它命名——我们只是尝试不断改进设置,让它明天不再犯同样的错误,而这个"设置"就是你的框架(harness)。 > > Cursor 公开了他们重新调整框架的方式,后来还撰文介绍了一次历时一周的研究型浏览器多代理运行,并在查看日志后调整了角色分工。 > OpenAI 将 Codex 循环以可供背诵的序列形式发布出来。 > Anthropic 则通过手工编写技能来实现。(https://cursor.com/blog/continually-improving-agent-harness) (https://cursor.com/blog/self-driving-codebases) (https://openai.com/index/unrolling-the-codex-agent-loop/) (https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills) 而我今天真正想谈的重点是——一个能够自进化的框架,以及记忆在其中所处的位置。 ## 通用框架 通用框架的样子是这样的:编码代理是一个冻结的模型加上一个与之通信的程序。每一轮交互中,该程序会构建: - 一个提示词(prompt) - 工具列表 - 执行模型所请求的操作 - 追加执行结果,然后进行摘要或停止 好了,这是一种非常笼统的表达方式,但这就是框架。 Claude Code、Codex、Cursor、Pi、Hermes 都采用相同的循环,只是厚度不同,而下面是我们实际可以查看源码的两个。 ___ ## Pi Pi 是一个极简框架,我正是因为这一点而喜欢它。(https://pi.dev/) - 主页介绍:"让 Pi 来构建你想要的东西,或者安装一个按你的方式运行的包。" - 核心工具:read、write、edit、bash - 循环:推理、调用工具、观察、再次推理 我们挂载四类东西: - 扩展。TypeScript 钩子:agent/pre-step、agent/request、tool start/end。记忆在下一次推理步骤之前注入。压缩策略可替换。 - 技能。遵循 agentskills.io 的格式。名称写入提示词,完整文件仅在被选中时加载,以保持缓存的热度。 - 提示词模板。/name 会展开一个 Markdown 文件。 - 主题。即 TUI 界面,这里不是重点。 指令以文件形式存在:全局 AGENTS.md,然后是父目录,然后是当前工作目录。SYSTEM.md 可替换或追加系统提示词。会话以树形结构组织,/tree 可以恢复任意节点。压缩策略大致保留最后 20,000 个原始 token,其余部分进行摘要处理。 同一个运行时可以作为 TUI、JSON、RPC 或 SDK 使用,最后一种方式的意义比听起来更大,因为一个只能交互使用的框架无法进入自动化的外层循环。 因此,官方 Pi 并不会在评分后重写自身,它只是暴露出这些接口。当自我改进循环存在时,它是以包(package)的形式实现的。我们稍后会再回到这个代码库。 ____ ## Hermes Hermes 来自 Nous,框架更厚,但仍是相同的循环。(https://github.com/NousResearch/hermes-agent) run_conversation:任务 ID,追加用户消息,构建或复用已缓存的系统提示词。如果历史记录超过上下文的一半,先进行压缩。根据提供商格式化内容(chat completions、Codex Responses、Anthropic Messages)。注入临时的预算警告和上下文压力提示。调用模型。处理工具调用:执行、追加、循环。处理文本输出:持久化会话,刷新记忆,返回。 提示词分为三个层级: - 稳定层(身份、工具、技能索引) - 上下文层(来自当前工作目录的 AGENTS.md) - 易变层(记忆快照、用户画像、时间戳) 它们在压缩时重建前缀,因此缓存保持热状态。会话存储在带搜索功能的 SQLite 中。压缩会关闭当前会话并开启一个子会话,因此你得到的是血缘谱系,而非一个被改写的单一数据块。工具是一个注册表加上一个暴露列表。默认迭代预算为 500 次。子代理存在,且父代理死亡时子代理也随之死亡。 不过这仍然是通用框架,尚未实现自我进化。 ## 两者实际上在构建什么 两者都在决定模型在本轮能看到什么。模型永远看不到整个代码仓库,它看到的是一条 token 窗口。 举一个具体案例:一个 Node 安装不断重新生成 pnpm-lock.yaml,已到第 17 轮,进程已运行二十分钟。 左侧边缘是稳定的,因此可以缓存:系统提示、工具、AGENTS.md。然后可能有一条注释——这个仓库的安装产物是一个锁文件,不要重新生成它。接着是替换了第 1 至第 11 轮的摘要,那些轮次已从窗口中消失。然后是原始的尾部内容和最新的 bash 输出。 如果"锁文件"这条经验从未被写入下一个进程会检索的地方,那么下一张工单的第 1 轮就是一个空线程,然后是同样的 npm install。/tmp 下的辅助进程随进程一同消亡。如果某件事没有写到磁盘上、写到新进程会打开的地方,它就等于没有发生过。而下文所有内容,都是关于谁来向那条窗口写入内容。 ## 这些系统如何变得自我进化? Hermes,续 同样的两套框架,现在加入额外的循环——这也是 Hermes 谈论"学习"的原因。在一次成功且未中断的对话轮次之后,一个 fork 出的代理可能会运行。 - 大约每 10 轮用户对话,它可以写入 MEMORY.md 或 USER.md - 大约每 10 次工具调用,如果技能工具已启用,它可以修补或创建一个 SKILL.md 该 fork 继承了已缓存的系统提示,因此他们测量到成本降低了约 26%,它只获得记忆和技能工具,最多迭代十六次,它无法对仓库执行 bash 操作,也无法编辑运行 run_conversation 的 Python 代码。文档中记载的优先级是:先修补已加载的内容,然后深化、在其下添加文件,最后才创建新技能。你可以启用写入审批门控,并将差异暂存至 ~/.hermes/pending/ 下。 下一次会话中,assemble 会加载这些文件,程序还是同一个程序。在他们的划分中,记忆是应常驻上下文的小型持久事实,技能则是按需加载的较长过程。 轨迹写入下一个窗口可以打开的文件,评分来自审核模型的判断,也可能加入人工评审,而非依赖编程基准测试。 __ Pi,续 官方 Pi 目前还不为你提供那种 fork 机制。Prime Intellect 在 Pi 之上构建了 Prime Agent,他们的 README 中有明确说明。(https://www.primeintellect.ai/blog/prime-agent) 面向模型的工具变成了一个持久化的 IPython 内核。文件、shell、技能、子代理都只是 Python 调用。上下文是一个变量,而不仅仅是一段聊天记录。子代理是 rlm(task),一个异步句柄。TypeScript 宿主仍然负责管理提供者、会话、子代理和安全性。 他们新增的是一个持续运行的框架,包含四个存储,每个存储都具有创建/读取/更新/删除操作:提示注释、子代理规格、技能、记忆。这些对象既以 rlm.harness 的形式存在于内核中,也存在于磁盘上。 /refine 是额外的写入器。一个后台代理读取当前轨迹,并对上述四项之一应用最小的、有证据支撑的编辑,记录精炼日志、创建快照以便回滚,且不会改写不可变的基础系统提示。pi-continual 将同样的思路以 .pi/harness/ 下的 Markdown 形式复制回普通的 Pi 上。提交该目录后,精炼内容便成为一个可审查的差异文件。(https://www.npmjs.com/package/pi-continual) 所以 Hermes 在转折之后、在一个分支中写入,Prime 从带有回滚日志的轨迹中途写入任务,两者都持久化文件,都不替换 coding_agent.py。 Prime Agent 报告 ARC-AGI-3 RHAE Best@1 从 30% 提升至 95.5%(Karten 等人),这不是 SWE-bench,是不同的游戏,也是不同维度的写入。(https://arxiv.org/abs/2608.23552) ## 因此,一个常见的观察 这里实际引入了什么——内部循环没有变化:组装、采样、工具、追加、压缩。出现的是第二个写入者,有额外的东西被允许去改变下一个窗口所包含的内容。 在 Hermes 中,那个写入者是一个可能写入 MEMORY.md 或 SKILL.md 的分支。在 Prime 中,是针对四个存储的 /refine。在你自己的设置中,是你在一个糟糕的任务单之后编辑 AGENTS.md。 一个普通的编程智能体检查代码库、编辑文件、运行测试、提交补丁。一个自我演化的智能体做同样的事,并将这些交互转化为持久化更新——持久化是分水岭。一次较长的尝试,如果在 issue 结束时丢弃了改变,那就不算。(Zhou 等人已经为此命名。)(https://arxiv.org/abs/2608.03392) 一旦你看到了第二个写入者,你也会发现人们一直在把三种不同的写入方式引用为同一个数字。 1. 在一个 issue 内部发明的工具,随进程一起删除。 1. 下一个会话将加载的文件,智能体程序本身不动,这正是我们刚刚讨论的。 1. 智能体自身的一个新检出版本,保存在归档中。 Hermes 和 Prime 属于(2),Live-SWE 属于(1),DGM 属于(3)。将 1 和 3 混淆,就是 77.4% 和 20 到 50 这两个数字被引用为同一结果的原因。 ## 发明它,然后删除它 Live-SWE 从 mini-SWE 出发,大约一百行,仅用 bash,每次动作都是一个新的 subprocess.run,他们没有改变那个循环。离线智能体编辑脚手架并在基准上评分,一次 DGM 在 SWE-bench 上的运行大约耗资 22,000 美元。他们的赌注恰恰相反——一个能写 Python 的模型,可以在仍处理 issue 的过程中写出一个工具。(https://arxiv.org/abs/2511.13646) (https://github.com/SWE-agent/mini-swe-agent) 每一步之后,一个反思提示会询问是否有新工具能让速度更快。智能体写一个脚本,运行它,可能修改它。他们测量的是反思本身,而不仅仅是这种许可。 他们实际产出的一个工具是 go_analyzer.py,用于 SWE-Bench Pro 中的一个 Navidrome issue。Bash 可以用 grep 处理 Go 文件,但 grep 分不清结构体和注释。这个脚本匹配 Go 语法,能找到结构体、函数、引用和导入。此前最优的基准无法完成那个 issue。(https://github.com/navidrome/navidrome) 左侧仍是 mini-SWE,在观察之后,额外的方块是反思,如果它说"是",就写入 /tmp/go_analyzer.py。下一次采样调用 python /tmp/go_analyzer.py struct handler.go Library,这只是另一条 bash 命令——没有新的工具 API,只是在这个进程内部,磁盘上出现了一个文件。 SWE-bench Verified 随机 50 个样本,Claude 4.5 Sonnet: - 仅 bash:62.0% - 提示中说明可以写工具,但无反思:64.0%,2.92 个工具 - 每步之后进行反思:76.0%,3.28 个工具 提醒才是推动数字变化的原因,然后是完整的 Verified 集,Gemini 3 Pro 在无测试时缩放的情况下达到 77.4%。SWE-Bench Pro 上,Claude 4.5 Sonnet 为 45.8%。不同的基准,不同的模型,77.4% 不是 Pro 的数字。 换用较弱的模型,它就会崩溃。同样的 50 个样本切片,GPT-5-Nano 在 mini-SWE 下得到 44.0%,在 Live-SWE 下跌至 14.0%,轨迹陷入循环,模型根本不明白创建工具是为了什么。 然后他们把它扔掉了,论文里就是这么说的。未来工作是将有用的工具序列化为技能,这一点他们还没有落地,下一个 Navidrome issue 还是从 bash 开始。 一个发明了解析器又把它删掉的更长 issue,比一个新的测试框架更有价值。在一个 60 题的子集上,他们以 65.0% 对 53.3% 击败了 DGM,且没有离线预算。如果你同时引用两篇论文,就把两个数字都用上,不要把它们硬拼在一起。 ## 技能文件 写 SKILL.md 是所有人的建议,包括 Live-SWE 的未来工作:保留程序,把知识存到磁盘上。 SkillsBench 实测了这种人们一直在推荐的做法:让智能体在解题前先编写技能包,然后加载它。18 种测试框架配置,87 个任务。由人工整理的技能可将通过率从 33.9% 提升至 50.5%。通过 Anthropic 技能创建器自动生成的技能包,每次都低于无技能基准:(https://arxiv.org/abs/2602.12670) - Claude Code,Opus 4.7:下降 8.1 - Codex,GPT-5.5:下降 11.3 - Gemini CLI,Gemini 3.1 Pro:下降 11.5 审计结果枯燥却有用:技能包未被使用、编写过程耗尽了解题时间、技能包被使用但内容有误(3d-scan-calc 将某个单位换算列为关键假设,求解器随之照单全收),以及技能包泄露了任务内容。Hermes 可以对写入操作设置门控。但你仍然需要一个评分,让下一个任务有失败的可能。 真正站得住脚的写入方式是:评分之后再提取。CODESKILL 从已经通过的轨迹中提取过程,再由一个管理员进行合并与删减。相较于无技能基准,平均提升 +9.69。仅提取会使知识库增长至 1,252 条,经过维护后削减至 676 条,而收益依然保持。文件结构相同,时序相反。(https://arxiv.org/abs/2605.25430) 先成功,再建库——SkillsBench 展示的正是跳过这个顺序会发生什么。 ## 替换智能体 DGM 是 Live-SWE 所对比的离线写入方式。取 Schmidhuber 的 Gödel 机器,去掉证明部分,在编程基准测试上为重写打分。用他们的话说,一个编程智能体是一个代码仓库加上一个可以读取、写入和执行的冻结模型,而自我改进就是对该仓库执行的一项编程任务。(https://arxiv.org/abs/2505.22954) (https://arxiv.org/abs/cs/0309048) 基础智能体刻意设计得很精简:bash 加上一个可以查看或整体替换文件的编辑工具,与 mini-SWE 的赌注相同。 一代演化分两个部分。父代复制自身并编辑副本,新文件存在了,但尚未成为智能体本身,随后对子代进行评分。如果它仍能编译、仍能编辑,档案中的指针就会移动。在指针移动之前,父代依然有效。 父代的采样大致按得分高低,并与其已拥有的具备编辑能力的子代数量成反比,每个节点都保留非零概率。父代读取自身的评估日志,提出一个特性,并在副本上实现它。 首先用 10 个任务验证它是否仍能编辑,若不能则永不进入档案。接着用 50 个任务测试。若它在 60 题混合集上超过 40% 且排名前两位,则进行 200 题测试,使分数更可靠。 经过 80 次迭代,SWE-bench 从 20.0% 提升至 50.0%,完整 Polyglot 从 14.2% 提升至 30.7%,每次 SWE-bench 运行约花费 22,000 美元。 演化路径经历了更差的父代,即已发布运行中的第 4 次和第 56 次迭代。节点 24 是编辑工具的重写,在该谱系上从 23.3% 提升至 40.5%。取消档案机制则退化为爬山算法。始终扩展当前冠军只能达到 39.7%,而档案机制下是 50.0%。 子代所发明的都是普通的测试框架工作:更精细的查看与编辑、补丁验证、多次尝试加第二个模型排序、失败尝试历史、长上下文管理。真正带来提升的,是测试框架文件本身。 这份档案也是发现作弊的方式。在一次独立运行中,评分标准是"停止幻觉工具调用",有一个子节点剥离了检测器令牌,在没有修复幻觉的情况下获得了满分2.0。血统记录让差异一目了然,因此将该子节点放入沙箱、切断网络、保留检出结果。 没有任何IDE内置了这些,Sakana的报告是一次研究运行,它不是Cursor。(https://sakana.ai/dgm/) ## 记忆实际存在于何处 下一张工单是一个新进程,线程为空,凡是你没有写下来的东西都会消失——这就是为什么记忆存在于本文中,不是作为插件,而是作为规则,规定第二位写作者可以保留什么。 你可以写下三类东西,它们并不可互换。 **智能体的Git**。DGM的档案、提交记录、父指针、评估日志、分数。无法编辑的节点会被丢弃,差于父节点的会被刻意保留——这就是为什么你仍然拥有节点24。这不是一个记忆产品,只是带有账本记录的harness仓库。 **笔记**。SWE-Exp是一个经验库。Experiencer读取成功和失败的修复记录,提取一条简短笔记:问题是如何被理解的、归纳出的策略是什么。下一个问题检索时,重排序器保留一条。Claude 4 Sonnet在Verified上的Pass@1为73.0%。DeepSeek-V3,零条经验时为37.8%,一条时为42.0%,二、三、四条反而更差。经验库在约300条时趋于饱和。将原始轨迹塞回去,你会损失6.0个百分点。(https://arxiv.org/abs/2507.23361) 逐步拆解一条笔记,因为这正是人们将"记忆"扁平化处理的对象。 问题A,lockfile工单,智能体重新生成了pnpm-lock.yaml,CI失败,有人看到这个仓库固定了lockfile。你不存储那400行日志,你存储一句话。两周后的问题B,新进程,检索一次后放入首个提示词,而不是每次bash调用时都检索,一行记录。SWE-Exp已经验证了一条胜过四条。将来自仓库A的pnpm约定仅存储在某个用户ID下,对仓库B来说是毒药,因此作用域是检索的组成部分。 **技能**,在一次通过之后。人工整理有帮助,解题前由智能体撰写往往没有帮助,评分后提取是目前持有数据的写入方式。 能够泛化的辅助工具应作为提交写入harness仓库。你希望第40代看到的失败方案应作为一行记录写入经验库。下一次会话应作为技能加载的流程,必须来自已通过评分的轨迹。自动加载上一个问题的SKILL.md,正是SkillsBench已经评分为负收益的混合方式。 ## Mem0 不要把coding_agent.py放进记忆API里。评分器和档案负责选择子节点。一个试图承担这项工作的存储系统会隐藏你需要的血统信息——当某个子节点剥离检测器时,你就看不到了。 我们拥有的是行记录:user_id、agent_id、run_id。两个共享这些ID并实际执行读写的harness版本,读取的是同一批笔记。第12代的失败方案应当在第40代时被调出。 写入路径在评估之后,你已经选好了那句话。infer=False将其原样存储。默认的add操作会从消息中提取事实,而提取过程会把一条lockfile笔记变成"用户遇到了依赖问题"。不要对同一份数据混用两种方式,否则你会重复存储。 run_id对应这张工单或这一代的评估,评分结束后即告失效。agent_id对应这个harness版本。user_id对应这个人或这个仓库,它会持续存在。 按照你写入的方式进行过滤。在infer=False之后,你可以在一行记录上同时设置两个ID并对其进行AND查询。在默认提取之后,一条事实被归属于某一位发言者,因此对这两个字段进行AND查询会返回空结果(Mem0)。(https://docs.mem0.ai/platform/features/entity-scoped-memory) 读取路径是下一个任务的组装,仅在第一个提示中搜索一次,而非每次 bash 都搜索,一行胜过四行。 - 锁文件说明、失败方法记录、仓库惯例:是 - 生成的工具:否 - 评分前编写的 SKILL.md:否 - 转录记录:否 Dream 平台将仅限于 user_id 范围内的行进行合并。同时含有 user_id 和 agent_id 的注释跳过该步骤。将人工编写的技能保留为文件,将测试框架的 git 保留为 git。 ## ## 参考文献 - Xia 等,Live-SWE-agent (https://arxiv.org/abs/2511.13646) - Zhang 等,Darwin Gödel Machine (https://arxiv.org/abs/2505.22954) - Sakana,The Darwin Gödel Machine (https://sakana.ai/dgm/) - Zhou 等,Self-Evolving Coding Agents (https://arxiv.org/abs/2608.03392) - Chen 等,SWE-Exp (https://arxiv.org/abs/2507.23361) - Li 等,CODESKILL (https://arxiv.org/abs/2605.25430) - Li 等,SkillsBench (https://arxiv.org/abs/2602.12670) - Yang 等,mini-SWE-agent (https://github.com/SWE-agent/mini-swe-agent) - Schmidhuber,Gödel Machines (https://arxiv.org/abs/cs/0309048) - Karten 等,Prime Agent (https://arxiv.org/abs/2608.23552) - Prime Intellect,Prime Agent (https://www.primeintellect.ai/blog/prime-agent) - Pi coding agent (https://github.com/earendil-works/pi) - pi-continual (https://www.npmjs.com/package/pi-continual) - Nous Research,Hermes Agent (https://github.com/NousResearch/hermes-agent) - Anthropic,Agent Skills (https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills) - OpenAI,Codex agent loop (https://openai.com/index/unrolling-the-codex-agent-loop/) - Cursor,Continually improving our agent harness (https://cursor.com/blog/continually-improving-agent-harness) - Cursor,Towards self-driving codebases (https://cursor.com/blog/self-driving-codebases) - Mem0 论文 (https://arxiv.org/abs/2504.19413) - Mem0,entity-scoped memory (https://docs.mem0.ai/platform/features/entity-scoped-memory)