4104 字
21 分钟

Letta / MemGPT Memory 深潜:虚拟上下文、Memory Block 与 Agent-controlled Paging

Agent Memory Engineering 专栏 · 5/6。 Letta / MemGPT 的核心不是“再加一个向量库”,而是把有限 Context 当成可管理的虚拟内存,让 Agent 自己决定哪些状态常驻、哪些信息按需检索、哪些内容应该重写或下沉。

专栏导航:总览与选型地图 · Codex · Claude Code · Hermes · Mem0 · Letta · Graphiti


0. 研究基线与架构问题#

本文于 2026-07-15 联网核对 Letta 官方 Context Hierarchy、Memory Blocks、Archival Memory 文档和 MemGPT 论文;源码固定到 letta-ai/letta Commit b76da9092518cbaa2d09042e52fdcbde69243e18。[L1][L2][L3]

核心阅读路径:

schemas/block.py
schemas/memory.py
functions/function_sets/base.py
services/block_manager.py
conversation / archival / file tools
prompt compilation and context window

0.1 十二个研究问题#

  1. Virtual Context Management 与普通 RAG 有什么区别?
  2. Memory Block 为什么是 Prompt ABI,而不只是数据库字段?
  3. label / description / value / limit 各承担什么控制语义?
  4. Always-on Block 何时比 Vector Recall 更可靠?
  5. memory_replacememory_insertmemory_rethink 如何分工?
  6. Whole-block Rewrite 为什么同时强大又危险?
  7. Shared Block 如何成为 Multi-Agent Coordination Primitive?
  8. Conversation Search 与 Archival Search 为什么不能合并?
  9. Files 与 Archival Memory 的分段、可变性和规模边界是什么?
  10. Context Distance 如何影响信息放在哪一层?
  11. Last-write-wins 与 Shared State 会产生哪些一致性问题?
  12. 如何评测 Agent 是否学会了正确 Paging,而不是只会存更多内容?

1. 从 MemGPT 到 Letta:Context Window 是有限 Working Set#

MemGPT 用操作系统虚拟内存类比 LLM Context:模型不能把全部历史永久放在 Context 中,需要在不同存储层之间移动信息。[L3]

Physical Memory
↔ LLM Context Window
Virtual Memory / Disk
↔ Archival / Files / External Stores
Page-in / Page-out
↔ Tool-driven retrieve / write / rewrite

普通 RAG 的典型流程是应用在每次 Query 前替模型检索;Letta 路线进一步让 Agent 能通过 Tool 决定:

  • 哪些信息进入 Always-on Block;
  • 哪些详细事实进入 Archival;
  • 何时搜索 Conversation;
  • 何时打开或关闭 File;
  • 何时重写一个 Block 以释放 Context Budget。

1.1 Agent-controlled Paging#

Observe current task
→ inspect current context hierarchy
→ decide missing information
→ call search/open tool
→ use retrieved evidence
→ update hot memory if future turns need it
→ evict or condense stale hot state

所以 Agent 不只是 Memory 的消费者,也成为 Memory Placement Policy 的执行者。

1.2 Context Management 不是 Storage Management#

存储系统问:

数据放在哪里、如何持久化?

Context 系统还要问:

哪一小部分数据现在值得占用推理预算?

Letta 最有价值的抽象正是把这个第二问题显式化。


2. 官方 Context Hierarchy:四层不是容量大小排序这么简单#

Letta 官方当前给出的推荐边界:[L1]

层级Agent Access是否在 Context推荐规模适合内容
Memory Blocks可编辑或 Read-only每 Block <50k chars,Agent <20 Blocks始终必须知道的状态
FilesRead-only,Open/Close/Search部分每文件 5 MB,Agent <100 Files文档、手册、资料
Archival MemoryInsert/Search单条约 300 tokens,数量不限低频长期事实
External RAG / MCP由自定义工具决定外部系统负责百万级 Corpus

2.1 四层的关键差异#

Memory Block
→ latency low, token cost always paid
File
→ deterministic source, partial open cost
Archival
→ semantic recall, agent-curated write
External RAG
→ independent scale / governance / retrieval

因此不能只按“数据大就往下放”判断,还要考虑:

  • 每 Turn 是否都需要;
  • 是否频繁变化;
  • 是否需要 Agent 修改;
  • 是否要求精确原文;
  • 是否有外部权限与治理;
  • Recall Miss 的业务代价。

2.2 一个 Placement Function#

可以把层级选择写成:

Tier(x)=f(frequency,criticality,size,mutability,precision,governance)Tier(x)=f(frequency, criticality, size, mutability, precision, governance)

例如用户姓名很小、每轮相关、漏召回代价高,适合 Block;一百页产品文档需要精确原文但只在特定问题中访问,适合 File;一次会议的摘要低频但未来可能相关,适合 Archival。


3. Memory Block:Hot Memory 的结构化单元#

源码中的 BaseBlock 至少包含:[L4]

id
label
description
value
limit
read_only
tags / metadata
project / template ownership

3.1 label 是地址#

Agent Tool 通过 Label 找到目标 Block:

human
persona
scratchpad
project_state
system/policy

Label 如果含糊,Agent 难以确定写入目标;如果频繁改名,Tool 调用与外部引用会漂移。

3.2 description 是 Routing Policy#

官方文档强调 Description 是 Agent 判断如何读写 Block 的主要信息。[L2]

label = human
description = stable facts and preferences about the user

Description 不是给 UI 的装饰文案,而是:

Write Router Instruction
+ Read Semantics
+ Retention Intent

一个糟糕的 Description:

misc notes

会让 Agent 把偏好、任务进度、临时 TODO 和长期规则混在一起。

3.3 limit 是 Prompt Budget Contract#

Block Schema 使用 Character Limit;Prompt Render 会把 chars_currentchars_limit 一起展示给模型。[L4][L5]

这使 Agent 能感知容量压力:

Block is 4,800 / 5,000 chars
→ prefer consolidate / replace
→ avoid blind append

3.4 read_only 是 Capability Boundary#

Read-only Block 仍进入 Context,但 Agent 不能通过 Memory Tool 更新。它适合共享政策、组织规范和外部同步状态。[L2]

不过 Read-only 只约束 Agent Tool;能否通过 Developer API 修改,取决于外部权限。不要把 Agent Read-only 误解成数据库不可变。


4. Prompt ABI:Block 如何编译进 Context#

固定版本 Memory._render_memory_blocks_standard() 把 Block 编译成 XML-like 结构:[L5]

<memory_blocks>
<human>
<description>...</description>
<metadata>
- chars_current=...
- chars_limit=...
- read_only=true
</metadata>
<value>...</value>
</human>
</memory_blocks>

4.1 为什么这是 ABI#

模型能否正确管理 Block,依赖:

  • 标签稳定;
  • Description 清晰;
  • Limit 可见;
  • Tool 参数使用同一 Label;
  • Render 与 Mutation 对字符、行号的理解一致。

这和函数 ABI 类似:数据库里 Block 结构正确,但 Prompt Render 改了标签或 Tool 参数不一致,Agent 仍会失败。

4.2 Line-numbered View 的陷阱#

源码还支持带行号的渲染:

1→ Their name is Alice
2→ Prefers concise answers

memory_replace 明确拒绝把显示行号或警告 Banner 放入 old_string / new_string。[L6]

这是 Human-readable Projection 与 Canonical Value 分离的问题:

Rendered view
≠ editable raw value

Tool Schema 必须反复提醒模型不要把 View-only Annotation 写回 Canonical State。

4.3 Git-backed Rendering#

固定版本 Memory 还包含 git_enabled 路线:只把 system/ Block 渲染为核心 Memory,并能把其他文件结构映射进 Memory Tree。[L5]

这表明 Letta 的 Memory 抽象正在从固定 Human / Persona Block 演进为更通用的 Context Filesystem 与 Projection Model。


5. Mutation Primitives:小改、插入、重写与 Patch#

固定版本同时存在多套 Memory Tool Primitive:[L6]

memory_replace
memory_insert
memory_rethink
memory_apply_patch
memory_finish_edits

5.1 memory_replace:精确小改#

它要求 old_string

  • 在 Block 中逐字出现;
  • 只出现一次;
  • 不含 View-only 行号;
  • Tab 规范化后匹配。

零命中和多命中都拒绝修改。这是一种 Optimistic Semantic Selector:Agent 必须基于当前 Block 构造唯一定位。

5.2 memory_insert:位置型增量#

Insert 支持指定行或 -1 追加。它适合新增结构化条目,但如果 Block 已经近满或存在重复事实,盲目 Insert 会加剧 Context Pollution。

5.3 memory_rethink:Whole-block Rewrite#

源码说明它用于大规模压缩、重组和整合,不应用于小改。[L6]

Old Block
+ New Conversation Evidence
→ rewrite complete new block

优势:

  • 可重排结构;
  • 合并重复;
  • 删除过期事实;
  • 一次释放大量预算。

风险:

  • 遗漏一条旧事实即永久丢失;
  • 新旧状态没有自动 Three-way Merge;
  • 并发 Writer 可能被覆盖;
  • 无 Provenance 时无法解释哪条信息来自哪里。

5.4 memory_apply_patch:多 Block Mutation Language#

固定版本定义了类 Unified Diff 的 Patch Protocol,支持 Add/Delete/Update/Move Block。[L6]

这比多个独立 Tool Call 更接近事务意图,但函数本身在该 Function Set 中是抽象入口,真实执行仍要由 Tool Executor 与 Manager 提供原子和权限语义。

5.5 memory_finish_edits#

显式 Finish Tool 能让 Sleep-time / Background Memory Agent 表达“本轮编辑已经完成”,避免系统只能通过超时或无 Tool Call 猜测巩固结束。


6. Shared Blocks:Memory 也是 Multi-Agent Coordination State#

一个 Block 可以附着到多个 Agent。更新一次,所有关联 Agent 都读取同一持久对象。[L2]

flowchart LR
B["Shared organization block"] --> A1["Agent A context"]
B --> A2["Agent B context"]
B --> A3["Agent C context"]
U["Developer / Agent update"] --> B
B --> R["Rebuild connected system prompts"]

固定版本 BlockManager 在 Prompt-affecting Field 变化后,会为所有关联 Agent 重建 System Prompt。[L7]

6.1 Coordination Primitive#

Shared Block 可用于:

  • 组织政策;
  • Team State;
  • Parent / Subagent 结果交接;
  • 共同任务看板;
  • 多 Agent 共享 User Profile。

6.2 Last-write-wins 风险#

官方文档明确警告:直接设置 value 会完整替换 Block;多个进程同时更新时 Last Write Wins,先前修改可能全部被覆盖。[L2]

A reads v1
B reads v1
A writes v2
B writes v3 based on v1
→ A update lost

6.3 生产一致性策略#

可选方案:

version / etag optimistic concurrency
→ reject stale write
patch with unique context
→ reduce overwrite surface
single-writer memory agent
→ serialize consolidation
append-only event log + materialized block
→ retain provenance and rebuild

Fixed Source 中部分 ORM 更新使用 Optimistic Locking、Block Manager 还支持 Checkpoint/Undo/Redo,但应用必须确认所有 Agent Tool 路径是否都经过同一版本控制边界。[L7]


7. Archival Memory:Cold Semantic Memory#

官方将 Archival Memory 定义为 Agent 可 Insert、按语义 Search 的长期数据库;它不常驻 Context,Agent 通常不能方便地修改或删除,Developer API 则可完整管理。[L8]

7.1 写入语义#

archival_memory_insert 的 Tool Description 要求保存自包含事实或摘要,并支持 Tags。[L6]

Conversation evidence
→ agent judges future value
→ self-contained passage
→ optional tags
→ embedding / passage store

7.2 Search Contract#

archival_memory_search 支持:

  • Natural-language Query;
  • Tags + any/all;
  • TopK;
  • Start / End Datetime;
  • Semantic Ranking。[L6]

Temporal Filter 只是按 Passage 创建或存储时间过滤,不自动等于事实有效时间。

7.3 Agent-immutable 的准确理解#

官方所说 Agent-immutable 更接近:Agent 内置工具主要提供 Insert/Search,普通 Agent 不方便原地 Update/Delete;Developer 仍可通过 SDK 管理。[L8]

它不是密码学不可变,也不代表没有删除 API。


8. Conversation Search:Evidence Log,不是 Curated Fact Store#

conversation_search 在 Agent 历史消息中按 Query、Role、时间与 Limit 检索,并返回原始 Role / Content。[L6]

维度Conversation SearchArchival Memory
写入自动产生的消息历史Agent 主动 Insert
单元User / Assistant / Tool Message自包含 Passage
用途找原话、过程与证据找整理后的长期知识
噪声取决于写入质量
Provenance原始消息天然更强需要额外来源字段

8.1 为什么两者都需要#

Archival says:
User prefers PostgreSQL for new services.
Conversation says:
原始讨论、例外条件、日期和谁提出的。

Curated Memory 提高 Recall Efficiency,Conversation Evidence 支持审计与纠错。

8.2 Summary Drift#

如果 Archival Passage 过度压缩,Agent 应能回到 Conversation Search 验证,而不是把摘要当作不可挑战事实。

生产设计可在 Passage 中保存:

source_message_ids
conversation_id
created_at
extractor / writer

9. Files:确定性文档层#

Files 是 Read-only、可部分 Open/Close/Search 的层级。官方建议每文件不超过 5 MB、每 Agent 少于 100 个 File。[L1]

9.1 File 与 Archival 的区别#

File
→ preserve document structure and source identity
→ deterministic open / grep / segment read
Archival
→ passage-oriented semantic recall
→ agent-curated facts

适合 File:

  • API 文档;
  • 公司规范;
  • 研究论文;
  • 需要引用原文的材料。

适合 Archival:

  • 跨会话形成的低频经验;
  • 会议摘要;
  • Agent 主动整理的事实。

9.2 File Block 与 Open State#

源码 FileBlockfile_id / source_id / is_open / last_accessed_at,说明“文件是否进入当前 Context”本身也是可持久化状态。[L4]

这让 Paging Policy 可以考虑:

last accessed
current open set
context budget
task relevance

10. Context Distance:同一事实放在哪一层会改变行为#

信息离模型越近:

Memory Block
→ every inference sees it
Open File Segment
→ current working context sees it
Archival / Conversation
→ only after successful tool call
External RAG
→ after external availability + auth + retrieval

10.1 Push 与 Pull#

Block = system pushes information every turn
Archive = agent pulls when needed

Push Recall 稳定但贵,Pull 便宜但可能不触发。

10.2 Placement Error#

错误后果
关键安全限制放 ArchivalAgent 可能忘记检索
大文档放 BlockContext Pollution 与高成本
频繁变化状态放 ArchivalUpdate 困难、旧 Passage 干扰
低频闲聊放 Block每轮持续付 Token

10.3 一个效用模型#

对候选信息 mim_i

HotUtilityi=P(neededi)×Cost(missi)TokenCostiHotUtility_i = P(needed_i) \times Cost(miss_i) - TokenCost_i

高 HotUtility 适合 Block;低频但高未来价值的信息适合 Archive;需要原文与结构的信息适合 File。


11. Compaction 与 Memory Block 的职责#

Compaction 压缩当前 Conversation Working Set;Memory Block 是持久 Agent State。两者可以协作,但不能互相替代。

Conversation grows
→ summarize / compact historical messages
→ preserve active Blocks
→ Agent continues with stable hot state

如果所有重要状态只在 Conversation 中,Compaction 可能丢细节;如果所有状态都复制进 Block,又会造成重复与冲突。

11.1 Compaction Write-back Policy#

生产 Agent 可以在 Compact 前评估:

Must remain hot → Block update
Useful but low-frequency → Archival insert
Needs exact evidence → keep message / file reference
Temporary progress → compact summary only

这类似 CPU Cache Eviction 前的 Dirty Page Write-back。


12. Security 与 Governance#

持久 Memory 同时扩大 Prompt Injection、跨会话污染、越权写入与难删除派生数据的风险,因此安全评测必须覆盖完整写入、召回和删除生命周期,而不只检查最终回答。[L9]

12.1 Block 是高影响 Prompt Surface#

Block 每轮注入 Context,错误或恶意内容比普通 Archive Passage 影响更持久。

需要:

  • Source / Writer Provenance;
  • Read-only Policy Block;
  • Sensitive Data Classification;
  • Version / Checkpoint;
  • Shared Block 权限;
  • Tool Mutation Audit;
  • Prompt Injection Detection。

12.2 Description Poisoning#

不仅 value 会影响模型,Description 也决定 Agent 如何使用 Block。攻击者如果能修改 Description,可能把“只读政策”描述成“可覆盖草稿”。

Block Manager 把 description / label / limit / read_only / value 都视为 Prompt-affecting Field 并触发关联 Agent Prompt 重建,这正说明治理不能只盯 Value。[L7]

12.3 Shared Block Blast Radius#

一个 Shared Block 连接 NN 个 Agent,错误更新影响面也扩大到 NN 个 Agent。高扇出 Block 应采用:

read_only by default
→ reviewed update
→ versioned checkpoint
→ staged rollout
→ behavior eval
→ rollback

12.4 Archive Poisoning#

Archival Search 是 Pull-based,但恶意 Passage 可以通过高语义相似度进入 Context。检索结果需要带 Trust Label,并与 Tool Permission 分离。


13. 评测:Agent 是否学会正确管理层级#

Memory Eval 不能只问“答案中有没有历史事实”。Letta 路线还要评测 Paging Policy。

13.1 Placement Accuracy#

critical always-on facts → Block
large exact documents → File
low-frequency learned facts → Archive
temporary history → Conversation

13.2 Retrieval Trigger Recall#

当答案需要 Archive / File 时,Agent 是否意识到自己缺信息并调用正确 Tool?

13.3 Hot Context Precision#

Precisionhot=useful hot tokensall hot memory tokensPrecision_{hot}=\frac{useful\ hot\ tokens}{all\ hot\ memory\ tokens}

Block 全部正确但大部分与任务无关,仍会降低推理质量。

13.4 Consolidation Loss#

Whole-block Rethink 前后建立 Gold Facts,测量:

retained facts
incorrectly deleted facts
stale facts retained
new contradictions

13.5 Concurrency Correctness#

两个 Agent 同时编辑 Shared Block,验证是否检测 Stale Version、是否能合并、是否能 Rollback。

13.6 Context Cost#

同时记录:

block tokens per turn
file open tokens
archive search latency
retrieved passage tokens
tool calls before answer

准确率提升但每轮长期多付 30k Tokens,未必是生产可接受方案。


14. 生产化参考架构#

flowchart TB
CP["Context Planner"] --> HB["Hot Memory Blocks"]
CP --> OF["Open File Set"]
CP --> AR["Archival Retriever"]
CP --> CR["Conversation Search"]
CP --> XR["External RAG / MCP"]
MUT["Memory Mutation Policy"] --> BM["Versioned Block Manager"]
BM --> HB
BM --> AUD["Audit + Checkpoints"]
AR --> PS["Passage Store"]
CR --> MS["Message Store"]
HB --> PB["Prompt Builder"]
OF --> PB
AR --> PB
CR --> PB
XR --> PB

14.1 控制面#

  • Block Ownership 与 Read-only;
  • Mutation Permission;
  • Version / Checkpoint;
  • Context Budget;
  • Retrieval Tool Policy;
  • Shared Block Rollout。

14.2 数据面#

  • Block Store;
  • File / Folder Store;
  • Passage / Vector Store;
  • Message Store;
  • Prompt Materialization。

14.3 观测面#

block_update_total{label,result}
block_conflict_total
block_tokens_per_turn
archive_insert_total
archive_search_hit_rate
conversation_search_attribution_rate
file_open_duration
memory_rethink_loss_rate
shared_block_fanout
prompt_rebuild_failure_total

15. Letta 路线的优势与边界#

15.1 优势#

  • 把 Context Placement 显式建模;
  • Agent 可以主动 Paging,而不是被动接收应用 RAG;
  • Block 有 Label、Description、Limit、Read-only 和共享关系;
  • 精确编辑与 Whole-block Rethink 分工清晰;
  • Conversation Evidence 与 Curated Archive 分离;
  • Files 保留确定性结构;
  • Shared Block 支持 Multi-Agent Coordination;
  • Prompt Builder 能显式呈现容量与编辑契约。

15.2 边界#

  • Always-on Block 持续消耗 Token;
  • Agent 可能忘记搜索 Cold Tier;
  • Whole-block Rewrite 有信息丢失风险;
  • Shared Block 存在 Last-write-wins 与高 Blast Radius;
  • Description / Label 设计质量直接影响行为;
  • Archival Semantic Search 仍可能漏召回;
  • 层级越多,Placement Policy 与 Eval 越复杂;
  • 动态事实的有效时间需要额外 Temporal Model。

15.3 最准确的架构定义#

Letta / MemGPT Memory 不是:

Core Memory + Vector DB

而是:

Agent-controlled Context Hierarchy
+ Structured Hot-memory ABI
+ Precise and Whole-block Mutation Primitives
+ Shared Multi-agent State
+ Curated Archival Retrieval
+ Conversation Evidence Search
+ Partial File Paging
+ External Retrieval Escape Hatch

它最值得学习的结论是:

Memory Engineering 的核心不是保存更多,而是让 Agent 在有限 Context 中做正确的信息分层、调入、写回和淘汰。


参考资料与源码#

[L1] Letta Context Hierarchy#

[L2] Memory Blocks#

  • Memory blocks
  • Markdown 原文
  • 核对内容:Label / Description / Value / Limit、Read-only、Shared Block、直接全量更新的 Last-write-wins 警告。

[L3] MemGPT Paper#

[L4] Block Schema#

  • schemas/block.py
  • 核对内容:Block Fields、Read-only、FileBlock、Human / Persona 与 Value Sanitization。

[L5] Memory Prompt Compilation#

  • schemas/memory.py
  • 核对内容:Standard / Line-numbered / Git-backed Rendering、File Blocks、Prompt ABI。

[L6] Built-in Memory and Search Tools#

[L7] Block Manager#

  • services/block_manager.py
  • 核对内容:Block Update、关联 Agent Prompt Rebuild、Bulk Update、Optimistic Locking 与 Checkpoint。

[L8] Archival Memory#

[L9] Agent Memory Security#


上一篇:Mem0 Memory Pipeline 源码深潜 · 下一篇:Graphiti Temporal Memory 源码深潜

Letta / MemGPT Memory 深潜:虚拟上下文、Memory Block 与 Agent-controlled Paging
https://jupiter-ws.cn/posts/ai-coding/agent-memory-letta-deep-dive/
作者
Jupiter
发布于
2026-07-15
许可协议
CC BY-NC-SA 4.0