Memory 机制
2.1.233 有四套互不替代的记忆面:本地 auto memory、session memory、agent memory,以及连上的 project memory store(memory_list / read / write)。
0. 2.1.233 的 memory_* 工具#
这三件套操作的是已连接的 project memory store(带 store id,路径形如 /project/<id>/MEMORY.md),不是本地 ~/.claude/projects/.../memory/ 那条 Write/Edit。
memory_list:不传store就列本会话连上的 store(id、描述、可写/只读、索引路径);传了就按path_prefix分页列文档。memory_read:读一篇,返回 content + 12 位 version。memory_write:整篇覆盖,上限 100KB;if_version乐观并发(新建传字面量new)。auto 模式下checkPermissions走 passthrough,交给分类器。- 三个都
shouldDefer,进 ToolSearch。 isEnabled:settingsorgMemoryRead !== false,再叠 GrowthBooktengu_haze_glass、策略allow_memory_sync、CLAUDE_CODE_DISABLE_ORG_MEMORY。没连上 store 时 list 会说 none / connecting。
本地 auto memory 仍用 Write/Edit 写 MEMORY.md 目录。/pause-memory 暂停 automemory;/memory 编辑 CLAUDE.md 和 memory 设置。
1. auto memory:跨会话持久记忆#
路径在 memdir/paths.ts:
- 默认 base dir:
~/.claude - 默认项目记忆目录:
~/.claude/projects/<sanitized-git-root-or-project-root>/memory/ - 入口索引:
MEMORY.md - 支持
CLAUDE_CODE_REMOTE_MEMORY_DIR、CLAUDE_COWORK_MEMORY_PATH_OVERRIDE、settings 中autoMemoryDirectory覆盖。 isAutoMemoryEnabled()默认开启,但会被CLAUDE_CODE_DISABLE_AUTO_MEMORY、CLAUDE_CODE_SIMPLE、远程无持久目录、settingsautoMemoryEnabled: false关闭。
memdir/memdir.ts 的 prompt 明确规定写入格式:
- 记忆内容写到单独
.md文件,带 frontmatter:name/description/type 等。 MEMORY.md只是索引,每条一行,未来会默认加载。- 避免保存可从代码直接推导出的事实,主要保存用户偏好、反馈、项目背景、外部引用等。
2. auto memory 何时写入#
有两个写入来源:
A. 主 agent 直接写
system prompt 中会告诉模型:用户明确要求 remember/forget 时立即写入 memory。此时模型会用 Write/Edit 写到 auto memory 目录。权限层对 auto memory 有特殊放行和安全校验:memdir/paths.ts、utils/permissions/filesystem.ts、utils/memoryFileDetection.ts 会识别 auto memory 路径。
B. 后台 extractMemories subagent 写
services/extractMemories/extractMemories.ts:
- 初始化:
initExtractMemories()。 - 触发:完整 query loop 结束、模型给出无工具调用的最终响应后,经 stop hook/post-sampling 类链路 fire-and-forget 执行。
- 只在主 agent 运行,subagent 不跑。
- 受 gate
tengu_passport_quail、isAutoMemoryEnabled()、remote mode 限制。 - 如果检测到主 agent 已经在本段消息中写过 auto memory,则跳过后台提取,避免重复写。
- 有节流:
tengu_bramble_lintel控制每 N 个 eligible turn 才提取一次。 - 有并发合并:提取进行中时,新请求只保留最新 context,当前完成后跑一个 trailing extraction。
- forked agent
maxTurns: 5,skipTranscript: true,只允许Read/Grep/Glob、只读 Bash、以及 memory 目录内的Edit/Write。
这说明 memory 写入不是每轮都同步阻塞主流程,而是"主 agent 可显式写;没写时后台 agent 尽力补写"。
3. auto memory 何时读取#
读取分三层:
- 启动/系统上下文加载:
loadMemoryPrompt()会创建 memory 目录并把 memory 行为说明放进 system prompt;MEMORY.md的内容通过 CLAUDE.md/memory 文件加载链路进入 user context(索引有 200 行和 25KB 限制)。 - 查询相关记忆预取:
utils/attachments.ts的startRelevantMemoryPrefetch()在用户 turn 开始时后台启动,调用findRelevantMemories()。它扫描 memory 文件 frontmatter,再用 sideQuery 让 Sonnet 从 manifest 里最多选 5 个相关文件,结果作为relevant_memoriesattachment 注入后续迭代。这个预取不会阻塞第一轮;如果没赶上,会跳过并下轮再试。 - 模型主动读:prompt 的 "When to access memories" 要求在用户要求 recall/check/remember 时主动访问;模型可用
Read/Grep/Glob搜 memory 目录。
4. session memory:当前会话压缩用笔记#
services/SessionMemory/sessionMemory.ts 维护的是当前会话 notes,不等同于跨会话 memory。
写入位置:utils/permissions/filesystem.ts 的 getSessionMemoryDir() / getSessionMemoryPath(),位于 ~/.claude/session-memory/... 体系下。
触发条件:
initSessionMemory()在启动时注册 post-sampling hook,但只在非 remote 且 auto compact enabled 时启用。- 2.1.233 制品里没有
tengu_session_memory这个 GrowthBook 名。session memory 面还在:viewer、current_session_memoryattachment、compact 仍读 notes。 - 默认初始化阈值:上下文达到
10_000token。 - 默认更新阈值:距离上次提取增长
5_000token。 - 默认工具调用阈值:3 次 tool calls。
- 满足 token + tool call,或 token 满足且最后 assistant turn 没有 tool call(自然停顿),才提取。
写入方式:forked agent 读取 notes 文件,再只允许对该文件执行 Edit。默认模板包含 Current State、Task specification、Files and Functions、Errors & Corrections、Worklog 等章节。
读取时机:
- session-memory compact 会读取它,把它变成压缩后的 summary 基础。
- 2.1.233 slash 表没有
/summary;提取靠 token/tool 阈值和 compact 前的等待。 waitForSessionMemoryExtraction()在 compact 前最多等待 15 秒,避免刚提取的 notes 来不及参与 compact。
5. agent memory#
tools/AgentTool/loadAgentsDir.ts 支持 agent frontmatter memory: user|project|local。启用后会给 agent 注入 memory prompt,并在工具集合中确保 Read/Edit/Write 可用于 agent memory 文件。它是 subagent 专用的持久上下文,不等于主会话 auto memory。