一套用 Markdown 文件、四类划分与「做梦式」整理流程,把无状态模型变成可跨会话积累的协作者的工程范例。引言:记忆为何是智能体的分水岭能力大模型本身是无状态的。每开一次会话,上下文窗口都是一张白纸;会话一结束,窗口里的一切随之清空,下一次对话从零开始。对一次性的问答,这没什么代价,使用者重新交代一遍背景即可。可一旦智能体要在数天、数周的跨度里反复服务同一个人、同一个项目,这种健忘就成了价值的天花板——它无法积累,也无法从过去学到任何东西,每次都得重新认识自己的工作对象。业界一个被反复验证的判断是:有没有记忆所带来的能力差距,往往比更换一个更强的底座模型还要大。记忆把无状态的模型调教成能够跨会话积累的协作者:它记得使用者的角色与偏好,也记得项目里定过的决策和踩过的坑,因而越用越顺手。更大的上下文窗口替代不了这件事——窗口只解决单次会话内的连贯,而且 token 越多,成本与延迟越高;真正的跨会话智能,要靠把关键认知留在窗口之外的持久层里。对企业而言,这一层的意义更直接。客服智能体记不住客户的历史工单、研发智能体记不住团队既定的规范,带来的就不止是体验问题,更是落地的根本障碍。记忆因此成了智能体的护城河:它把每一次交互都变成可复用的组织知识。但记忆同时也提出了治理上的新课题——隐私、数据隔离、合规,以及「该忘记什么」的机制,都要在设计之初就考虑进去。Claude Code 的记忆机制,正是把这套理念落到生产环境的一个完整范例。它用最朴素的 Markdown 文件、清晰的四类划分,以及一套模仿人脑睡眠的整理流程,回答了「什么该记、何时取出、如何不腐烂、如何隔离」这几个核心问题。下文逐层拆解。01 根本原则:只记上下文无法派生的认知记忆系统的入口处有一道筛子:一条信息是否「无法从当前上下文派生」。凡是能通过读代码、看文件、调工具重新得到的事实,都不该写进记忆。这类信息随时可重建,写下来只会占用预算,还要承担过期的风险。值得留存的,是丢失之后需要人重新告知、或者要跨多次会话才能积累起来的认知。落到 Claude Code 上,跨会话的知识由两套机制共同承载。一套是 CLAUDE.md——使用者亲手写下的长期指令,记录项目约定、构建命令、固定规范这类「每次都要重申」的内容;另一套是 Auto Memory(自动记忆)——模型根据使用者的纠正与偏好,自己判断哪些值得留下并写入。两者都在会话开始时载入,被当作上下文提示而非强制规则来对待。一个克制而关键的设计:系统提示明确要求模型把自己的记忆当成线索而非事实,落到具体动作前会先去核对真实代码。这种「记忆只是提示」的姿态,显著降低了凭记忆产生幻觉的概率,也正在被其他智能体框架借鉴。02 四类记忆:语义分型而非时间堆叠Auto Memory 把留存的认知归入四类,每一类都对应一种「上下文里拿不到、又值得跨会话保留」的信息。归类的依据是语义主题,而非发生的先后顺序。User —— 角色与背景记录使用者是谁:担任的角色、专业领域、沟通偏好、长期的工作背景。这类信息变化慢、复用率高,几乎每次会话都用得上,因此通常进入静态加载的部分,常驻上下文。它的作用域限定为私有。Feedback —— 纠错与确认这一类有个容易被忽略的细节:如果只记录「做错了什么」,记忆会逐渐退化成一张避雷清单,模型读着读着就变得畏手畏脚,越来越保守。所以除了纠错,还要把「被确认可行的用法」一并记下来。纠错划出边界,确认给出可以放心复用的范式,两者缺一不可。Project —— 进行中的目标保存当前推进的目标、deadline、过程里出现的 incidents 以及定下的决策。这里有一条硬规则:所有相对日期都要转成绝对日期。「下周三」在写下的当天清晰,三周后再读就失去了锚点;落成 2026-06-24 这样的形式,记忆才能在任意时刻被正确解读。Project 记忆天然带有时效,过期之后的处理方式见维护一节。Reference —— 外部系统信息存放外部系统里相对固定的坐标——Grafana 的看板 URL、Linear 里的项目标识之类。它们几乎不变,作用是查表,省去每次重新寻址的成本。四类记忆各自落在独立的 Markdown 文件里,文件顶部用 frontmatter 标注 name、description、type 三项。其中 description 尤其关键,它是后续动态召回时用来做相关性匹配的依据。03 存储结构:索引层与主题文件整个记忆库存在磁盘上,路径是 ~/.claude/projects/project/memory/。每个项目一个独立目录,目录里散落着一个个主题文件,以及一个统领全局的索引文件 MEMORY.md。MEMORY.md:只放指针的索引MEMORY.md 是整个记忆库的索引,本身不存放记忆正文。每行一条指针,形如 - [标题](file.md) — 一句话提要,单行控制在约 150 字符以内,文件不带 frontmatter。它的职责是「这里有哪些记忆、各自指向哪个文件」,真正的内容留在被指向的主题文件中。两条硬上限:200 行 / 25 KB。会话启动时只有 MEMORY.md 的前 200 行会被载入系统提示,超出部分被静默截断——系统只在文件里附了一句很难被注意到的警告。失效是无声的:索引一旦涨到第 201 行,最旧的条目就从底部掉出,模型在新会话里看到的是一份干净的系统提示,根本不知道自己「忘了」什么。这条上限,正是索引必须保持精简的根本原因。Topic file:三层结构每个主题文件由三层构成:name(名字)、description(描述)、type(归属的记忆类型)。description 写得准不准,直接决定这条记忆能不能在该出现的时候被取回。这也是为什么系统反复强调:写入前先检查已有文件,能更新就别新建,避免制造近似重复。04 读取与写入机制读和写由三个函数分担,各自的时机与范围如下。函数触发时机取回 / 写入范围loadMemoryPrompt()会话启动MEMORY.md 前 200 行,整段注入 system prompt,始终在场findRelevantMemories()处理当前问题时按相关性最多取回 5 个主题文件extractMemories()回复收尾、且无工具调用时子代理在后台写入记忆目录静态加载 loadMemoryPrompt()启动时把 MEMORY.md 的前 200 行注入 system prompt。这部分记忆始终在场、无需触发,适合放 User 这类高频复用的信息。动态召回 findRelevantMemories()根据当前问题的相关性,从主题文件里最多挑 5 个取回。上限卡在 5,是为了在「带回足够背景」和「不淹没上下文」之间留出余地。需要留意的是,这套召回靠关键词匹配,并不使用向量嵌入——若提问说的是「端口冲突」,而记忆里写的是「docker-compose 映射」,字面对不上就可能召回不到。措辞因此会实打实地影响命中率。后台提取 extractMemories()写入由一个子代理在后台完成。触发条件是:模型已经产出最终回复、并且这一轮没有任何工具调用——也就是对话自然收尾、进入闲谈状态的时刻。如果主代理在这一轮里已经写过记忆,子代理就直接跳过,避免重复落盘。子代理以完整 fork 的方式启动,共享主代理的 prompt cache,拉起来几乎是零成本。这一点很重要:正因为启动便宜,才敢在每个合适的回合都顺手做一次提取,不必担心开销。它运行在严格约束之下:回合预算有限,只能读写记忆目录、不允许 rm,并且只准依据最近若干条消息来更新,不得再去翻源码或跑 git 旁证。05 维护机制:Auto Dream(做梦)读和写解决的是单次会话内的进出,维护解决的是存量记忆随时间的腐烂。Anthropic 给这套流程起了个贴切的名字:Dream(做梦),自动运行的版本叫 Auto Dream。比喻取自人脑——白天用 Auto Memory 记下零碎的短期笔记,睡眠时再由「做梦」把它们复盘、强化、丢弃、重新归档为长期记忆。之所以需要它,是因为连续用上二三十次会话后,笔记会开始发霉:相互矛盾的条目堆积、相对日期失效、引用的文件已被删除、同一件事被三处重复记录。本该帮模型记住的笔记本,反而成了干扰它的噪声。触发与边界做梦由两个条件共同决定何时运行:距上次整理至少过去 24 小时,且期间有足够的会话活动;也可以用 /dream 命令手动触发。这项能力目前由服务端特性开关控制,以研究预览的形式向有开发者权限的用户分批放开。运行时它守着几条硬边界:只动记忆目录里的文件,绝不碰源码或配置;在后台独立进程里跑,不阻塞正在进行的会话;并且靠一把文件锁保证同一项目同一时刻只有一个「做梦者」——这正是分布式锁要解决的问题。四个阶段Orient 定向先 ls 一遍记忆目录,读 MEMORY.md 摸清现有索引,再略读各主题文件,顺带找出孤儿文件——那些实际存在、却没被索引登记的条目。目的是先建立一张全局地图,再动手。Gather 采集到会话记录(JSONL 文件)里捞新信号,用窄关键词检索而非通读全文,重点找使用者的纠正、反复出现的主题、以及重要决策。Consolidate 整合核心维护发生在这里:把重合的条目合并,相对日期改写为绝对日期,删除已被推翻的事实,清掉引用失效的陈旧条目。对已经过期的 Project 记忆,做法是降级保留——标记为历史,而非直接删除。过去发生过什么仍是有用的认知。Prune 剪枝最后重写 MEMORY.md,把总行数压回 200 行以内:移除指向已不存在文件的指针,把过于冗长的条目降格——索引里只留提要,细节挪进主题文件。这套设计有学理支撑:它呼应了 UC Berkeley 与 Letta 在 2025 年的「睡眠时计算」?Sleep-time Compute, arXiv:2504.13171?思路——用空闲算力提前整理,换取下一次会话的效率。实测中,曾有案例在 9 分钟内整合了 913 个会话的记忆,另有项目的索引从 280 行收敛到 142 行。需要提醒的是,做梦的剪枝相当激进:首次运行前最好备份记忆目录,并把不可丢失的关键决策显式标注,以免被误删。06 团队记忆与目录隔离记忆的作用域分为私有(private)与团队(team)两层,写入时按记忆类型的归属决定落到哪个目录:个人的角色、偏好留在 private,团队共享的约定与决策进 team。当团队记忆开启后,多人协作里因约定不一致而产生的冲突,也会在做梦的整合阶段被一并梳理。在这种共享场景下,前面提到的文件锁尤为重要——它避免多个进程同时维护同一份记忆而互相踩踏。从治理视角看,这种按作用域隔离的设计,正是企业级落地需要的那种控制力:个人上下文与团队知识各归其位,既能共享沉得下来的规范,又不会让私有信息越界扩散。07 新鲜度管理时效性信息会被打上新鲜度标记,相对日期则在整合时被改写为绝对日期,好让它在时间流逝后仍可解读。配合至少 24 小时一轮的整理节奏,带时效的记忆会被定期重新审视,而不是被无限期地照单全收。新鲜度给出「何时该重新审视」的信号,做梦流程决定审视之后是合并、降级还是剪除。这里有一处和存储结构相扣的细节:新鲜度警告只对「已被载入」的记忆生效。若某条记忆因为索引超过 200 行而被截断在外,它根本不会被加载,也就拿不到任何过期提醒。换句话说,新鲜度的可靠性,最终仍取决于索引层是否保持精简——这又回到了第三节那条 200 行的硬上限。参考文献Claude Code 官方文档,How Claude remembers your project — code.claude.com/docs/en/memory - https://code.claude.com/docs/en/memoryAnthropic,Memory tool(API 文档)— platform.claude.com - https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-toolMilvus Blog,Claude Code Memory System Explained: 4 Layers, 5 Limits — milvus.io - https://milvus.io/blog/claude-code-memory-memsearch.mdmem0,How Memory Works in Claude Code — mem0.ai - https://mem0.ai/blog/how-memory-works-in-claude-codeclaudefa.st,Auto Dream(整理流程四阶段)— claudefa.st - https://claudefa.st/blog/guide/mechanics/auto-dreamclaude-code-analysis(liuup),extractMemories 提示词 — github.com/liuup/claude-code-analysis - https://github.com/liuup/claude-code-analysisSleep-time Compute,UC Berkeley × Letta,2025 — arXiv:2504.13171Dataiku,Agent memory: the missing layer in enterprise AI systems — dataiku.com - https://www.dataiku.com/stories/blog/agent-memory
Claude Code 的记忆机制
一套用 Markdown 文件、四类划分与「做梦式」整理流程,把无状态模型变成可跨会话积累的协作者的工程范例。引言:记忆为何是智能体的分水岭能力大模型本身是无状态的。每开一次会话,上下文窗口都是一张白纸;会话一结束,窗口里的一切随之清空,下一次对话从零开始。对一次性的问答,这没什么代价,使用者重新交代一遍背景即可。可一旦智能体要在数天、数周的跨度里反复服务同一个人、同一个项目,这种健忘就成了价值的天花板——它无法积累,也无法从过去学到任何东西,每次都得重新认识自己的工作对象。业界一个被反复验证的判断是:有没有记忆所带来的能力差距,往往比更换一个更强的底座模型还要大。记忆把无状态的模型调教成能够跨会话积累的协作者:它记得使用者的角色与偏好,也记得项目里定过的决策和踩过的坑,因而越用越顺手。更大的上下文窗口替代不了这件事——窗口只解决单次会话内的连贯,而且 token 越多,成本与延迟越高;真正的跨会话智能,要靠把关键认知留在窗口之外的持久层里。对企业而言,这一层的意义更直接。客服智能体记不住客户的历史工单、研发智能体记不住团队既定的规范,带来的就不止是体验问题,更是落地的根本障碍。记忆因此成了智能体的护城河:它把每一次交互都变成可复用的组织知识。但记忆同时也提出了治理上的新课题——隐私、数据隔离、合规,以及「该忘记什么」的机制,都要在设计之初就考虑进去。Claude Code 的记忆机制,正是把这套理念落到生产环境的一个完整范例。它用最朴素的 Markdown 文件、清晰的四类划分,以及一套模仿人脑睡眠的整理流程,回答了「什么该记、何时取出、如何不腐烂、如何隔离」这几个核心问题。下文逐层拆解。01 根本原则:只记上下文无法派生的认知记忆系统的入口处有一道筛子:一条信息是否「无法从当前上下文派生」。凡是能通过读代码、看文件、调工具重新得到的事实,都不该写进记忆。这类信息随时可重建,写下来只会占用预算,还要承担过期的风险。值得留存的,是丢失之后需要人重新告知、或者要跨多次会话才能积累起来的认知。落到 Claude Code 上,跨会话的知识由两套机制共同承载。一套是 CLAUDE.md——使用者亲手写下的长期指令,记录项目约定、构建命令、固定规范这类「每次都要重申」的内容;另一套是 Auto Memory(自动记忆)——模型根据使用者的纠正与偏好,自己判断哪些值得留下并写入。两者都在会话开始时载入,被当作上下文提示而非强制规则来对待。一个克制而关键的设计:系统提示明确要求模型把自己的记忆当成线索而非事实,落到具体动作前会先去核对真实代码。这种「记忆只是提示」的姿态,显著降低了凭记忆产生幻觉的概率,也正在被其他智能体框架借鉴。02 四类记忆:语义分型而非时间堆叠Auto Memory 把留存的认知归入四类,每一类都对应一种「上下文里拿不到、又值得跨会话保留」的信息。归类的依据是语义主题,而非发生的先后顺序。User —— 角色与背景记录使用者是谁:担任的角色、专业领域、沟通偏好、长期的工作背景。这类信息变化慢、复用率高,几乎每次会话都用得上,因此通常进入静态加载的部分,常驻上下文。它的作用域限定为私有。Feedback —— 纠错与确认这一类有个容易被忽略的细节:如果只记录「做错了什么」,记忆会逐渐退化成一张避雷清单,模型读着读着就变得畏手畏脚,越来越保守。所以除了纠错,还要把「被确认可行的用法」一并记下来。纠错划出边界,确认给出可以放心复用的范式,两者缺一不可。Project —— 进行中的目标保存当前推进的目标、deadline、过程里出现的 incidents 以及定下的决策。这里有一条硬规则:所有相对日期都要转成绝对日期。「下周三」在写下的当天清晰,三周后再读就失去了锚点;落成 2026-06-24 这样的形式,记忆才能在任意时刻被正确解读。Project 记忆天然带有时效,过期之后的处理方式见维护一节。Reference —— 外部系统信息存放外部系统里相对固定的坐标——Grafana 的看板 URL、Linear 里的项目标识之类。它们几乎不变,作用是查表,省去每次重新寻址的成本。四类记忆各自落在独立的 Markdown 文件里,文件顶部用 frontmatter 标注 name、description、type 三项。其中 description 尤其关键,它是后续动态召回时用来做相关性匹配的依据。03 存储结构:索引层与主题文件整个记忆库存在磁盘上,路径是 ~/.claude/projects/project/memory/。每个项目一个独立目录,目录里散落着一个个主题文件,以及一个统领全局的索引文件 MEMORY.md。MEMORY.md:只放指针的索引MEMORY.md 是整个记忆库的索引,本身不存放记忆正文。每行一条指针,形如 - [标题](file.md) — 一句话提要,单行控制在约 150 字符以内,文件不带 frontmatter。它的职责是「这里有哪些记忆、各自指向哪个文件」,真正的内容留在被指向的主题文件中。两条硬上限:200 行 / 25 KB。会话启动时只有 MEMORY.md 的前 200 行会被载入系统提示,超出部分被静默截断——系统只在文件里附了一句很难被注意到的警告。失效是无声的:索引一旦涨到第 201 行,最旧的条目就从底部掉出,模型在新会话里看到的是一份干净的系统提示,根本不知道自己「忘了」什么。这条上限,正是索引必须保持精简的根本原因。Topic file:三层结构每个主题文件由三层构成:name(名字)、description(描述)、type(归属的记忆类型)。description 写得准不准,直接决定这条记忆能不能在该出现的时候被取回。这也是为什么系统反复强调:写入前先检查已有文件,能更新就别新建,避免制造近似重复。04 读取与写入机制读和写由三个函数分担,各自的时机与范围如下。函数触发时机取回 / 写入范围loadMemoryPrompt()会话启动MEMORY.md 前 200 行,整段注入 system prompt,始终在场findRelevantMemories()处理当前问题时按相关性最多取回 5 个主题文件extractMemories()回复收尾、且无工具调用时子代理在后台写入记忆目录静态加载 loadMemoryPrompt()启动时把 MEMORY.md 的前 200 行注入 system prompt。这部分记忆始终在场、无需触发,适合放 User 这类高频复用的信息。动态召回 findRelevantMemories()根据当前问题的相关性,从主题文件里最多挑 5 个取回。上限卡在 5,是为了在「带回足够背景」和「不淹没上下文」之间留出余地。需要留意的是,这套召回靠关键词匹配,并不使用向量嵌入——若提问说的是「端口冲突」,而记忆里写的是「docker-compose 映射」,字面对不上就可能召回不到。措辞因此会实打实地影响命中率。后台提取 extractMemories()写入由一个子代理在后台完成。触发条件是:模型已经产出最终回复、并且这一轮没有任何工具调用——也就是对话自然收尾、进入闲谈状态的时刻。如果主代理在这一轮里已经写过记忆,子代理就直接跳过,避免重复落盘。子代理以完整 fork 的方式启动,共享主代理的 prompt cache,拉起来几乎是零成本。这一点很重要:正因为启动便宜,才敢在每个合适的回合都顺手做一次提取,不必担心开销。它运行在严格约束之下:回合预算有限,只能读写记忆目录、不允许 rm,并且只准依据最近若干条消息来更新,不得再去翻源码或跑 git 旁证。05 维护机制:Auto Dream(做梦)读和写解决的是单次会话内的进出,维护解决的是存量记忆随时间的腐烂。Anthropic 给这套流程起了个贴切的名字:Dream(做梦),自动运行的版本叫 Auto Dream。比喻取自人脑——白天用 Auto Memory 记下零碎的短期笔记,睡眠时再由「做梦」把它们复盘、强化、丢弃、重新归档为长期记忆。之所以需要它,是因为连续用上二三十次会话后,笔记会开始发霉:相互矛盾的条目堆积、相对日期失效、引用的文件已被删除、同一件事被三处重复记录。本该帮模型记住的笔记本,反而成了干扰它的噪声。触发与边界做梦由两个条件共同决定何时运行:距上次整理至少过去 24 小时,且期间有足够的会话活动;也可以用 /dream 命令手动触发。这项能力目前由服务端特性开关控制,以研究预览的形式向有开发者权限的用户分批放开。运行时它守着几条硬边界:只动记忆目录里的文件,绝不碰源码或配置;在后台独立进程里跑,不阻塞正在进行的会话;并且靠一把文件锁保证同一项目同一时刻只有一个「做梦者」——这正是分布式锁要解决的问题。四个阶段Orient 定向先 ls 一遍记忆目录,读 MEMORY.md 摸清现有索引,再略读各主题文件,顺带找出孤儿文件——那些实际存在、却没被索引登记的条目。目的是先建立一张全局地图,再动手。Gather 采集到会话记录(JSONL 文件)里捞新信号,用窄关键词检索而非通读全文,重点找使用者的纠正、反复出现的主题、以及重要决策。Consolidate 整合核心维护发生在这里:把重合的条目合并,相对日期改写为绝对日期,删除已被推翻的事实,清掉引用失效的陈旧条目。对已经过期的 Project 记忆,做法是降级保留——标记为历史,而非直接删除。过去发生过什么仍是有用的认知。Prune 剪枝最后重写 MEMORY.md,把总行数压回 200 行以内:移除指向已不存在文件的指针,把过于冗长的条目降格——索引里只留提要,细节挪进主题文件。这套设计有学理支撑:它呼应了 UC Berkeley 与 Letta 在 2025 年的「睡眠时计算」?Sleep-time Compute, arXiv:2504.13171?思路——用空闲算力提前整理,换取下一次会话的效率。实测中,曾有案例在 9 分钟内整合了 913 个会话的记忆,另有项目的索引从 280 行收敛到 142 行。需要提醒的是,做梦的剪枝相当激进:首次运行前最好备份记忆目录,并把不可丢失的关键决策显式标注,以免被误删。06 团队记忆与目录隔离记忆的作用域分为私有(private)与团队(team)两层,写入时按记忆类型的归属决定落到哪个目录:个人的角色、偏好留在 private,团队共享的约定与决策进 team。当团队记忆开启后,多人协作里因约定不一致而产生的冲突,也会在做梦的整合阶段被一并梳理。在这种共享场景下,前面提到的文件锁尤为重要——它避免多个进程同时维护同一份记忆而互相踩踏。从治理视角看,这种按作用域隔离的设计,正是企业级落地需要的那种控制力:个人上下文与团队知识各归其位,既能共享沉得下来的规范,又不会让私有信息越界扩散。07 新鲜度管理时效性信息会被打上新鲜度标记,相对日期则在整合时被改写为绝对日期,好让它在时间流逝后仍可解读。配合至少 24 小时一轮的整理节奏,带时效的记忆会被定期重新审视,而不是被无限期地照单全收。新鲜度给出「何时该重新审视」的信号,做梦流程决定审视之后是合并、降级还是剪除。这里有一处和存储结构相扣的细节:新鲜度警告只对「已被载入」的记忆生效。若某条记忆因为索引超过 200 行而被截断在外,它根本不会被加载,也就拿不到任何过期提醒。换句话说,新鲜度的可靠性,最终仍取决于索引层是否保持精简——这又回到了第三节那条 200 行的硬上限。参考文献Claude Code 官方文档,How Claude remembers your project — code.claude.com/docs/en/memory - https://code.claude.com/docs/en/memoryAnthropic,Memory tool(API 文档)— platform.claude.com - https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-toolMilvus Blog,Claude Code Memory System Explained: 4 Layers, 5 Limits — milvus.io - https://milvus.io/blog/claude-code-memory-memsearch.mdmem0,How Memory Works in Claude Code — mem0.ai - https://mem0.ai/blog/how-memory-works-in-claude-codeclaudefa.st,Auto Dream(整理流程四阶段)— claudefa.st - https://claudefa.st/blog/guide/mechanics/auto-dreamclaude-code-analysis(liuup),extractMemories 提示词 — github.com/liuup/claude-code-analysis - https://github.com/liuup/claude-code-analysisSleep-time Compute,UC Berkeley × Letta,2025 — arXiv:2504.13171Dataiku,Agent memory: the missing layer in enterprise AI systems — dataiku.com - https://www.dataiku.com/stories/blog/agent-memory