Claude Code 源码分析(五):分层记忆体系 —— AI Agent 的知识持久化架构

本系列文章基于 Claude Code 2.1.88 版本的 TypeScript 源码进行分析。源码版权归 Anthropic 所有,本文仅用于技术研究。

引言

AI Agent 的记忆管理是一个尚未被充分解决的工程问题。单次对话中的上下文会随着压缩而丢失,跨会话的知识无法自动积累,不同 Agent 之间的经验无法共享。Claude Code 实现了一套三层记忆架构------会话内记忆、跨会话记忆、Agent 级记忆------在不同时间尺度上解决知识持久化问题。

涉及的核心源码文件:

  • src/services/SessionMemory/ ------ 会话内记忆(3 个文件)
  • src/services/extractMemories/ ------ 跨会话记忆提取
  • src/tools/AgentTool/agentMemory.ts ------ Agent 级记忆目录
  • src/tools/AgentTool/agentMemorySnapshot.ts ------ 记忆快照与同步

一、会话内记忆(Session Memory)

src/services/SessionMemory/ 负责在单次会话内提取和管理记忆。

1.1 提取时机判断

typescript 复制代码
function shouldExtractMemory(messages: Message[]): boolean { ... }
function countToolCallsSince(messages: Message[], lastMessageId: string): number { ... }

系统根据工具调用次数和消息量判断是否需要提取记忆。这种基于活动量的触发机制避免了过于频繁的提取(浪费 API 调用)和过于稀疏的提取(丢失重要信息)。

1.2 并发控制

typescript 复制代码
function markExtractionStarted(): void { ... }
function markExtractionCompleted(): void { ... }
async function waitForSessionMemoryExtraction(): Promise<void> { ... }

记忆提取过程有锁机制,防止并发提取。waitForSessionMemoryExtraction 允许其他操作等待提取完成后再继续,确保后续操作能看到最新的记忆状态。

1.3 记忆模板与 Prompt

typescript 复制代码
async function loadSessionMemoryTemplate(): Promise<string> { ... }
async function loadSessionMemoryPrompt(): Promise<string> { ... }
function getDefaultUpdatePrompt(): string { ... }

记忆提取使用专门的 prompt 模板,指导模型从对话中提取结构化的知识。

1.4 记忆大小分析

typescript 复制代码
function analyzeSectionSizes(content: string): Record<string, number> { ... }
function generateSectionReminders(sizes: Record<string, number>): string[] { ... }

系统会分析记忆各部分的大小,当某个部分过大时生成优化建议。这防止了记忆文件无限膨胀。

1.5 位置追踪

typescript 复制代码
function getLastSummarizedMessageId(): string | undefined { ... }
function setLastSummarizedMessageId(id: string | undefined): void { ... }

系统追踪"上次总结到哪条消息",确保增量提取不会重复处理已总结的内容。当对话被压缩时,这个标记会被重置(因为旧的消息 UUID 不再存在)。


二、跨会话记忆(Extract Memories)

src/services/extractMemories/ 负责从对话中提取可跨会话复用的知识,持久化到 CLAUDE.md 等记忆文件中。

CLAUDE.md 是 Claude Code 的项目级记忆文件,类似于 .editorconfig.eslintrc,但存储的是 AI 助手需要了解的项目知识:编码规范、架构决策、常用命令等。

跨会话记忆的提取发生在会话结束时或用户显式触发时,提取的知识被追加到 CLAUDE.md 中,供后续会话使用。


三、Agent 级记忆

3.1 记忆目录管理

agentMemory.ts 为每个 Agent 类型维护独立的记忆目录:

typescript 复制代码
function sanitizeAgentTypeForPath(agentType: string): string { ... }
function getLocalAgentMemoryDir(dirName: string): string { ... }
function getAgentMemoryDir(agentType: string, scope: AgentMemoryScope): string { ... }
function isAgentMemoryPath(absolutePath: string): boolean { ... }
function getAgentMemoryEntrypoint(agentType: string, scope: AgentMemoryScope): string { ... }

sanitizeAgentTypeForPath 将 Agent 类型名转换为安全的文件系统路径。isAgentMemoryPath 用于判断一个路径是否属于 Agent 记忆目录,这在权限检查中很重要------Agent 对自己的记忆目录有特殊的读写权限。

3.2 记忆快照

agentMemorySnapshot.ts 实现了记忆的快照与同步机制:

typescript 复制代码
function getSnapshotDirForAgent(agentType: string): string { ... }
function getSnapshotJsonPath(agentType: string): string { ... }
function getSyncedJsonPath(agentType: string, scope: AgentMemoryScope): string { ... }
async function readJsonFile<T>(path: string): Promise<T | null> { ... }
async function copySnapshotToLocal(agentType: string): Promise<void> { ... }

快照机制支持记忆的版本管理和跨作用域同步。copySnapshotToLocal 将远程或共享的记忆快照复制到本地,确保 Agent 在离线环境中也能访问其记忆。


四、记忆与压缩的协同

记忆系统与上下文压缩系统之间有紧密的协同关系。

4.1 会话记忆压缩

src/services/compact/sessionMemoryCompact.ts 实现了基于会话记忆的压缩策略:

typescript 复制代码
function setSessionMemoryCompactConfig(config: SessionMemoryCompactConfig): void { ... }
function getSessionMemoryCompactConfig(): SessionMemoryCompactConfig { ... }
async function initSessionMemoryCompactConfig(): Promise<void> { ... }

当上下文需要压缩时,系统优先尝试会话记忆压缩------将对话中的关键信息提取为记忆,然后用记忆替代原始对话内容。这比简单的截断保留了更多有价值的信息。

4.2 压缩后的记忆重置

在自动压缩完成后,会话记忆的位置标记会被重置:

typescript 复制代码
// autoCompact.ts 中
setLastSummarizedMessageId(undefined)

因为压缩会替换消息列表,旧的消息 UUID 不再存在。


五、记忆在 Agent 派生中的传递

5.1 记忆加载事件

当 Agent 加载其记忆时,系统会记录遥测事件:

typescript 复制代码
if (selectedAgent.memory) {
  logEvent('tengu_agent_memory_loaded', {
    agent_type: selectedAgent.agentType,
    scope: selectedAgent.memory,
    source: 'subagent',
  })
}

5.2 CLAUDE.md 的选择性加载

不同类型的 Agent 对 CLAUDE.md 的需求不同。例如 Explore Agent 设置了 omitClaudeMd: true

typescript 复制代码
export const EXPLORE_AGENT: BuiltInAgentDefinition = {
  omitClaudeMd: true,  // 不加载项目记忆文件
}

Explore Agent 是一个快速的只读搜索代理,不需要了解项目的编码规范或架构决策。主 Agent 拥有完整的上下文,会在 Explore Agent 的结果基础上做出判断。

5.3 嵌套记忆去重

ToolUseContext 中维护了一个去重集合,防止同一个 CLAUDE.md 文件被重复注入:

typescript 复制代码
loadedNestedMemoryPaths?: Set<string>
// 源码注释:readFileState is an LRU that evicts entries in busy 
// sessions, so its .has() check alone can re-inject the same 
// CLAUDE.md dozens of times.

在繁忙的会话中,LRU 缓存会驱逐条目,导致 readFileState.has() 检查失效,同一个 CLAUDE.md 可能被注入数十次。独立的去重集合解决了这个问题。


六、总结

Claude Code 的分层记忆体系在三个时间尺度上解决了知识持久化问题:

其一,会话内记忆通过增量提取保留对话中的关键信息,与压缩系统协同工作,确保上下文压缩不会丢失重要知识。

其二,跨会话记忆通过 CLAUDE.md 等文件实现项目级知识的积累,使得 AI 助手能够在多次会话中逐步"了解"一个项目。

其三,Agent 级记忆为每个 Agent 类型维护独立的知识库,支持快照和同步,使得专业化的 Agent 能够积累领域经验。

三层记忆之间的协同设计(压缩时的记忆重置、Agent 派生时的选择性加载、嵌套记忆去重)确保了整个系统的一致性。对于正在构建 AI Agent 记忆系统的团队,这套分层架构提供了一个清晰的参考框架。

相关推荐
不懒不懒2 小时前
【自然语言处理:词嵌入技术与 CBOW 模型详解】
人工智能·机器学习
新缸中之脑2 小时前
FineTune Studio:Mac微调AI工具
人工智能·macos
LuoQuHen2 小时前
第十一章:Agent的“雷区“与边界—— 幻觉、安全、工程化与伦理挑战
人工智能·ai·agent
薛定猫AI2 小时前
【深度解析】Anthropic Epitaxi 泄露:从聊天机器人到统一智能体系统的产品跃迁
人工智能·机器人
天宝耐特2 小时前
赣江之上,SLAM“智”扫跨江桥梁,灵光L2Pro精准守护赣江南昌段通航安全
人工智能·三维激光扫描技术·天宝耐特·航道测绘·灵光l2pro手持扫描仪·其域创新·slam应用
YuanDaima20482 小时前
解决Conda环境下RTX 50系列显卡PyTorch+Transformers+PEFT微调报错
人工智能·pytorch·笔记·python·深度学习·机器学习·conda
俊哥V2 小时前
AI一周事件 · 2026-03-25 至 2026-03-31
人工智能·ai
-Da-2 小时前
【ai应用开发日记】通用未注入Bean AI提示词
java·数据库·人工智能·spring boot·sqlserver
憨波个2 小时前
【说话人日志】从 BLSTM 到 Self-Attention:SA-EEND
人工智能·transformer·音频·语音识别