开篇:你的AI编程助手为什么总在"重新入职"?
上周我在做一个项目,AI编程助手帮我修了一个挺隐蔽的Bug——某个订单状态的枚举值在不同Java版本间映射逻辑不一致,导致线上偶发写入失败。修完、测试通过、发布,一切顺利。
三天后,同一个模块又出了一个类似的问题。同一个Agent,同一个仓库,它从零开始重新探索目录结构、重新理解业务概念、重新犯了一遍前面已经踩过的坑。
我突然意识到:它就像一个每天早上醒来就失忆的工程师——技术能力还在,但关于这个项目的所有经验,全部清零。
这不是AI模型不够聪明,而是它缺少一个关键能力:Memory。
但注意,这里说的Memory,不是你直觉里那个"把聊天记录存下来"的东西。真正的Agentic Coding Memory,是一个远比"长上下文"和"代码索引"复杂得多的系统工程。
最近我读了一份关于Agentic Coding领域Memory与Dreaming技术的深度报告,覆盖了12篇核心论文、8个开源项目和GitHub Copilot/Claude/Codex三家的工业实践。看完之后,我对"AI编程应该怎么做记忆"这件事,有了完全不一样的理解。
一、Memory不是你以为的那个东西
大部分人理解的Memory,就是"把对话历史存下来,下次接着聊"。
这是个误解。
对一个Coding Agent来说,真正有用的信息至少分布在四个维度上,而它们的长相、生命周期和应用方式完全不同:
你看代码→结构记忆:函数在哪里、调用链怎么走、依赖关系是什么。这些是可以从源码"确定性重建"的事实。Tree-sitter、LSP、Git diff可以搞定。
你改过什么→情景记忆:上次那个订单状态Bug具体改了哪三个文件、Review时被指出什么问题、QA发现了什么缺陷、最终修复方案是什么。这是一次具体工程事件的"问题→行动→结果"全记录。
你知道为什么→领域记忆:为什么订单状态不能用enum ordinal直接写入数据库?因为有一段历史遗留的legacy映射逻辑。为什么修改支付模块时必须同步更新库存状态?因为业务不变量要求"支付成功→库存扣减→履约创建"的原子性。这些知识,代码里写不出来。
你知道怎么做→程序性记忆:这类Bug怎么复现?改这个模块之前应该先跑哪些测试?发布前必须检查哪几个配置项?这些是"如何做"的可复用流程。
这里有一个关键矛盾:结构记忆可以用代码索引解决,但后三种记忆——情景、领域、程序——才是决定Agent能不能"越用越聪明"的核心。而它们恰恰是当前所有Coding Agent最缺失的东西。
GitHub Copilot的工程团队分享过一个很有意思的观点:记忆必须有"证据链"。每条领域知识或历史经验,都必须能追溯到具体的代码commit、Issue、测试结果或PR Review——如果没有,它就可能是不准确的、过时的、甚至是幻觉。而且检索到记忆后,不是直接相信,而是先对比当前代码版本验证是否仍然成立。
这才是工业级的工程思维。
二、六层记忆,缺一不可
报告把Agent Memory按内容和用途划分为六类。这六层如果缺了任何一层,Agent就会在某个场景下表现失常。
第一层:工作记忆。这不是"长期"记忆,而是当前任务的执行状态——任务目标、当前假设、已检查的文件、最近的测试结果。它应该被视为"可恢复的执行快照",而不仅仅是聊天摘要。长任务压缩时,应该生成结构化的checkpoint,而不是自由文本总结。
第二层:结构记忆。符号表、调用图、依赖关系、模块所有权。这是最容易建立的一层,codebase-memory-mcp这类工具就是干这个的。但它只回答"代码是什么",不回答"为什么这样设计"。
第三层:情景记忆。最有价值的一层。记录一次工程事件的完整生命周期:Issue描述、Agent的探索路径、最终patch、测试结果、Review意见、QA缺陷。特别重要的是——记录哪些尝试失败了,以及失败的具体证据。
论文里有一个反直觉的发现:不是所有失败经验都值得记录。"以后要更仔细地测试"这种泛化提醒,不仅没用,还可能产生负收益。真正有价值的是具体的、可操作的失败事实,比如"该仓库的集成测试必须通过./gradlew integTest启动,直接运行JUnit会缺少Testcontainers环境"。
第四层:领域记忆。业务术语、实体关系、状态机、架构决策及其原因。"修改订单模块时必须同步检查履约状态"——这行字代码里没有,但不知道就会出Bug。这层不能只从源码生成,必须融合PR、Issue、设计文档、Review和线上反馈。
第五层:程序性记忆。"改这个模块之前应该先跑哪些测试"、"这类需求的标准检查清单"、"定位这类Bug的固定流程"。经过多次验证后,程序性记忆可以晋升为Superpowers风格的Skill——也就是说,Memory是候选经验池,Skill是经过验证的正式资产。
第六层:偏好与组织记忆。个人编码偏好、团队约定、Owner和权限边界。必须严格按user/team/repository/branch的作用域隔离,避免跨项目泄露。
这个分类体系的价值在于,它给了一个清晰的工程地图:哪一层用什么工具建、什么信息该进哪一层、哪一层容易做哪一层需要长期打磨。不会一上来就想"做个大而全的向量数据库",然后发现根本用不起来。
三、Dreaming:让AI"做梦"的秘密武器
如果说六层记忆是"记录什么",那Dreaming就是"如何把记录变成能力"。
报告对Dreaming的定义很精准:
在不执行用户当前任务的后台阶段,对多次会话、任务轨迹和已有记忆进行跨时间尺度的重组,生成更紧凑、更一致、更可迁移的记忆。
换句话说,在线记忆写入是"快系统"——任务进行中快速捕获事实和经验;Dreaming是"慢系统"——获得跨会话的全局视角后,再去重、纠错、归纳和晋升。
Anthropic的Claude Managed Agents已经把Dreaming产品化了:它接受1到100个历史session,异步生成一个新的记忆存储。它会合并重复内容、替换过时或冲突项、挖掘新的关联,同时不修改输入存储,方便人工审阅或直接丢弃。
Dreaming具体应该完成八件事:
去重:合并语义重复但表述不同的记忆。比如"订单状态用legacy映射"可能被记录了五次。 冲突解决:识别矛盾记忆,根据时间、分支和证据决定是替换、分条件保存还是标记未知。 抽象:从"订单模块Bug A用了fix X"、"订单模块Bug B用了fix Y"、"订单模块Bug C用了fix Z"中,归纳出"订单模块的DB映射有一个legacy逻辑,所有字段都受其影响"。 特殊化:发现一条规则其实只适用于特定模块、版本或任务阶段,补充适用条件。 压缩:把原始长轨迹(几万token)转成短的证据化结论(几百token)。 关联:建立业务概念、代码符号、Issue、测试和失败模式之间的关系。 遗忘:降低长期未使用或已失效记忆的优先级。注意,遗忘不是删除——原始证据永远保留,但从活跃记忆中移除。 晋升:将多次成功验证的程序性经验提升为规则或Skill候选。
论文Auto-Dreamer的实验数据特别有意思:高质量的consolidation可以同时提升任务成功率并大幅缩小记忆体积。在WebArena上,Auto-Dreamer的活跃记忆只有927个token,就取得了最高成功率和AUC;而对比方法UMEM的记忆高达80.9K token——差了87倍,效果还不如。
这告诉我们:Dreaming的真正价值不是"生成更多记忆",而是"让每一token的记忆都值得被读取"。
四、五层架构:从想法到落地
报告的推荐架构分为五层,每一层都有明确的职责:
Layer 1:事件与证据存储。这是地基。所有原始数据——session日志、Git diff、测试结果、PR Review、QA缺陷——以append-only的JSONL/SQLite存储。原始证据永不可被Dream覆盖。这是防止记忆被污染的最后防线。
Layer 2:确定性仓库模型。由代码索引、Git和构建系统生成的结构化图谱。codebase-memory-mcp覆盖这一层的符号和调用图部分。它的特点是"可确定性重建"——你随时可以从源码重新生成,不需要信任任何LLM的输出。
Layer 3:类型化记忆银行。这是核心。每条记忆至少携带:类型(情景/领域/程序/失败)、作用域(repo/branch/module/任务阶段)、摘要、适用条件、证据链(代码引用+Issue+测试+事故号)、置信度、最近验证时间和commit、以及过去被检索后的有用率统计。没有证据链的记忆,不能进入这一层。
Layer 4:记忆路由器。检索不是简单的"语义相似度排序"。正确的流程是:先按repo/branch/module/任务阶段硬过滤→多路检索(BM25+embedding+图谱邻域)→按任务相关性、证据质量、时效和历史有用率重新排序→即时验证citation是否在当前代码仍成立→按token预算生成记忆包。
Layer 5:Dreamer与晋升管道。Dreamer不直接修改输入bank,而是生成候选输出版本。通过自动校验和人工审查后,才能进入活跃记忆或Skill库。这条路线的本质是安全地让AI从经验中学习,而不被错误经验污染。
这里有个反直觉的设计决策值得特别说:写入门槛要高,检索精度要高,但不用一上来就做复杂图数据库。
报告推荐的MVP技术栈出奇的朴素:JSONL做原始事件、SQLite做类型化元数据、pgvector做向量索引、codebase-memory-mcp做结构图谱。没有Neo4j,没有大规模知识图谱,没有RL训练。
因为第一版最重要的是跑通闭环——从记录到检索到验证到Dream到回馈——而不是把技术栈搞得复杂无比。
五、给你最重要的三条建议
看完报告,我觉得有三条原则可以立刻用在你当前的Agent开发中:
第一条:不是所有"经验"都值得记。
报告反复强调一个观点:泛化的、不可操作的"教训"不仅没用,还可能有害。"以后要更仔细"——这是废话。"这个仓库的集成测试必须用./gradlew integTest,JUnit直接跑会缺Testcontainers"——这是黄金。
给你一个简单的写入门槛:这条信息未来很可能影响代码正确性、无法从当前源码轻易推断、已在PR/QA/事故中得到验证——三个条件满足至少一个,才值得写进长期记忆。
第二条:使用前验证,而不是盲目信任。
GitHub Copilot的做法值得直接学习:每条记忆都附带代码citation(具体文件、行号、commit),检索到记忆后,先读取对应位置的当前代码——如果代码反驳了记忆,就生成修正版,而不是继续使用旧内容。
记忆不是真理,它是"在那个时间点、那个版本上成立的一种判断"。代码变了,判断就可能失效。"能用"比"记得多"重要一百倍。
第三条:让Memory闭环,而不是单向流水线。
很多团队做个"存→查"就停下来了。真正的Memory系统必须闭环:任务结束后提取经验→citation化存储→下次任务按阶段检索→使用前验证→PR/QA结果回写→Dream去重归纳→晋升为Skill。每一轮的失败都变成下一轮的输入,Agent才会越用越聪明。
总结
这份报告让我最受触动的一句话是它的核心定义:
Memory 负责"留下什么",Retrieval 负责"什么时候想起",Verification 负责"现在还能不能信",Dreaming 负责"如何把经历变成能力"。
AI编程的下一阶段,不再是比谁的上下文更长、谁的模型更大、谁的工具更多。而是比谁的Agent能像一个真正的工程师一样——在项目中积累经验,在失败中学习教训,在重复中形成直觉。
Memory + Dreaming,就是让Agent从"一次性工具"变成"成长性伙伴"的关键。
你的Agent现在有Memory吗?它能在下次任务中回忆起上次的经验吗?如果答案是否定的,也许现在是时候认真考虑这件事了。
夜雨聆风