8.3 上下文管理与记忆

人类的大脑有短时记忆(工作记忆)和长时记忆(经验知识)。 一个高可用的 Agent 也需要这两层记忆结构。只依赖单一的上下文窗口往往是难维护且昂贵。

8.3.1 记忆的分层架构

spinner

图 8-1:Agent 记忆分层架构示意图

正如上图所示,一个完整的记忆系统并非单体,而是由不同介质、不同访问速度的存储层组成的混合体。这就好比计算机有寄存器(极快但极小)、内存(快且适中)和硬盘(慢但海量)。

在 Claude Agent 的设计中,我们通常将记忆分为以下三个层级,分别对应不同的应用场景:

Working Memory

  • 介质: 模型的 Context Window (Prompt)。

  • 内容: 当前正在进行的对话、最近几步的思考过程 (CoT)、临时变量。

  • 特点: 速度快,但容量有限,掉电(会话结束)即失。

Episodic Memory

  • 介质: 向量数据库 (Vector DB)。

  • 内容: 过去发生过的类似事件、历史对话记录。

  • 实现: RAG (Retrieval-Augmented Generation)。当用户问起“上周我们讨论了什么方案”时,Top-k 检索相关的历史片段注入 Context。

Semantic Memory

  • 介质: 外部知识文档、结构化数据库。

  • 内容: 公司的 SOP、产品手册、Fast Facts。

8.3.2 上下文记忆 vs 权重记忆:Agent 排错的关键区分

上述三层架构解决的是“如何存取信息”,但还有一个更根本的问题——信息究竟住在哪里?LLM 的知识载体分为上下文记忆(存在于 Prompt 中,即取即用但会话结束即消失)和权重记忆(通过预训练固化在参数中,模型发布后即冻结)。

这个区分对 Agent 排错有直接影响:当 Agent 回答“错误”时,你需要判断问题出在哪一层——如果是上下文不足(该给的信息没给),可以通过改进 RAG 或扩大窗口解决;如果是权重本身的知识缺陷(模型“从来没学过”),则只能等待下一代模型或通过工具调用来弥补。

关于上下文记忆与权重记忆的深层原理(Position Interpolation、持续学习、灾难性遗忘等)的详细分析,参见姊妹篇《大语言模型原理》14.8.5 节。

8.3.3 突破上下文窗口限制的技术

上下文窗口的需求没有天花板。当 Agent 从“聊天助手”进化为“自主执行者”——需要处理整个代码库、进行多轮工具调用——上下文需求将轻松突破百万 token。分层 Memory 和压缩策略都是过渡方案;在智能压缩真正成熟之前,暴力扩大窗口仍是最直接有效的路径。

Context Caching

Claude 3.5 引入的 Prompt Caching 功能是降低 Agent 成本的神器。

  • 原理: 由于 Agent 的 System Prompt 和 RAG 文档在多轮对话中是不变的,Anthropic 允许将这些静态部分(Prefix)缓存起来。

  • 收益: Input Token 成本最高可降低 90%,首字延迟 (TTFT) 降低 80%

  • 用法: 在发送请求时,通过 beta header 标记哪些 block 需要缓存。

Memory Tool

除了隐式的 RAG,还可以给 Agent 一个显式的“记事本工具”。

Tool Definition:

Workflow:

  1. User: “以后生成的代码都用 Python。”

  2. Agent Call: manage_memory(action="save", key="coding_lang", value="Python").

  3. (Three days later) User: “写个脚本。”

  4. Agent Call: manage_memory(action="read", key="coding_lang") -> "Python".

Progressive Disclosure(渐进式上下文加载)

Claude Code 团队在实践中发现,与其一次性把所有文档塞进系统提示词,不如让 Agent 主动按需获取上下文。这一策略体现在两个关键设计选择上:

Grep 优于 RAG(在代码场景中):团队最初使用向量数据库(RAG)为 Agent 提供代码上下文,但后来发现直接给 Agent 一个 Grep 工具效果更好。原因在于:RAG 返回的是预先切分的语义片段,而开发者真正需要的是精确的代码行定位和文件结构探索。Grep 工具让 Agent 能够像人类开发者一样,通过关键词搜索逐步“钻入”代码库,自主构建对项目结构的理解。

Agent Guide 模式:团队没有在系统提示词中堆砌大量 Claude Code 的使用文档,而是提供了一个“Agent Guide”子代理(或链接)。只有当 Agent 遇到不确定的情况时,才会调用这个子代理查询文档。这保持了主要上下文的干净和聚焦。

核心原则:让 Agent 主动构建自己的上下文,而非被动接收预加载的海量信息。这不仅节省了 Token,还能让 Agent 获取到更精准、更相关的信息。

Context Compression

当对话轮数(Turns)超过 50 轮时,直接截断会导致丢失早期目标。 Summarization Strategy:

  • 每隔 10 轮对话,触发一个 Summary Agent。

  • 将前 10 轮对话压缩成一段 200 字的摘要。

  • 将这段摘要作为新的 System Prompt 的一部分,替换掉原始的历史记录。

8.3.4 会话分支与工作状态恢复

在 Claude Code 的实践中,"记忆"不仅仅是对话历史——它是完整的工作状态(Work State)。理解这一点对设计健壮的 Agent 系统至关重要。

用户可用的会话操作

Claude Code 为用户提供了几种不同的会话操作方式:

操作
用法
说明

Resume(恢复)

claude --resume

从中断处继续,恢复完整工作场景(包括进行中的计划和文件状态)

Fork(分叉)

claude --resume <id> --fork

从某个时间点创建分支,后续独立演化

Subagent(子代理)

Agent 工具自动派生

拥有独立上下文窗口的从属代理

关键区别在于:Resume 恢复的是操作语境(Operational Context),而非仅仅是消息序列。这也是为什么 Claude Code 能够在会话中断后"记住"它正在做什么——它保存的不只是"说了什么",而是"在做什么"。

对 Agent 设计的启示

Claude Code 的这些实践对你设计自己的 Agent 系统有以下启示:

  1. 保存工作状态而非对话状态:如果你的 Agent 需要支持中断和恢复,应该序列化的是"当前任务进度 + 待执行计划 + 中间产物",而不仅仅是聊天记录

  2. 惰性物化:只在真正产生数据时才创建持久化文件,避免空会话占用存储

  3. 事件日志优于消息列表:将会话记录设计为带有元数据的事件流,便于后续的分析、回放和分支

8.3.5 记忆的生命周期管理

就像人类会遗忘一样,Agent 的记忆也需要 GC (Garbage Collection)。

  • TTL (Time-To-Live): 对于短期的任务状态,设置 24 小时过期。

  • Relevance Scoring: 检索记忆时,结合“语义相似度 + 时间衰减因子”。越近的记忆权重越高。

  • Privacy Purge: 提供“忘记我”功能,允许用户删除特定 Key 的记忆(符合 GDPR)。


有了记忆,Agent 就能处理长周期的任务了。但如果任务本身极其困难(比如证明黎曼猜想,或者规划某国登月工程),不仅需要记忆,还需要更长时间的 深度思考

➡️ Extended Thinking 扩展思考模式

最后更新于