数据STUDIO

Anthropic 首次公开 Claude 内部记忆架构

Image

做过长程 Agent 的朋友,应该多少遇到过这种情况:Agent 昨天刚把一个问题排查清楚,今天开个新会话,又从头查了一遍。

比如让它维护代码仓库。上午它刚弄明白某个接口超时与网关重试有关,下午换个会话,又去调整数据库连接池,把已经排除过的方案重新试了一遍。任务做得越多,这种重复劳动越明显。

很自然地,我们会想给 Agent 加记忆:把历史对话塞回上下文,或者把日志、文档、执行记录存进向量库,需要的时候再检索。问题是,记录越攒越多,临时状态、过期结论和真正有价值的经验容易混在一起。下一次任务想找到那条关键提醒,反倒得翻半天。

Anthropic 最近公开了《The components of agent memory》,分享了 Claude 如何处理长期记忆。这套思路已经应用在 Claude Code 等产品中,包含四层记忆结构,以及一个叫 Dreaming 的离线整理过程。

Image

文章里有不少具体实验,从玩《宝可梦》到数据库问答、代码知识库和法律合同。我觉得最值得聊的是三个问题:哪些经验应该留下、留下来的结论怎样纠错,以及新会话怎么方便地把这些经验用起来。

01哪些不算 Agent 记忆

先弄清楚这里的“记忆”到底指什么。平时我们说模型记住了某件事,其实可能是三个不同的层面。

一个是训练时进入模型参数的知识。模型懂 Python、会写 SQL,主要靠训练获得这些能力。但今天让它修好一个项目的报错,并不会因此当场改写权重。

第二个是当前会话的上下文。你刚告诉 Agent 项目目录在哪里,它接下来几轮能接着用,这属于 in-context learning。换个新会话,通常就不能指望这些信息自动留着。

还有 compaction:上下文快满的时候,先给当前任务做一份摘要,让接下来的操作有地方接续。这个功能很实用,但主要是为了把正在做的事继续推进。

Anthropic 这里说的长期记忆范围更具体:Agent 从真实任务中总结出知识和规则,跨会话保存,之后还能主动读取。

举个例子,Agent 昨天跑测试得到几千行报错日志,这些属于原始记录。如果它从多次验证中总结出“这个项目的测试必须先设置某个环境变量”,下次遇到同类问题还能找到这条经验,才更接近长期记忆的用途。

把这几层分开看,后面的架构就好理解了:原始记录可以保留,上下文可以压缩,但真正要沉淀的经验还需要筛选、组织和验证。

02记全为什么会拖垮 Agent

我们很容易觉得,记忆当然是越详细越好,反正多记一点总没坏处。Anthropic 让 Claude 玩《宝可梦 红版》的实验,恰好能说明这种想法的代价。

在这个长程任务里,早期模型 Sonnet 3.7 采取了事无巨细的记录方式。每遇到一场战斗、捡到一个道具、和 NPC 说一句话,它都可能单独建一个文件。游戏推进到大约 10,000 步时,它已经写下 413 个文件,分散在 225 个文件夹里,合计 977,930 个字符,最终只拿到 1 枚徽章。

更成熟的 Fable 5 只保留了 10 个文件,放在 2 个文件夹里,加上一个 global.md,合计 43,406 个字符,拿到了 4 枚徽章。


Image

图:Anthropic Treemap实验中的记忆目录面积对比。Sonnet 3.7 事无巨细的记录拖慢了行动,Fable 5 用 10 个文件拿到 4 枚徽章。

差距还体现在实际行动上。大约第 10,000 步时,Sonnet 3.7 又开始建第 4 个主记忆目录。接下来连续 17 步,它创建了 6 个文件、删除了 9 个文件,游戏却没有取得有效进展。

有点像我们在开发 Agent 时碰到的情况:任务还没做多少,工具调用已经花了大半时间整理历史笔记。

因为记忆本身也要花成本。写入、检索、维护都需要操作,读进上下文还会占 token。游戏里的坐标、道具数量这些信息变化又快,旧记录很容易失效。等下次需要时,Agent 还得判断究竟哪一条是最新的。

所以问题不在于文件越少越好。关键是留下来的信息,能不能真正减少下一次任务的探索成本。

03该记什么:易变事实和隐性规则

哪些内容值得留?Anthropic 提出了一个很好用的区分:易变事实和隐性规则。

易变事实指当前的状态,比如 NPC 现在站在哪里、背包还剩几个伤药、网页此刻的 DOM 长什么样。这些东西通常可以重新查询,而且变化很快。从昨天的记忆里查一个坐标,不一定比现在看一眼地图更靠谱。

隐性规则是另一类信息。比如“出了这个洞穴,右侧台阶跳下去就回不了头”“某个 API 并发调用前需要先拿锁”“这类测试错误经常和缺少环境变量有关”。它们往往要经过几次尝试和验证才能总结出来。

放到代码 Agent 里也一样。“服务现在运行在 8080 端口”可以现场确认;“这个服务每次部署前都要执行一次数据库迁移,否则健康检查会失败”,如果已经验证过,就很值得告诉下一次接手任务的 Agent。

当然,规则也可能过期。把它记下来只是第一步,后面还得有办法核对它是否仍然成立。

那是不是给 Agent 写一套非常严格的记忆规则,就能让它越用越好?Anthropic 还专门在 CL-Bench 1.0 的数据库任务里测试了这种思路。

实验中每次答题都会开启新会话。模型可以读取此前保留的记忆目录;如果答错了,可以记录失败、提出解释、再验证解释,最后把有用的经验留给下一次。

模型
无记忆
有记忆
Opus 5.5
0.655
0.838
Sonnet 5.5
0.644
0.833
Opus 5
0.564
0.828
Opus 4.7
0.383
0.700
Sonnet 5
0.306
0.610
Sonnet 4.6
0.330
0.364

Image
图:Anthropic 公布的 CL-Bench 1.0 结果。不同模型都能从跨会话记忆中获益,但形成完整学习循环的能力不同。

从结果看,记忆确实有帮助。不过,把规则定得太死,也可能影响模型发挥。

研究团队试着要求模型“只记录失败经验”,结果 Opus 5 的记忆收益减少了 0.234,Opus 4.7 减少了 0.150,Sonnet 4.6 减少了 0.020。

想想也合理。假设 Agent 已经找到了一套稳定的 API 调用顺序,或者验证过一条正确的 SQL 查询方式,这些成功经验对后面的任务同样有用。如果只准记录失败,它就可能把这些经验漏掉。


Image
图:限制性提示对强模型是负向约束,方向性提示更能帮到弱模型。

但如果模型能力还不够强,适当的提醒确实有效。Sonnet 4.6 无记忆时得分 0.330,有记忆后是 0.364;明确提示它“答题前先读记忆、验证猜想”后,分数升到 0.641。而 Sonnet 5 在 10 次里有 9 次会主动先读记忆。

这对实际开发挺有参考价值。能力较强的模型,可以先告诉它记忆有什么用,再让它判断该留哪些经验;能力较弱的模型,则可能需要把“先读取记忆、再核对猜想”这样的步骤写得更明确。

所以比起一上来写几十条“禁止记录什么、必须记录什么”,我更倾向于先把记忆的存储、检索和纠错机制做好,再根据模型实际表现补充提示。

04四层记忆:从原始流水到开局注入

看完这些实验,再来看 Anthropic 怎么组织记忆,就比较容易理解了。它把内容分成四层,从底层的原始执行记录一路整理到新会话启动时使用的简短索引。

层级
内容
作用
第 1 层
Transcripts:完整对话、工具调用参数、执行结果、环境反馈
唯一无损的原始底账,可搜索
第 2 层
Memory notes:会话中主动写下的显著观察
记录单次任务的局部经验
第 3 层
Memory representations:Wiki 等结构化、互链的知识表示
把碎片笔记归纳成知识地图
第 4 层
Injected context:新会话自动加载的少量内容
充当目录索引,不是资料仓库

Image
图:从底层的原始执行流水,逐层提炼为笔记、Wiki 和顶层注入索引。

可以把它想成一个代码 Agent 的经验库。

第 1 层保留一次真实排障的完整过程:看过什么文件、执行过哪些命令、报错日志具体是什么。第 2 层是 Agent 当时写下的观察,比如“问题似乎和网关配置有关”,这时还只是候选结论。

第 3 层把多次任务验证过的内容组织起来:哪个模块依赖哪个服务、常见报错怎么定位、哪些操作顺序需要注意。条目之间还可以互相链接。第 4 层则像一份很短的目录,只告诉新会话这些知识分别存在哪里。

这样新会话就不用每次从全部历史日志里重新翻起,需要查某个模块时再打开对应资料。同时,原始记录还留着,万一上层结论有问题,也有地方回查。

新经验可能写入笔记,旧经验可能被合并到 Wiki;如果后来发现规则失效了,就需要修订或者清理。长期记忆要能维护,光让文件越来越多还不够。

05一条错误笔记,怎么让之后每个会话都走错

记忆还有个麻烦的地方:写下来的经验也可能是错的。

Agent 正忙着处理当前任务时,往往只能根据手头信息做判断。它当场记下的某条结论,可能只是未经验证的猜想。偏偏下一次会话看到这份笔记时,很容易把它当成已经确认的事实。

宝可梦的月见山任务里,Claude 在笔记中错误地写下“宝可梦中心在山洞东侧”。走出洞口后,它依据这条笔记认定月见山已经走完,跳下了一个单向台阶,直接摔回原点。更麻烦的是,导航工具感知不到高低落差,Claude 还一度在笔记里加倍确认自己走对了。后续每个进入游戏的新会话,都无条件相信前人留下的记录,连续 3 次跌回同一条路线,最后写下“我宁愿停下来,也不想继续循环”,退回深灰市。


Image
图:未修正的错误笔记让 Claude 在同一个台阶反复跌落。

这个故事有点像代码 Agent 的错误排障经验被反复继承:第一次误判“所有超时都要先调大数据库连接池”,后面几个会话就照着改,结果真正的网关问题一直没人查。错误一旦写进长期记忆,还会被包装成看起来很可靠的“历史经验”。

Anthropic 的 Dreaming 就是为这种情况提供一个事后检查环节。它在离线阶段回到第 1 层原始流水,拿真实的工具反馈去对照上层笔记。

月见山的例子里,笔记说宝可梦中心在东侧,但原始记录显示角色向东走出大门后坠落、路线重置。两边对上以后,原来的笔记被修正为:穿过月见山后不要向右跳下台阶,必须返回洞内向北走。


Image
Dreaming 在离线阶段对照原始执行记录,修正上层笔记图:Dreaming 调取底层原始流水,逐条比对并重写错误笔记。

修正之后,使用新笔记的运行在第 1,935 个累计动作抵达华蓝市。保留原始错误笔记的对照组和无记忆组,都没有越过月见山。


Image
图:修正组顺利穿越月见山抵达华蓝市,未修正组在悬崖处迷航折返。

我觉得这部分很值得做 Agent 工程的人注意:我们经常检查 Agent 这次答得对不对,却不一定检查它准备留给下次会话的结论。

长期记忆需要能回查原始依据,也需要允许纠错。 只有底层记录保留得足够完整,上层笔记出现争议时才有机会重新核对。当然,Dreaming 是离线运行的,整理需要额外算力,修正后的内容也无法立刻帮助正在进行的会话。

06从文件堆到 Wiki:收益和边界

除了纠错,Dreaming 还会把散落在不同地方的笔记组织成 Wiki。

这件事对大型代码仓库尤其有用。第一次接手几十万个文件时,全文搜索当然能帮你找到代码,但如果有一份模块地图,告诉你认证逻辑、数据库访问层和主要调用链分别在哪里,很多问题就能少绕弯路。

Anthropic 也做了这样的实验。他们使用内部代码语料 Stainless,规模约 35 万个文件、4.2 亿 token,评测包含 25 道题。

他们让 Opus 5 在 128 个会话里持续撰写、合并、修剪并互链 Wiki 页面。随着整理轮次增加,只用 Wiki 的得分从 13% 提升到 48%;Wiki 加搜索从 54% 提升到 61%,而单独搜索停在 53%。同时,Wiki 加搜索平均每个问题少消耗约 20,000 个 token。Wiki 本身也从 103 个页面、766 条链接,长到 222 个页面、12,893 条链接。


Image
图:Wiki 从零散页面长成知识网络,Wiki 加搜索的评测结果最好。

可以把 Wiki 理解为一张知识地图。搜索负责找到具体材料,Wiki 则提前整理出模块、概念和文档之间的关系。碰到跨文件、跨系统的问题,有了这张地图,Agent 会更容易知道先去哪里查。

但也没必要给所有任务都建一套很重的 Wiki。Anthropic 在 Harvey LAB 的任务里发现,答案需要跨多份文档组合时,Wiki 得分 87%,单独搜索是 73%;答案集中在一份文档里时,Wiki 的优势就不明显了。

还有一次,Wiki 最后增长到 203 KB,原始语料却只有 115 KB,体积达到原文的 1.77 倍。整理出来的知识比原始资料还长,检索和维护的成本就得重新算。

所以我觉得可以先看实际任务:大家缺的是一份跨资料的导航图,还是一个能准确找到原文的搜索入口?对于简单问题,后者可能已经够用了;需要频繁组合多份材料时,前者才更值得投入。

07生产环境:顶层做目录,底层做仓库

这些层级真正落到产品里是什么样?Claude Code 的 auto memory 就是一个比较具体的参考。

按文中介绍,新会话启动时,它不会把 MEMORY.md 全部塞进上下文,只读取前 200 行或 25 KB。开局加载的内容尽量简短,主要告诉 Agent:已经整理过哪些知识,详细内容应该去哪里找。

假设一个仓库有十几个模块,这份索引可以指向项目约定、测试注意事项和各模块的排障笔记。Agent 这次负责支付模块,就按索引读取支付相关的内容;下次处理构建脚本,再去查构建部分。


Image
图:顶层注入轻量索引,底层知识按需读取或搜索。

这么做主要是为了省上下文。每次启动都加载一大堆历史记录,模型会花很多注意力处理和本次任务无关的内容。更麻烦的是,如果开局索引里混入一条错误规则,它可能在之后每次会话中持续产生影响。顶层负责指路,细节留在下层按需读取。

多 Agent 协作里还有另一个容易踩的坑:几个 Agent 同时修改同一份共享记忆。

Harvey LAB 的法律合同任务就遇到了这种情况。多个 Agent 一开始共同维护一张条款表,内容互相覆盖,57 项关键事实最后只留下 41 项,完成度 72%。

后来团队调整了工作方式:每份合同由一个 Agent 独立建页,条款逐字保留,再处理不同文档之间的关系。这样改完,57 项事实全部保留,简报评测的满足率达到 100%。

这种问题放到代码 Agent 里也不难想象。几个 Agent 分别分析接口、数据库和测试日志,如果直接争抢一份共享总结,很容易把别人的观察覆盖掉。先按来源独立记录,再汇总和建立关联,出了问题也更方便追溯。


Image
图:从共享表格改为每份合同独立建页,关键事实保留率从 72% 提升到 100%。

第二轮 Dreaming 还修复了 9 个指向不存在页面的链接,新增 3 个页面,Wiki 从 38 个条目、225 条链接变成 41 个条目、278 条链接。

这些工作看着琐碎,却很重要。长期记忆除了写下经验,还得修坏链接、处理重复内容、保留来源、避免多人写入冲突。否则等 Agent 真要调用这些知识时,可能连正确的页面都找不到。

08落地前必须权衡的三件事

如果准备借鉴这套架构做自己的 Agent,我建议先聊清楚三件事,第一版没必要一下把四层都做满。

第一,哪些内容需要当场记,哪些可以等离线整理? 比如一次部署刚失败,Agent 还记得具体的命令和错误信息,可以先留一条观察并附上来源。等任务结束后,再检查这次现象和之前的记录是否一致,决定要不要整理成长期规则。

在线记录及时,但会占用当前会话的工具调用和上下文。离线 Dreaming 可以集中做合并、检查和纠错,需要额外算力,结果也没法立刻用于正在运行的任务。具体怎么分工,要看任务时长以及错误经验会不会马上影响下一步。

第二,哪些记忆容易过期? 比如某个 API 过去要求先调用鉴权接口,后来 SDK 把鉴权封装进去了。旧笔记如果还在指导 Agent,后续任务就可能重复调用。

所以记忆最好能标明来源和适用条件,变化频繁的内容优先复查。全部记录每次都重新验证,成本太高;可以先从最近常用、容易变化、证据不充分的内容开始。

第三,真的需要一整套 Wiki 吗? 如果项目只有几份重要文档,一个简短 Markdown 索引配合搜索,可能已经够用。遇到几十万文件、多个模块、需要跨会话反复组合知识的任务,再考虑逐步建设 Wiki。

Anthropic 的思路也给出了这样的折中:顶层放轻量索引,底层保留可搜索的详细材料。真正值得衡量的是,记忆帮 Agent 省下了多少重复探索,又增加了多少写入、查询和维护开销。

09写在最后

看完这些实验,有三点我觉得特别适合从小项目开始试。

保留可以回查的原始记录。 笔记、摘要和 Wiki 都可能出现误判。有了执行日志和工具反馈,后面发现结论有冲突,才知道当时到底发生了什么。

开局给目录,细节按需读取。 把真正需要在新会话开始时知道的内容放在顶层。模块细节、历史故障和复杂规则留在下层,需要时再找,避免每次把全部历史塞进上下文。

让模型判断经验价值,也给它核对和改正的机会。 强模型可以少一些死板的记忆模板;能力不足时再补充明确的读取、验证步骤。无论采用哪种方式,记忆都要允许修订和撤回。

比如做第一版代码 Agent,可以先保留执行流水、给关键任务写短笔记,再维护一份简洁索引。等真实使用中发现重复踩坑、旧经验传播错误或检索成本持续上涨,再逐步引入定期整理和结构化 Wiki。

这样做的目的很简单:下一次任务遇到相似问题时,Agent 能少走弯路;如果过去的经验有误,它也能找到依据及时纠正。

Image