别再只会用向量数据库了!Claude Code记忆机制源码级拆解
现在一提到 AI Agent,十有八九会被追问:“你这个项目的记忆机制是怎么设计的?”
很多人第一反应就是:“用向量数据库存聊天记录,做相似度检索啊。”
这个回答只能拿 60 分。如果你能接着说:“其实 Claude Code 根本不用向量数据库,它只用 Markdown 文件就搞定了记忆,而且比向量检索还稳”,面试官眼睛立马就亮了。
今天咱们就从源码层面,把 Claude Code 这套反直觉的记忆机制彻底拆透。看完你不仅能搞懂它为什么这么设计,还能直接抄走几条原则用到自己的项目里。
先搞懂一个最基本的事实:LLM 本身根本没有记忆
很多人以为,跟 ChatGPT 聊到第 50 轮它还能记得你说过的话,是因为模型把你的对话存进“脑子”里了。
完全错误。
LLM 是彻头彻尾的无状态系统。你每按一次回车,它都会把系统提示词、所有历史对话、当前问题,从头到尾完完整整看一遍,然后生成回复。你以为它“记得”,其实是你的客户端偷偷把所有历史又重新发了一遍。
打个最贴切的比方:LLM 就像一个得了严重失忆症的天才实习生。他写代码、查资料、做分析样样都行,但每天早上一睁眼,昨天发生的事全忘了。
你想让他正常干活,就得在他工位上贴满便签:“你叫张三”、“这个项目要在 6 月 10 号上线”、“老板讨厌 PPT 用斜体”。而 Agent 的记忆机制,本质上就是解决三个问题:
- 这些便签应该贴在哪?
- 谁来写这些便签?
- 什么时候该撕掉旧便签?
记忆分两种:短期记忆就是上下文窗口本身,装着当前这轮对话;长期记忆是持久化存在磁盘上,能跨会话保留的信息。今天咱们重点讲的,就是 Claude Code 的长期记忆设计。
下面这张图直观展示了 LLM 无状态记忆的本质:
业界主流的四种记忆方案,其实全有硬伤
在讲 Claude Code 之前,咱们先盘点一下现在大家常用的记忆方案。你会发现,这些听上去都很合理的方案,真用起来全是坑。
方案一:滑动窗口记忆
最简单粗暴的一种:只保留最近 N 轮对话,超过的直接删掉。LangChain 早期的 BufferWindowMemory 就是这么做的。
但它有个致命问题:删掉的不一定是没用的。比如你第 1 轮说“我是十年 Go 后端,刚接触 React”,聊了 50 轮前端问题后,这句话早就被滑出窗口了。结果第 51 轮它给你按零基础讲起了 HTML,你还得重新说一遍自己的背景。
方案二:对话摘要记忆
比滑动窗口聪明一点:不直接删旧对话,而是定期用 LLM 把旧对话总结成摘要,再塞回上下文。
但它的问题是:重要细节容易被压缩失真。比如你 20 轮前说过“我们的 API 网关用的是 Kong 不是 Nginx”,LLM 做摘要的时候觉得这不重要,就压成了“讨论了一些技术栈细节”。等你问“网关 502 怎么排查”,它按 Nginx 给你答了一通,完全驴唇不对马嘴。
方案三:向量检索记忆
这是目前最火的方案,Mem0、Letta(原 MemGPT)、Zep 全是这个路子。把每条对话转成 embedding 向量存进向量数据库,每次新问题来,先检索最相似的前 K 条塞回上下文。
但它的坑一点也不少:
- 相似不等于相关:你问“这段代码有没有 bug”,它可能把过去所有讨论 bug 的对话都召回来,大部分都是噪音
- 召回不稳定:换个 embedding 模型,结果天差地别
- 维护成本极高:要部署向量数据库、调 chunk 大小、管索引更新
- 完全不可读:存进去的是一堆 768 维浮点数,哪天召回错了,你根本不知道是哪条记忆出了问题
方案四:分层存储记忆
Letta 那一派的方案,把记忆分成 core memory(常驻上下文)、recall memory(最近对话)、archival memory(远期归档),让 LLM 自己当操作系统在不同层之间搬数据。
这套设计学术上很漂亮,但工程落地太复杂。你得教 LLM 什么时候搬、搬哪条记忆,prompt 写得巨长,还经常出问题。而且本质上还是靠向量检索,前面的坑一个都没躲开。
这四个方案有个共同的病根:重检索、轻写入。所有人都在琢磨“怎么查到”,但没人管“该不该存”、“存什么”。结果就是垃圾进,垃圾出,记忆库用不了多久就变成了垃圾堆。
下面这张图对比了四种主流记忆方案的优缺点:
Claude Code 的反直觉设计:不用向量数据库,只用 Markdown 文件
🎯 反直觉洞察:当所有人都在卷向量数据库时,Claude Code 选择了最"土"的 Markdown 文件,却解决了最根本的问题。
就在所有人都在卷向量数据库的时候,Claude Code 走了一条完全不同的路。它没用 embedding,没用复杂的存储引擎,甚至连数据库都没用到。。
它用的是磁盘上的纯文本 Markdown 文件。。
听上去很土对不对?但等你看完整套机制,就会明白为什么这个“土办法”反而比向量检索好用得多。。
Claude Code 的记忆机制是两条独立的线并行工作::
## 静态层 vs 动态层对比
| 维度 | 静态层 (CLAUDE.md) | 动态层 (自动记忆) |
|------|-------------------|------------------|
| **本质** | 声明式指令 | 学习式偏好 |
| **内容** | 你写好的规则 | Agent 自动学到的经验 |
| **加载时机** | Agent 启动时全量加载 | 按需加载 |
| **解决的问题** | "我们怎么协作"<br/>"项目有什么规则" | "我从跟你的互动中学到了什么" |
| **类比** | 公司员工手册 | 个人工作笔记 |
打个比方:
- 静态层就像公司的员工手册,每个新员工入职都得看
- 动态层就像你自己的工作笔记,写的是"老板不喜欢 PPT 用斜体"、"张三的需求经常变"这种你自己摸索出来的经验
静态层:为什么一个 CLAUDE.md 不够用,非得拆成六个层级?
很多人对 CLAUDE.md 的印象,就是项目根目录放一个 md 文件,写点项目说明。但你打开源码就会发现,Claude Code 把它拆成了六个层级。。
为什么要这么做?因为不同的规则,来源不一样,可见范围不一样,谁能改也不一样。硬塞进一个文件里,只会乱成一锅粥。。
按加载顺序从低到高,这六个层级分别是:
- Managed 层:放在系统级路径,只有管理员能改。公司级的强制策略,比如“禁止提交密钥”,就放这层
- User 层:放在用户家目录下,你自己的全局偏好。无论在哪个项目,“commit message 用中文”这个习惯都会生效
- Project 层:项目根目录的
CLAUDE.md或.claude/CLAUDE.md,项目层规则,签入 git 让整个团队共享 - Local 层:项目根目录的
CLAUDE.local.md,默认不签入 git,只有你自己能用 - Auto 层:项目级的自动记忆目录,Claude Code 自动写入的偏好都存在这里
- Team 层:Auto 目录下的
team/子目录,团队共享的 AI 学到的偏好好
这六层是叠加关系不是覆盖关系。Claude Code 启动时会把它们全部拼接进系统提示词,让模型一起看到。。
除了分层,静态层还有两个特别巧妙的设计:
- @include 指令:就像 C 语言的
#include一样,你可以在 CLAUDE.md 里引用其他文件。比如公司有一份通用安全规范,每个项目都得遵守,不用每个项目都复制一遍,直接@include就行 - 条件规则:你可以写一条只在编辑特定文件时才加载的规则。比如前端规范只在编辑
.tsx和.jsx文件时生效,编辑后端代码时就不加载,大大节省了 tokenn
下面这张图展示了 CLAUDE.md 六个层级的叠加关系:
引用 ----------------------^ Expecting 'SEMI', 'NEWLINE', 'SPACE', 'EOF', 'subgraph', 'end', 'acc_title', 'acc_descr', 'acc_descr_multiline_value', 'AMP', 'COLON', 'STYLE', 'LINKSTYLE', 'CLASSDEF', 'CLASS', 'CLICK', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', 'direction_tb', 'direction_bt', 'direction_rl', 'direction_lr', 'direction_td', got 'LINK_ID'
动态层:让 Agent 自己学、自己写、自己用的完整闭环
🔄 完整闭环:从记忆抽取到验证使用的五步流程,让 Agent 真正"学会"而不是"记住"。
如果说静态层是框架,那动态层就是 Claude Code 的真正灵魂。CLAUDE.md 再好,也得你主动写。而动态记忆能让 Agent 在跟你聊天的过程中,自动把学到的东西记下来,下次你不用再说第二遍。
遍。
第一步:只允许四种记忆类型,其他一律不许写
要让 Agent 自己写记忆,第一个要解决的问题就是:让它写什么?
如果放任它自由发挥,三天下来记忆库就成了垃圾桶。Claude Code 的答案干脆利落:只允许写四种类型,其他一律不许存。
user(用户画像):记“你是谁”。比如“这位用户写了十年 Go,刚接触 React”feedback(行为偏好):记“你不喜欢什么/什么做法有效”。比如“这位用户不希望每次回复后做总结,给 diff 就行”project(项目动态):记“项目正在发生什么”。比如“移动端 3 月 5 号开始合并冻结”reference(外部指针):记“去哪查什么”。比如“流水线 bug 都在 Linear 的 INGEST 项目里追踪”
而且
feedback和project类型有强制结构:必须包含规则本身、为什么这么要求、什么情况下生效。比如"不要用 mock 测试"这条记忆,还要加上"上季度 mock 测试通过但生产环境迁移挂了"和"所有标了集成测试的 case 都适用"。
为什么这么严? 因为只记规则不记原因,遇到边界情况 Agent 就抓瞎了。
还有一条非常重要的禁令:绝对不能存代码能推出来的东西。比如文件路径、函数名、Git 历史,这些用
grep或git log就能查到,存了反而会和实际状态不一致,变成"权威的错误"。
第二步:存储设计:单文件+索引
所有记忆都是独立的 Markdown 文件,每个文件头有一段 YAML 元数据,记录名称、描述和类型。
然后有一个特殊的
MEMORY.md文件,是所有记忆的索引清单。这里有一个非常关键的设计:只把索引塞进系统提示词,完整内容按需加载。
就像你不用把整本字典背下来,只要知道目录里有什么,需要的时候再翻到那一页就行。这样既不会让 Agent 不知道有哪些记忆可用,又不会把上下文窗口撑爆。
第三步:写入:后台专门跑一个记忆提取代理
记忆是怎么写进去的?不是让主对话模型一边干活一边写,那样会分心,还浪费 token。
Claude Code 的做法是:每轮对话结束后,后台单独 fork 一个轻量代理来抽取记忆。这个代理复用主对话的 prompt 缓存,几乎不额外花钱。它会扫一遍这一轮的对话,跟现有记忆比对,有新的值得记的内容,就按四种类型分类写进新文件。
第四步:检索:用小模型做选择题,不用向量计算
下次对话来的时候,怎么从 100 条记忆里挑出最相关的 5 条?你第一反应肯定是向量检索对吧?但 Claude Code 偏偏不这么干。它的做法是:把所有记忆的标题和描述拼成一个清单,发给 Sonnet 小模型,让它直接选出最相关的 5 个文件名。
为什么这么做?因为向量相似度是个冷冰冰的数值,0.87 到底算不算相关?没人说得清。而小模型做的是自然语言判断,“这条该选,那条不该选”,判错了也是可解释的,调起来比调向量阈值容易得多。
而且只要候选集合不大(几百以内),用小模型选择的成本,比维护一个向量数据库的人力 + 算力成本低得多。
第五步:注入:加老化警告,逼模型主动验证
记忆被选出来之后,不会直接塞进对话
Claude Code 会用 <system-reminder> 标签把它包起来起来,并且如果这条记忆是 5 天以前写的,还会主动加一句警告:“这条记忆是 5 天前保存的,使用前请先验证它是否仍然准确”。
这一条设计,直接解决了向量检索最致命的问“权威的错误”。记忆不是真理,只是历史快照。模型见到旧记忆的时候,会自动带着怀疑的心态去用,先 grep 一下代码确认,发现冲突就更新或忽略它。
下面这张图完整展示了动态记忆的五步闭环流程:
四条能直接抄进你项目的设计原则
看完 Claude Code 的整套机制,提炼出了四条通用的设计原则,不管你用什么框架做 Agent,都能直接抄走:
- 结构化优于自由文本:给你的记忆定一个严格的 schema,强制每条记忆都填齐类型、来源、置信度、更新时间。自由文本无约束,最后一定会变成垃圾堆。
- 索引常驻+内容按需:任何内容总量大但只有少数需要展开的场景,都可以用这个模式。先让 Agent 知道有什么,需要的时候再加载完整内容,平衡可用性和 token 消耗。
- 廉价模型做选择题:只要候选集合不大,用小模型做相关性判断,比向量检索更准确、更可解释、成本更低。
- 时间感知+主动验证:永远不要让模型把记忆当真理。给所有记忆加上时间戳,旧记忆主动加警告,要求模型使用前先验证当前状态。
下面这张图总结了四条设计原则及其核心要点:
面试怎么答才能拿 95 分?
最后回到开头那个问题:“你的 Agent 项目记忆机制是怎么做的?”
如果你只能答出“用向量数据库做相似度检索”,那是 60 分。
如果你想拿 95 分,可以这么说:
首先,LLM 本身是无状态的,记忆机制的本质是给模型提供上下文参考。业界主流的滑动窗口、对话摘要、向量检索这几个方案,都有重检索轻写入、自由文本无约束、没有老化机制的共同问题。
Claude Code 的源码,它走了一条不同的路,用结构化 Markdown 文件代替向量数据库。它把记忆分成静态和动态两层,静态层用六个层级的 CLAUDE.md 管理声明式规则,动态层只允许四种记忆类型,用后台代理自动抽取,用小模型做检索选择,还给旧记忆加老化警告逼模型主动验证。
这套设计给了我很大启发,我在自己的项目里也借鉴了结构化记忆、索引常驻和时间感知这几个原则,效果比单纯用向量检索稳定得多。
能说到这个程度,你就不仅懂技术,还有自己的思考,稳了。
更多推荐



所有评论(0)