Context is All You Need:智能体的上下文工程
博客列表 主页

Context is All You Need:智能体的上下文工程

引言:Context is All You Need

在前文《从智能体的认知结构到智能体框架》中,我借 CoALA 讨论了智能体的认知结构,并得出了一个核心判断:Agent 的工程发展史,本质上就是不断用外部系统去弥补当前 LLM 在记忆和推理上的短板。

如果说 《从 Working Memory 到长期记忆:Agent Memory 的全景图》 主要回答的是”Memory 在研究上已经长成了什么样子”,那么这篇文章要回答的就是另一个问题:当我们真正去实现一个 Agent 或一个 Agent 框架时,应该怎样把这些想法压成可运行的 Context 系统?

Context Engineering 和 Memory 高度交叉。按照 CoALA 的理解,Context Engineering 本质上就是对 Working Memory 的工程化管理:在有限的上下文预算里,决定什么该进场、什么该留在场、什么该退场,以及什么应该在需要时被重新召回。只要底层还是 attention 机制和有限窗口,这四个动作就始终构成 Agent Context Engineering 的核心。

所以这篇文章不再承担文献综述职责,也不再把论文拆成附录逐篇解释。这里更关心的是工程面:系统应该如何分层、Memory Manager 应该承担什么职责、读写路径应该如何组织、遗忘和隔离怎么做,以及我们准备参考哪些技术来把这件事真正落到框架里。

Agent Memory 的分层体系

严格区分 LLM Memory 与 Agent Memory

在讨论上下文工程之前,一个必须先澄清的混淆是:KV Cache、RoPE、Attention 变种、长上下文架构,它们解决的是模型如何更高效地利用窗口,而不是智能体如何跨任务维护长期记忆。

LLM Memory 关注的是模型架构层的能力边界,比如 Flash Attention、Ring Attention、KV Cache 压缩等;Agent Memory 关注的是智能体在多轮决策中如何积累、检索、更新和遗忘知识。前者是底层推理基础设施,后者是上层系统设计。把两者混在一起,就很容易把真正的 Context 工程问题误判成”把窗口做得更长”。

从记忆分层到系统分层

关于 Agent Memory 应该被拆分成哪些类型、为什么 Working Memory 是枢纽、长期记忆和参数记忆各自处在什么位置,文献脉络已经可以单独成文。到了工程实现阶段,更重要的问题反而会收缩成两个:

  1. 如何保护 Working Memory 的预算:不能把所有历史和所有检索结果都直接塞进当前上下文。
  2. 如何管理记忆的生命周期:不仅要会读,还要会写、会改、会删、会审计。

也就是说,Context Engineering 并不是把一堆 memory 论文硬拼进框架里,而是要把它们翻译成系统问题:存储层怎么组织,读路径怎么走,写路径怎么走,哪些策略靠规则,哪些策略将来可以学习,哪些动作必须能被开发者检查和干预。

Memory Manager 作为系统组件

与其说 “Agent as Memory”,不如更直接一点:我们需要一个显式的 Memory Manager 组件。 这个组件可以是单独的 Agent,也可以是框架内的系统服务,但它至少要负责五件事:

  • 抽取:从对话、工具调用、环境反馈里识别值得保留的信息。
  • 检索:根据当前任务意图,从不同载体召回候选记忆。
  • 更新:对已有记忆做 merge、supersede、版本更新,而不是只会 append。
  • 遗忘:支持软删除、硬删除、降级和过期处理。
  • 审计:记录来源、时间、冲突状态和操作日志,保证可回溯。

Memory 是基础设施,而不是零散 prompt 技巧。MemGPT 提醒我们要把上下文预算当成操作系统问题来处理;Mem0 说明抽取、更新和召回可以被包装成独立 memory layer;Memory-R1 提供了 learned CRUD 的方向;ACE 和 Dynamic Cheatsheet 则说明 Working Memory 不是只能压缩,它还可以在任务执行中通过 delta update 持续演化。对工程系统来说,重点不是把这些论文逐篇搬进来,而是吸收它们各自证明有效的机制。

检索:把该在场的信息带进来

检索是 Memory 的入口,也是 Context Engineering 最直观的一面。真正的问题从来不是”能不能检索”,而是用什么路径检索、检索到什么粒度、以及如何把结果安全地暴露给 Working Memory。

混合检索,而不是单一路线

目前最实用的方案不是在 RAG 和 Grep 之间二选一,而是接受它们各自擅长不同问题:

  • Grep / 关键词匹配:适合已知术语、配置名、错误信息、规则条目等精确定位任务。
  • 向量检索 / RAG:适合自然语言查询、模糊需求、跨表述召回。
  • LSP / 结构化索引:适合代码、配置、符号引用等天然带类型和层次的信息源。
  • 图遍历 / 关系查询:适合需要多跳关联、时间条件、实体关系的记忆内容。

工程上最有价值的不是押注单一技术,而是把这些路径统一放到检索编排层里:让 Agent 先判断任务属于哪一种信息需求,再选择合适的检索组合,而不是默认所有问题都走相同的向量库。

Query Rewrite 与 Rerank

原始输入通常不是合适的查询。用户说的是任务语言,记忆库存的是摘要、事实、代码片段、规则、图节点和历史上下文,它们之间天然存在语义鸿沟。

因此检索系统至少要有两步增强:

  1. Query rewrite:把用户问题改写成更适合 memory store 的检索语句,必要时拆成多个子查询。
  2. Rerank / compression:把候选结果重新排序,并压成可进入 Working Memory 的最小必要片段。

如果没有这两步,所谓的”检索增强”常常只是把更多噪声搬进上下文。真正有效的检索系统,不是召回一百条候选,而是能稳定挑出那三条真正该在场的信息。

从检索结果到 Working Memory

检索完成后,还有最后一道真正决定效果的工序:promotion 到 Working Memory。 长期记忆的单位不应该原样进入当前上下文,而应经过一个最小必要暴露过程:

  • 提取和当前目标直接相关的字段。
  • 在需要时保留 provenance 和时间信息。
  • 对重复、冲突、低置信度内容做折叠或标记。
  • 超预算时优先保留约束、计划、当前子任务和高价值事实。

Working Memory 不是长期记忆的镜像,而是长期记忆在当前任务切面上的受限投影。

写入:把行动经验变成长期记忆

如果检索回答的是”什么该被带进来”,写入回答的就是”什么值得被留下来”。后者往往更难,因为写入错误会在未来持续污染检索结果。

记忆对象与 Metadata

我越来越倾向于把长期记忆存成 memory object,而不是一大坨未经治理的文本。无论最终落在向量库、数据库、图还是文件系统,一个 memory object 至少都应该有这些字段:

  • type:Persona、conversation、experience、knowledge、rule 等。
  • scope:用户级、会话级、项目级、全局级。
  • content:被保留的事实、规则、经验或摘要。
  • source:来自哪次对话、哪次工具调用、哪份外部材料。
  • timestamp:写入时间和最后更新时间。
  • confidence:这条记忆有多确定。
  • status:active、stale、conflicted、deleted 等。
  • links:它与哪些记忆重复、冲突、继承或 supersede。

只要这些元数据不存在,后面的版本更新、冲突消解、删除与回滚几乎都无从谈起。

抽取、去重、Merge、版本更新

一个可用的写路径至少要经过四步:

  1. 抽取:从原始交互中识别值得保留的候选信息。
  2. 分类:判断它应该进入 Persona、经验、语义知识还是对话记忆。
  3. 对齐:检查是否已有相同或相近记忆,决定是新增、merge、覆盖还是仅记录冲突。
  4. 版本化:保留更新链路,而不是简单覆盖旧值。

比如”用户喜欢拿铁”与”用户最近开始戒咖啡”就不是单纯的二选一覆盖问题。系统需要知道两条记忆的时间关系、适用条件和冲突状态,而不是把它们压成一条失真的静态偏好。

何时写入

很多系统把写入拖到会话结束再统一处理,但这通常太晚了。更合理的做法是按事件触发写入:

  • 用户明确给出稳定偏好或身份事实时。
  • 工具调用成功或失败并产生可迁移经验时。
  • 用户纠正系统、推翻旧事实时。
  • 某个规则在短时间内反复被激活时。

这也是为什么写入策略本身会成为独立研究方向:什么时候写、写什么、写成哪种结构,本身就是 Memory 系统最关键的控制面。

分层级的上下文维护

Context Engineering 的工作并不是把记忆塞进来就结束了,更困难的是在任务执行过程中持续维护当前工作台的可用性。

编排层预加载

在真正进入单步推理之前,系统就应该先完成一部分廉价整理:项目初始化摘要、目录结构、关键接口、用户长期偏好、当前任务计划,都适合在编排层先被准备好。这样做的目标不是把信息提前塞满窗口,而是提前建立可用索引,让后续调用不必每次都从零搜索。

Session 层 Compact 与 Promotion / Demotion

一旦任务变长,Working Memory 必然需要 promotion / demotion 机制:

  • 当前子任务、约束、待办和最近反馈保持在前台。
  • 已完成步骤被压缩成摘要或 checkpoint。
  • 细节证据退回长期记忆,只保留索引和引用。
  • 当子任务切换时,重新 promotion 新一批必要上下文。

这比简单的”截断旧消息”复杂得多。它更像是一个小型操作系统:前台保活,后台换出,需要时再换入。

Playbook 式 Delta Update

我很认同一个越来越清晰的方向:上下文维护不应只有压缩,还应有 delta update。 对于知识密集、长时间执行的任务,系统提示词或当前工作手册不应该被反复整体重写,而应该以 playbook 的形式增量演化:

  • 成功策略被沉淀为新的操作要点。
  • 失败原因被转化为约束或检查项。
  • 重复出现的模式被折叠成更稳定的规则。
  • 过时条目被 prune 或标记 stale。

这条路线并不意味着所有任务都要用富上下文。它的含义只是:当任务确实需要在线适应时,我们不能把 Context Engineering 只理解成摘要压缩。

上下文隔离策略

隔离和压缩同样重要。多智能体系统之所以常常更稳定,不只是因为能分工,还因为它天然提供了上下文边界:

  • Subagent 隔离:子智能体保留中间推理,主智能体只接收结果摘要。
  • Tool-call 隔离:工具执行日志进入工具工作区,而不是直接污染主会话。
  • Session 隔离:不同任务或不同用户的工作记忆默认不共享,只通过显式 memory object 交换。

很多所谓的”上下文污染”本质上不是压缩失败,而是隔离失败。

遗忘与治理

如果说检索是把信息带进来,遗忘就是把不该继续在场的信息移出去。对一个长期在线的 Agent 来说,遗忘并不是附属能力,而是和检索同等重要的主能力。

删除不等于物理抹除

工程上至少要区分几种不同动作:

  • 软删除:对当前检索不可见,但保留审计记录。
  • 硬删除:为隐私、合规或用户明确要求执行物理移除。
  • 降级:从 active 降到 stale,不再默认召回,但在追溯时可见。
  • 回滚:当更新错误时,恢复到上一个版本。

如果系统只有 append 和 overwrite 两种操作,它几乎不可能被真正部署到长周期、强约束的环境里。

冲突、时间与 Provenance

未来更像样的 memory store,几乎都必须原生支持这些治理字段:

  • 来源追踪:这条记忆来自用户明示、工具输出,还是模型推断。
  • 时间有效性:它从何时开始生效,是否已经过期。
  • 冲突标记:是否存在互相矛盾的候选记忆。
  • 不确定性:是否应在召回时主动 abstain。

Context Engineering 的困难并不只是”怎么让模型更聪明”,还包括”怎么让系统知道自己什么时候不该自信”。

我们准备怎么做

如果把上面的讨论压成一个可实现的工程方案,我现在更倾向于按下面五层落地:

  1. 统一记忆对象:先把 Persona、经验、语义知识、对话摘要统一成带 metadata 的 memory object,而不是直接堆原始文本。
  2. 混合检索层:让 grep、vector、LSP、graph 各自负责自己擅长的问题,再通过 rewrite + rerank 汇总候选。
  3. 写入管线:把抽取、分类、去重、merge、版本更新做成显式流程,先用规则 + LLM 判断,后续再尝试 learned policy。
  4. 上下文维护层:围绕 Working Memory 做预算管理、compact、promotion / demotion 和 playbook 式 delta update。
  5. 治理与评估层:补齐时间戳、来源、冲突标记、删除 / 回滚,并用写入正确性、更新正确性、调用及时性、行为一致性这些指标反向检查系统。

这里面最重要的一点是:我们不会把 Context Engineering 只做成一个检索外挂。 它必须同时覆盖读、写、更新、遗忘和审计,才能真正成为 Agent 框架内部的基础设施。

结论:Context 管理的核心矛盾与下一步

回头看,Context Engineering 一直在处理几组核心矛盾:

  • 丰富性 vs 高效性:信息越多,决策依据越充分;但注意力预算和调用成本会被迅速吃光。
  • 稳定性 vs 适应性:系统既要维护稳定规则,又要允许经验和用户状态持续演化。
  • 自动化 vs 可控性:开发者希望少写 memory plumbing,但又不能失去对写入、删除和调用行为的控制。

所以,Context Engineering 的重点从来不是单一技巧,而是把这些矛盾压进一个可治理的系统设计里。未来真正强的 Agent,不只是上下文更长的 Agent,而是知道什么该在场、什么该退场、什么该被写成长期记忆、什么该被删除,以及这些动作为什么发生的 Agent。