Agent记忆与上下文工程#
一句话答案#
Agent 记忆分工作记忆(Context Window)、短期记忆(会话级)和长期记忆(跨会话),上下文工程通过压缩、裁剪、动态加载平衡信息完整性与 token 预算。
核心要点
1. 三层记忆架构#
| 类型 | 存储位置 | 生命周期 | 内容示例 |
|---|---|---|---|
| 工作记忆 | Context Window | 单轮推理 | 当前对话历史 + 工具结果 + System Prompt |
| 短期记忆 | Redis / 内存 | 会话级 | 对话摘要、已完成步骤、临时变量 |
| 长期记忆 | 向量库 + DB | 跨会话持久化 | 用户偏好、知识积累、历史决策 |
2. Token 预算分配(以 4K 输入预算为例)#
现在主流模型窗口已到 128K 甚至百万级,但窗口越大不等于越该塞满:官方把”上下文越长、召回准确率越下降”的现象称为 context rot,而且输入 token 直接决定成本和首 token 延迟。所以即使窗口很大,也建议给每次请求设一个明确预算,下面用 4K 预算演示分配思路:
System Prompt: ~500 token(角色+规则+工具描述)
记忆上下文: ~500 token(历史摘要/检索的长期记忆)
检索文档: ~2000 token(RAG 召回内容)
用户输入: ~100 token
预留生成: ~500 token
─────────────────────────
合计: ~3600 tokenplaintext3. 上下文压缩策略#
| 策略 | 原理 | 适用场景 |
|---|---|---|
| 滑动窗口 | 只保留最近 N 轮对话 | 简单多轮对话 |
| 摘要压缩 | LLM 将历史对话压缩为摘要 | 长对话场景 |
| 检索式加载 | 向量检索相关历史片段按需加载 | 知识密集场景 |
| 渐进式披露 | 不一次性装载全部工具/规则 | 工具数量多(>20) |
4. 长期记忆写回策略#
- 写入什么:事实性结论、用户偏好、任务模板(不写入过程性对话)
- 衰减机制:访问频率衰减(LRU)或时间衰减(TTL)
- 冲突处理:新信息覆盖旧信息 + 版本记录
5. 渐进式披露#
Agent 启动时只加载核心工具描述,根据用户意图动态加载相关工具/规则,避免 System Prompt 膨胀。代价是工具表每轮不同,prompt 前缀一变,前缀缓存就从变化处失效。想保住缓存,可以让工具表保持不变,只把规则和打法按需加载(见 [Agent Skill机制与渐进式加载](/topics/ai-agent/Agent Skill机制与渐进式加载)),不该用的工具在执行层拒绝(见 [Agent Harness与Hook设计](/topics/ai-agent/Agent Harness与Hook设计))。
6. 官方上下文工程实践(Anthropic)#
Anthropic 在 Effective context engineering for AI agents(2025-09)里把上下文工程定义为”找出最可能让模型产生期望行为的那组上下文”,核心观点是 token 是有限的注意力预算。长任务常用三招,另有 API 层能力对应:
| 手段 | 做法 | 对应 API 能力(Claude,以官方文档为准) |
|---|---|---|
| Compaction(压缩) | 对话接近上限时把旧轮次总结成摘要,用摘要开新窗口,保留关键决策和未解决问题 | 服务端 compaction(beta):按需压缩或按 token 阈值自动压缩,由服务端生成摘要替换旧轮次 |
| Context editing(按规则清理) | 不做摘要,直接清掉旧的工具结果或旧的 thinking 块 | clear_tool_uses_20250919、clear_thinking_20251015 两种策略(beta) |
| 结构化笔记 / 外部记忆 | Agent 把进度、结论写到上下文之外的文件(如 NOTES.md),需要时再读回 | Memory tool(memory_20250818):客户端工具,Claude 发出 view/create/str_replace/insert/delete/rename 指令,由应用在 /memories 目录下执行,存储由你控制 |
| 子 Agent | 子 Agent 在自己的干净上下文里深挖,只把压缩后的结论(通常一两千 token)交回主 Agent | 应用层编排 |
| Just-in-time 检索 | 上下文里只放文件路径、ID 等轻量引用,运行时再用工具按需加载 | 应用层工具设计 |
组合思路:compaction 负责让活跃上下文保持小,memory 负责保存”必须活过摘要”的信息;context editing 适合只想精确清掉旧工具结果、不想做摘要的场景。
面试回答(2分钟版)
Agent记忆系统我理解为三层架构。工作记忆就是Context Window,存放当前对话历史和工具结果,生命周期是单轮推理。短期记忆用Redis存储,保存会话级别的对话摘要和已完成步骤,支持多轮连续交互。长期记忆用向量库加数据库持久化,存储跨会话的用户偏好和知识积累。上下文工程的核心是Token预算管理,窗口再大也要设预算,以4K输入预算为例:System Prompt约500token,记忆上下文500,检索文档2000,用户输入100,预留生成500,总共约3600token。当对话变长时需要压缩策略:最简单是滑动窗口只保留最近N轮,更好的是摘要压缩用LLM把历史对话压缩成摘要,知识密集场景可以用检索式按需加载相关历史片段。长期记忆的写回要谨慎,只持久化事实性结论和用户偏好,过程性对话不写入,还需要衰减机制防止噪声累积。渐进式披露也很重要,不一次性把所有工具和规则塞进System Prompt,根据用户意图动态加载相关的工具描述。长任务里还会用到官方推荐的几招:接近上限时做 compaction 把旧轮次总结成摘要,用 context editing 清掉旧的工具结果,把必须长期保留的进度写进外部记忆文件,重的子任务交给子 Agent 只回传结论。
追问与易错
追问方向:
- token 预算怎么动态分配?不同场景分配不一样怎么办? → 按优先级动态调整:System Prompt 固定 → 用户输入固定 → 剩余空间按比例分给检索文档和记忆。简单 QA 多给检索,多轮对话多给记忆
- 长期记忆的衰减策略怎么设计?怎么防止噪声累积? → LRU(访问频率衰减)+ TTL(时间衰减)+ 定期清洗(低访问量 + 久远 → 删除)。写入时过滤过程性对话,只持久化事实结论和用户偏好
- 压缩(compaction)和上下文编辑(context editing)有什么区别? → 压缩是把旧轮次总结成摘要再替换,信息被改写但语义保留;上下文编辑是按规则直接删掉旧工具结果或 thinking 块,不生成摘要。工具结果体积大、事后很少回看时用编辑,需要保留来龙去脉时用压缩;两者都可能丢信息,关键事实要先写进外部记忆
- 语义缓存算不算记忆?怎么避免返回过期答案? → 算”答案级”短期复用,不是用户记忆。做法:query embedding 相似度超过阈值才命中,同时校验知识库版本号,知识库更新后旧缓存自动失效;多用户场景缓存 key 要带用户或租户隔离
- 多轮对话越聊越脏(上下文污染)怎么办? → 用摘要压缩定期”清洗”对话历史(每 5-10 轮压缩一次),保留关键信息丢弃细节。标记”不可压缩”的关键事实
- 渐进式披露在工程上怎么实现? → 意图分类后按类别加载对应工具描述,不一次性塞所有工具;也可以用规则按请求特征(是否需要实时信息、是否需要历史记忆等)选出工具子集,System Prompt 只装当前需要的。代价是工具表每轮变化会打断前缀缓存;要保缓存就让工具表不变,只按需加载规则正文(skill),不该用的工具在执行层拒绝
易错点:
- ❌ “把所有对话历史塞进 Context” → token 爆炸,成本激增,注意力稀释
- ❌ “长期记忆只做 append” → 噪声累积导致检索质量下降,需要衰减和清洗
- ❌ “摘要压缩不会丢信息” → 摘要必然损失细节,关键信息需要标记为”不可压缩”