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 记忆系统的团队,这套分层架构提供了一个清晰的参考框架。

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
回眸&啤酒鸭3 天前
【回眸】Minicart 电商购物车核心功能落地指南
人工智能
一隅论数智3 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
AI的探索之旅3 天前
97 个 OpenCV 实例(三十):双目立体,从标定到点云
人工智能·opencv·计算机视觉
AlbertZein3 天前
Step-5-Preview 上手实测:3D 游戏、金融分析、网页设计一次跑完
人工智能·aigc
LaughingZhu3 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
1点东西3 天前
做了近两年的Agent开发,其实真正要学的就是这五件事
llm·agent·ai编程
wukangjupingbb3 天前
智能网联汽车安全能力框架
人工智能