所属专题簇:记忆与上下文算法深挖
Agent memory 的项目快照是如何同步到本地的?Claude Code 又如何避免无声覆盖用户已有记忆?
Claude Code 用一套小型同步协议来管理 agent memory snapshot:先判断是否存在本地记忆,再根据 snapshot 时间戳和 syncedFrom 元数据决定是初始化、本地提示更新,还是保持不动。
这一章聚焦 agent memory snapshot 的状态机与同步语义,而不是重复介绍 memory scope。
- snapshot 同步不是“有就覆盖”。
- Claude Code 至少区分首次初始化、提示更新和无需动作三种状态。
syncedFrom元数据是这套协议的关键。
- snapshot 协议:src/tools/AgentTool/agentMemorySnapshot.ts
- memory 路径与 scope:src/tools/AgentTool/agentMemory.ts
- agent 加载入口:src/tools/AgentTool/loadAgentsDir.ts
flowchart TD
A["发现 snapshot metadata"] --> B{"本地 memory 存在?"}
B -- 否 --> C["initialize"]
B -- 是 --> D{"存在 syncedFrom?"}
D -- 否 --> E["prompt-update"]
D -- 是 --> F{"snapshot.updatedAt > syncedFrom?"}
F -- 是 --> E
F -- 否 --> G["none"]
C --> H["copy snapshot -> save syncedFrom"]
E --> I["提示用户更新或同步"]
src/tools/AgentTool/agentMemorySnapshot.ts 的 checkAgentMemorySnapshot() 直接返回:
noneinitializeprompt-update
这里已经是一个非常明确的小状态机,而不是松散辅助逻辑。
如果:
- snapshot metadata 存在
- 本地 memory 目录里还没有
.md文件
则动作是 initialize。这说明项目 snapshot 的首要用途是帮助 agent memory 完成首次冷启动。
如果本地已有 memory,但:
- 没有
syncedFrom - 或 snapshot 的
updatedAt晚于syncedFrom
则返回 prompt-update,而不是直接覆盖。
这很关键,因为它表明 Claude Code 认可“本地 agent memory 可能已经发展出自己的分支”,因此不能把项目 snapshot 当绝对真相。
同一文件里有三种动作:
initializeFromSnapshotreplaceFromSnapshotmarkSnapshotSynced
这说明“接受 snapshot”与“只是记下我看过这个 snapshot”是分开的,不是一个按钮语义。
src/tools/AgentTool/agentMemory.ts 表明 agent memory 有:
userprojectlocal
而 snapshot 同步最终会落在具体 scope 的 memory 目录里。因此 snapshot 并不是抽象层,而是会直接影响某个 scope 的持久状态。
因为它揭示了一个很有意思的设计判断:
- Anthropic 不只关心“agent 是否有记忆”
- 它还关心“记忆是怎么初始化、更新、继承和分叉的”
这已经接近版本化知识同步,而不是普通 prompt 拼接。
- snapshot sync 是一套显式协议,不是附带脚本。
syncedFrom是它的关键协调元数据。- Claude Code 倾向于提示更新,而不是默认静默覆盖本地 agent memory。