乐于分享
好东西不私藏

【白话】深度解析Claude Code源码记忆模块:影子Agent+KAIROS机制

【白话】深度解析Claude Code源码记忆模块:影子Agent+KAIROS机制

这两天 Claude Code 被 “被迫开源” 的消息热度很高,两天时间star已经升至101k,对做 AI Agent 的人而言,这无疑是一份送上门的标准答案。
出于好奇,我把整套源码完整梳理了一遍,内容体量极大,单篇很难讲透。
今天先聚焦大家普遍关注的记忆模块,它依靠三个核心技术决策,既规避了记忆爆炸问题,也避免了因遗忘导致系统失效。内容有点儿多,可以先收藏~
01.
这些场景你一定遇到过
先稍微赘述一下memory记忆模块干的事情:简单说主要是解决每次开新session都要重新解释项目背景的烦躁感;
可以让我们不用每次都对着AI反反复复的说我们的一些通用诉求,比如
“我是后端工程师,用TypeScript,主要做React Native移动端——好了Claude,我们继续上次的工作。”
因此我们需要agent具有记忆,这才是Claude Code真正花大力气解决的问题。
02.
问题的本质:AI记东西,为什么这么难?
大模型没有状态。每次`send`都是白纸一张。Claude Code的解法是:把记忆写成磁盘上的Markdown文件,每次对话开始时读进来,塞进System Prompt 。
这听起来简单,但越做越发现坑:
  • 记忆文件越堆越多,超过Token限制怎么办?
  • 每轮对话结束后,新学到的东西谁来负责写入?
  • 主Agent一边回答一边写记忆,和后台提取记忆,会不会重复劳动?
  • 团队共享记忆时,如何防止有人把API Key也传上去?
Claude Code用三层架构解决了这些问题。
03.
三层架构全景图
记忆系统采用三层架构设计,核心实现“文件存储、自动提取、云端同步”的全流程记忆管理,具体分层及细节如下:
一、持久记忆核心层(memdir/,基于本地文件系统)
作为整个记忆系统的“数据底座”,负责本地记忆的存储、解析、检索与基础管理,所有记忆最终以文件形式沉淀于此;
二、自动记忆提取层(services/extractMemories/,后台影子Agent)
作为记忆的“自动采集器”,由后台影子Agent(智能代理)负责,无需手动操作,自动从相关场景中提取可复用记忆;
三、团队记忆同步层(services/teamMemorySync/,云端同步)
作为团队记忆的“协同桥梁”,负责本地团队记忆与云端的同步,保障多成员、多设备间的记忆一致性;
三层职责分离: 存储的是文件, 写入的是影子Agent, 同步 的是团队云端。这三个层次互相配合,又各自独立演化
具体代码中结构如下:
记忆系统三层结构├── memdir/                     # 持久记忆核心层(本地文件系统)│   ├── paths.ts                # 路径解析与安全校验│   ├── memdir.ts               # Prompt 构建与截断保护│   ├── memoryTypes.ts          # 四种记忆分类 + 内置 Prompt 文本│   ├── memoryScan.ts           # 记忆文件扫描(frontmatter(记忆文件前面有一小段"目录卡") 读取)│   ├── findRelevantMemories.ts # 相关记忆检索(模型侧查询)│   ├── memoryAge.ts            # 记忆时效性管理│   ├── teamMemPaths.ts         # 团队记忆路径管理│   └── teamMemPrompts.ts       # 团队/个人合并 Prompt 构建├── services/extractMemories/# 自动记忆提取层(后台影子 Agent)│   ├── extractMemories.ts      # 提取引擎│   └── prompts.ts              # 提取 Agent 的专用 Prompt└── services/teamMemorySync/# 团队记忆同步层(云端同步)    ├── index.ts                # 同步核心(pull/push/ETag 管理)    ├── watcher.ts              # 文件变更监听器(fs.watch)    ├── secretScanner.ts        # 上传前秘钥扫描    └── teamMemSecretGuard.ts   # 秘钥防泄漏守卫
04.
记忆类型分类法:不是所有东西都值得记
Claude Code强制将记忆分为四种类型,每种有明确的边界和写入规范:
记忆口诀:”我是谁(user)/怎么做(feedback)/在干嘛(project)/去哪找(reference)”
类型
存什么
典型触发场景
user 用户记忆
职业背景、技能水平、工作目标
用户说”我是数据科学家”
feedback 反馈记忆
用户纠正或认可的行为准则
用户说”别再每次都总结一遍”
project 项目记忆
代码和git历史里看不出来的项目背景:谁在做什么、为什么、截止日期
用户说”周四之后冻结合并” 
reference 引用记忆 
外部系统的地址和用途:Linear项目、Slack频道、内部看板
用户说”pipeline的bug在Linear INGEST项目跟踪”
这个分类法,它解决了一个实际问题: 让Claude知道什么值得写进记忆,什么读代码就能知道 。
Prompt里明确告知Claude:代码模式、架构、Git历史、commit message,这些都不值得记 ,因为工具本身就带着这些信息。 只有代码里看不出来的才值得写下来。
user 和 feedback 这两个记忆相对好理解,我们对 project 和 reference 做进一步的解释:
project项目记忆
存的是当前项目的来龙去脉和现状,不是代码怎么写的技术细节。
project 主要记一些关键背景,比如:
  • 为什么要这么改?
  • 这个截止日期是谁定的?
  • 这次重构是因为合规要求,还是单纯清理烂代码?
reference引用记忆
存的是去哪里查,而不是信息本身。外部系统(Linear、Grafana、Slack、内部Wiki)里的内容会不断变化,Claude没法把它们的实时状态存进记忆,能存的是这类信息在那个系统的哪个位置 。
下次遇到相关问题,Claude知道往哪里找,而不是凭记忆直接给出可能过时的答案。
MEMORY.md 截断保护 —`truncateEntrypointContent()`
这里简单提一下大家已经说过比较多的 MEMORY.md 200行限制,工作逻辑如下:
  1. 文件超 200 行 → Claude 只显示前 200 行并弹出警告
  2. 理想情况:Claude 主动精简、合并、删除过时内容
  3. 未清理时:超出内容仍在文件里,平时看不见
    exportconst MAX_ENTRYPOINT_LINES = 200// 最多 200 行exportconst MAX_ENTRYPOINT_BYTES = 25_000 // 最多 25000 字节
  4. 超限时追加警告:
> WARNING: MEMORY.md is 247 lines (limit: 200). Only part of it was loaded.  Keep index entries to one line under ~200 chars; move detail into topic files.
当然被截断后的MEMORY.md还是会有额外的兜底机制,保证记忆被截断后不至于完全失忆,以下是兜底逻辑:
兜底机制
即使 MEMORY.md 超过 200 行后面的条目被截掉,findRelevantMemories()仍然能找到对应的具体记忆文件。它直接扫描文件系统,不依赖 MEMORY.md 索引。会直接扫描文件,绕过 MEMORY 的 200 行限制,仍能找到相关记忆。
MEMORY.md的更新逻辑
代码里没有任何自动删除旧记忆的逻辑 。管理 MEMORY.md 的责任完全压在 Claude 的判断力上,靠 Prompt 指令约束行为。
设计哲学:Anthropic 赌 Claude 足够聪明,看到”索引已截断”警告后会主动整理,而不是无限堆砌,用 LLM 智能替代硬性算法,灵活但无法保证一致性。
05.
影子Agent:在后台负责记忆提取
通俗理解:想象有一个后台记忆秘书,它在你每次和Claude聊完天后,悄悄阅读对话记录,帮你把重要信息整理成笔记。这个秘书完全后台运行,不耽误你继续聊天。
这是整个系统最聪明的设计之一。
每一个完整的查询循环结束时(即主模型产出最终回复、且本轮没有剩余工具调用时), 一个影子Agent在后台悄然启动 ,专门负责从这轮对话中提取可能值得记住的内容。
Claude Code的做法是: 主Agent和影子Agent共享同一份System Prompt和对话历史 (称为”完美Fork”),影子Agent在后台以相同的模型配置运行,完全不干扰主Agent的响应。
互斥机制:防止主Agent和影子Agent重复劳动
如果主Agent已经在对话中主动写过记忆文件,影子Agent会检测到这一点(通过扫描`tool_use`块里的文件路径),然后主动放弃本轮提取 。
两个Agent永远不会写同一轮对话的记忆,互斥,不重复,不遗漏。
Trailing Run:高频对话的兜底机制
如果用户连续快速发消息,影子Agent可能还在处理第一轮,此时第二轮对话已经结束。Claude Code的做法是:把最新上下文暂存起来 ,等当前提取完成后,立即触发一次补充提取,确保中间轮次不被跳过。
最小权限:影子Agent只能读写记忆目录
这是个安全设计:影子Agent的工具权限被严格限制。
工具
权限
FileRead / Grep / Glob
无限制允许(只读)
Bash
仅允许ls/find/cat等只读命令
FileEdit / FileWrite
仅允许写入记忆目录内的文件
其他所有工具
拒绝
这个权限矩阵确保影子Agent即使被Prompt注入攻击,也无法把记忆目录之外的东西写进去。
06.
相关记忆检索:不让无关记忆污染上下文
把所有记忆都塞进对话不现实。Claude Code用了两阶段检索:
Phase 1:scanMemoryFiles()  → 读取每个记忆文件的前30行以解析frontmatter(name/description/type  → 自动排除MEMORY.md(它已通过System Prompt注入,不参与检索)  → 按修改时间倒序,最多返回200个文件Phase 2:sideQuery(Sonnet)  → 用Sonnet判断哪些记忆和当前问题真正相关  → 保守策略:只选"明显有用"的,最多5  → 相关记忆 → Attachment Message注入主对话
通俗理解:记忆文件前面有一小段”目录卡”(frontmatter),写着这是哪种记忆、什么时候记的。检索时先快速扫目录卡,过滤掉无关的;再用Sonnet做第二轮判断,确保只拉取真正有用的进来。
这个设计省了大量Token。先用模型做初筛,确保只有真正相关的记忆才进入主模型的上下文窗口。
07.
KAIROS模式:解决记忆无限膨胀的终极方案
通俗理解:普通模式像每次聊完天就写笔记,时间久了笔记本越来越厚。KAIROS模式换了个策略,平时只写日记(append-only日志),定期找时间做一次精华提炼,把日记整理成精简版笔记本。日记本越来越厚没关系,反正查资料时先去翻精华版,需要细节再去日记里找。
这是整个系统里最值得单独拿出来讲的设计。
普通模式下,影子Agent负责将每轮对话中值得保留的内容提取并写入独立的记忆文件,再在`MEMORY.md`里更新索引,长期使用后`MEMORY.md`越来越长,超过 200行或25,000字节 (两个限制,任一触发即截断)后,Claude只能看到前半部分,后面的内容对主模型不可见 。
Claude Code没有用自动删除策略。它的解法是:KAIROS模式 。
KAIROS模式(长会话/助手模式专用):  平时:对话内容 → 追加写入日志文件         logs/YYYY/MM/YYYY-MM-DD.md(append-only,永不修改)         MEMORY.md由单独的蒸馏步骤维护,不在平时直接编辑  autoDream自动触发条件:距上次整理 ≥ 24小时 AND 积累了 ≥ 5个session  /dream技能手动触发:蒸馏所有日志 → 重写MEMORY.md         → MEMORY.md永远是精华版
日志是append-only的,不做修改,只做积累。蒸馏时把日志里的重要信息提炼出来,重写MEMORY.md。 索引文件永远保持精简,细节在日志里,需要时通过`findRelevantMemories`检索。
这里的设计哲学同样是用LLM的智能代替硬性算法 。不是写个定时任务自动删旧记忆,而是让Claude自己判断什么值得保留,然后用一套蒸馏流程重建索引。
08.
团队记忆同步:多人协作时安全检查
在团队场景下,记忆文件会同步到云端(GitHub repo关联)。这里有一个巨大风险,有人不小心把API Key写进记忆文件,然后同步到团队云端 。
Claude Code做了两层防护:
  1. 第一层:上传前扫描。 同步前自动检测密钥、私钥等敏感内容,只提示违规,不泄露明文。
  2. 第二层:版本锁防冲突。 类似在线文档机制,多人同时修改时,避免内容被覆盖,提交失败会自动重试。
不过话说回来,不知道Claude Code这次被迫开源,有没有走这套逻辑~
09.
结语
Claude Code记忆系统的核心设计哲学是相信模型足够聪明 。
但用LLM智能替代硬性算法也有代价,那就是灵活但无法保证一致性 。
Anthropic赌的是Claude的判断力足够好,对于Memory的更删改主要依赖模型能力来进行。
Claude Code的记忆系统,真正值得借鉴的不是某个具体实现,而是一个系统设计的思路:把存储、执行、检索三层解耦;用影子Agent分离关注点;用append-only日志+蒸馏解决膨胀问题;用权限矩阵控制安全风险。
AI Agent的记忆问题,本质上是一个工程问题,而不是一个模型问题 。需要一个好的记忆架构,让模型每次都能想起来需要的东西。
这个思路,值得做AI应用的人认真看看。

END