Agent 上下文工程:从 Token 管理到终身记忆
0. 引言
想象这样一个场景:你让 Agent 帮你调研一个开源项目。第一轮,你告诉它「只关注 Python 实现,忽略 JS 版本」。第三轮,它兴高采烈地给你推荐了一个 Node.js 库。你纠正了它。到了第五轮,它又忘了。
你忍不住问:你的记性为什么这么差?
这个问题背后,是 AI Agent 领域一个被严重低估的核心挑战——上下文工程(Context Engineering)。大多数人以为,只要上下文窗口足够大(比如 Gemini 的 1M tokens),Agent 就能「记住一切」。但真实情况是:上下文窗口是 Agent 的 RAM,记忆系统才是 Agent 的硬盘——两者缺一不可,且各自有各自的工程难题。
本文将系统性地拆解 Agent 记忆系统,从问题定义到工程方案,分为六个层次逐步深入。
1. 问题定义:上下文窗口的幻觉
长上下文是必要条件,但它带来的问题远比解决的问题多。我们来看四个核心挑战:
1.1 注意力稀释:Lost in the Middle
2023 年,Liu 等人在论文 Lost in the Middle: How Language Models Use Long Contexts 中揭示了一个反直觉的发现:当信息位于上下文窗口的中间位置时,模型的检索准确率会显著下降。
这个发现的重要性怎么强调都不为过。模型不是均匀地「注意」所有上下文——它天然倾向于关注开头(首因效应)和结尾(近因效应),中间部分的信息被严重稀释。当你把 100K tokens 的上下文一股脑塞给模型时,中间 40K-60K 位置的关键指令可能已经被「淹没」了。
1.2 成本爆炸
以 GPT-4 级别模型为例,输入价格为 $10/1M tokens。1M token 上下文的一次推理就要 $10,而一个复杂的 Agent 任务可能需要十几轮甚至几十轮对话。成本不是线性增长,而是飞轮效应——每轮都把历史带上,上下文越来越长,成本越来越高。
| 上下文长度 | 单轮成本(估算) | 10 轮对话成本 |
|---|---|---|
| 32K tokens | $0.32 | ~$5 |
| 128K tokens | $1.28 | ~$25 |
| 500K tokens | $5.00 | ~$80+ |
| 1M tokens | $10.00 | ~$150+ |
1.3 幻觉加剧
上下文越长,无关信息越多。模型在多轮对话中会逐渐被早期噪声干扰,产生「上下文幻觉」——用错误的记忆覆盖正确的信息。这不是模型本身的幻觉问题,而是上下文工程的问题。
1.4 延迟不可控
KV Cache 的大小与上下文长度成正比。1M token 上下文的 prefilling 阶段可能需要数秒甚至数十秒,首 token 延迟(TTFT)从毫秒级膨胀到秒级。对于需要快速响应的 Agent 场景,这是致命的。
结论: 上下文窗口大 ≠ 记忆好。你需要一套工程体系来管理 Agent 的「注意力预算」。
2. 上下文分层架构
Agent 记忆系统的核心设计理念是分层——不是一层记忆,而是三层。
2.1 工作记忆(Working Memory)
定义: 当前对话窗口中的全部信息,4K–32K tokens,严格顺序保留。
工作记忆是 Agent 的「意识」。它包含系统提示(角色定义、行为规则)、对话历史(用户输入和 Agent 回复的完整序列)、工具定义(函数签名和参数 schema),以及从长期记忆中检索到的相关上下文。
关键工程挑战:
- 触发压缩的时机: 当 token 预算达到阈值(如 70%)时,必须触发压缩,而不是等 OOM 再处理
- 压缩策略选择: 摘要(保留语义,丢失精确细节)vs 截断(保留最新信息,丢失历史)vs 关键对话提取(保留决策点和纠正,丢弃过程噪音)
- 压缩粒度: 对早期轮次进行激进压缩(只保留摘要),对近期轮次保持原始内容
2.2 情景记忆(Episodic Memory)
定义: 历史会话的结构化摘要,向量化存储,支持语义检索。
情景记忆是 Agent 的「短期记忆」。当一次会话结束后,不是把原始对话全部丢掉,而是提取关键信息——决策、纠正、偏好变化——并以向量的形式存储。
存储什么:
- 用户在这次会话中的偏好表达(「以后用 pytest 不要用 unittest」)
- Agent 在这次会话中的关键决策及其原因
- 用户对 Agent 行为的纠正(「上次你说 X,实际是 Y」)
- 会话最终产出的摘要
不存储什么:
- 过程性讨论和试探性尝试
- 工具调用的中间结果
- 用户明确表示「不要记」的内容
2.3 语义记忆(Semantic Memory)
定义: 长期累积的结构化知识,包含用户画像、领域知识、工具经验和固化技能。
语义记忆是 Agent 的「长期记忆」,也是最稳定的一层。它不随会话结束而消失,而是逐步累积和更新。
| 类别 | 示例 | 存储方式 |
|---|---|---|
| 用户画像 | 角色、编程风格偏好、时区 | 结构化标签 |
| 领域知识 | 项目文件结构、常用 API 端点 | 文档化存储 |
| 工具经验 | 「该 API 超时设为 30s 而非 5s」 | 结构化经验库 |
| 固化技能 | 从多次重复操作中提取 SOP | 可执行技能定义 |
核心原则: 语义记忆必须是结构化的,不能是纯文本堆砌。因为它在每次推理时都会被注入到系统提示中,结构化的信息更容易被模型有效利用。
3. Token 预算管理
如果把上下文窗口比作 Agent 的「预算」,那么 Token 就是 Agent 的「货币」。你需要一个精打细算的财务管理系统。
3.1 静态预算分配
以 128K 上下文窗口为例,建议的分配策略:
| 组件 | 建议占比 | 说明 |
|---|---|---|
| 系统提示 | 10-15% | 角色定义、行为规则、语义记忆注入 |
| 工具定义 | 10-15% | 函数签名、参数 schema、工具描述 |
| 对话历史 | 40-50% | 工作记忆核心内容 |
| 检索上下文 | 15-20% | 从情景记忆中检索到的相关信息 |
| 预留余量 | 5-10% | 工具调用返回结果的空间 |
3.2 动态调度机制
静态分配只是起点。真正的挑战在于动态调度:
工具返回截断: 当工具调用结果超过预留空间时,不直接截断到固定长度,而是提取关键信息——比如从 10000 行的日志中只保留 ERROR 和 WARNING 级别的内容。
递进式压缩: 不是一次性压缩所有历史,而是递进式处理。早期轮次(第 1-5 轮)高度压缩为摘要,中期轮次(第 6-10 轮)保留关键对话,近期轮次(最近 5 轮)完整保留。
记忆外化: 当上下文即将耗尽时,主动将部分信息「外化」到外部存储,并在需要时通过检索召回。这类似于操作系统的虚拟内存机制。
3.3 实践建议
1 | # 伪代码:Token 预算检查 |
重要提示: 不要信任模型自报的 token 计数。始终使用独立的 tokenizer 维护精确计数,在每次工具调用前后检查预算。
4. 记忆检索:Agent 的搜索引擎
存得好不如取得好。如果检索系统不能在海量记忆中精准召回相关信息,那记忆系统就是个昂贵的摆设。
4.1 Agent 场景的检索特殊性
相比传统 RAG,Agent 的记忆检索有三个独特挑战:
- 时间敏感性: 上一条消息中用户说的「不要用 unittest」比三个月前说过的话重要得多
- 上下文依赖性: 同样的查询「跑一下测试」,在不同项目、不同阶段含义完全不同
- 精确匹配需求: 用户可能明确提到实体名(如「那个叫 hermes-agent 的项目」),需要关键词级别的精确匹配
4.2 混合检索公式
单一维度无法满足 Agent 的需求。我们需要混合检索:
1 | score = α × 语义相似度 + β × 时间衰减 + γ × 关键词匹配 + δ × 重要性权重 |
各维度详解:
- α × 语义相似度(权重 0.40): 基于 embedding 的 cosine similarity,捕捉语义层面的相似性
- β × 时间衰减(权重 0.25): 指数衰减函数
e^(-λ × Δt),让近期记忆有更高的召回率 - γ × 关键词匹配(权重 0.20): 使用 BM25 算法,确保用户提到的精确实体能被命中
- δ × 重要性权重(权重 0.15): 在存储时由 LLM 对记忆的重要性进行预打分
4.3 检索时机
Agent 不应该只在用户明确要求时才去检索记忆。三种触发时机:
- 主动检索: 每轮对话开始时,根据用户最新输入检索相关记忆,注入工作记忆
- 被动检索: 当 Agent 对自己的回答不确定时,主动查询记忆进行校验
- 触发词检索: 用户说「上次」「之前」「我记得你说过」时,强制触发跨会话检索
5. 终身学习:让 Agent 越用越聪明
三层记忆架构解决的是「记住什么」和「怎么取」的问题。但还有一个更深刻的问题:Agent 能不能从经验中学习,而不是每次都需要用户重新教一遍?
这就是终身学习(Lifelong Learning)——Agent 记忆系统的最上层。
5.1 学习什么
Agent 可以从以下几个维度持续学习:
| 学习维度 | 触发条件 | 示例 |
|---|---|---|
| 用户偏好 | 用户明确表达或行为暗示 | 「回复简洁一点」→ 更新用户画像 |
| 纠正学习 | Agent 犯错后被用户纠正 | 「你说的 X 不对,实际是 Y」→ 更新知识 |
| 工具经验 | 任务执行中遇到问题并解决 | 「此 API 并发限制 10 req/s」→ 更新工具使用经验 |
| 项目约定 | 用户多次使用相同模式 | 连续 5 次用 pytest -n 4 → 固化为默认 |
| 成功模式 | 某个任务流程多次成功执行 | 「这种调研任务分 3 步做最快」→ 固化为技能 |
5.2 学习机制
显式学习: 用户明确纠正 Agent → 立即更新相关记忆。这是最高优先级的学习信号。
隐式学习: Agent 从成功完成的任务中提取模式。不需要用户干预,但需要足够多的样本(连续 3-5 次相同模式)才会触发固化。
反思学习: 任务失败后,Agent 进行根因分析(Root Cause Analysis),将教训以「反模式」的形式存入记忆,避免下次犯同样的错误。
5.3 防止灾难性遗忘
记忆系统最大的敌人不是「记不住」,而是「记错了」或者「新知识覆盖了旧知识」。
三大防御机制:
- 冲突检测: 新记忆与旧记忆矛盾时,优先信任用户最新表达,但保留旧记忆作为上下文参考
- 衰减而非删除: 长期未使用的记忆降低检索权重,但不删除。因为「很久没用的知识」可能只是暂时不需要
- 定期审计: 定期让 Agent 自查记忆一致性。例如:用户说他是「Python 开发者」,但某条记忆写的是「主要写 Rust」——这种矛盾应该标记出来
6. 工程实践与总结
6.1 架构全景
完整的 Agent 记忆系统架构可以总结为三层 + 两个管道:
- 三层: 工作记忆 → 情景记忆 → 语义记忆
- 向下管道(压缩沉淀): 工作记忆过期 → 压缩为情景记忆 → 长期知识提取为语义记忆
- 向上管道(检索召回): 语义记忆 + 情景记忆通过混合检索 → 注入工作记忆
6.2 选型建议
| 场景规模 | 推荐方案 |
|---|---|
| 个人开发者 / 原型验证 | SQLite + ChromaDB + 简单摘要策略 |
| 小团队 / 内部工具 | PostgreSQL + pgvector + Redis 缓存 + 混合检索 |
| 生产级 Agent 系统 | 自研记忆服务 + 专用向量数据库 + 事件溯源 + 持续评估管道 |
6.3 关键启示
回顾全文,我想强调三个核心理念:
- 「上下文窗口是 Agent 的 RAM,记忆系统是 Agent 的硬盘」——两者缺一不可,且各自需要精心设计
- 「好的记忆系统让 Agent 从工具变成伙伴」——它不需要你反复交代,能从过往交互中学习成长
- 「不要等到上下文不够用了才想记忆——在设计的第一天就要考虑三层架构」
6.4 展望
Agent 记忆系统还远未成熟。展望未来,有几个值得关注的方向:
- 多模态记忆: Agent 不仅要记住文本,还要记住图片、代码片段、结构化数据
- 联邦记忆: 多个 Agent 共享部分记忆,形成集体智能
- 自适应记忆架构: 根据用户使用模式自动调整各层容量和检索策略
- 隐私感知记忆: 用户可以选择性地「遗忘」某些信息,符合 GDPR 等隐私法规
本文首发于 jackzhu.top。如果你在大厂 Agent 团队工作或有相关实践经验,欢迎在评论区交流讨论。





