第八章 Context Engineering:工作记忆的精细管理

核心命题:Context 是 Harness 的”工作记忆”设计。在 token 预算约束下,在有限信道上最大化意图与行动之间的互信息——这是 Context Engineering 的工程目标。衡量这一目标的核心指标是上下文熵(Context Entropy):它刻画了当前 Context 中信息的分布状态,是 Compaction、分层、动态更新三类策略的统一评估基准。

与第六章的分工:第六章建立信息论理论框架(Rate-Distortion、信道容量、互信息、MDL 原则、信息不对称性);本章聚焦工程实践——如何将这些理论转化为可操作的 Context 策略。

8.1 Context 分层策略与淘汰机制

Rate-Distortion 理论指出最优有损压缩应保留信息量最高的内容(§6.1);§6.4 进一步揭示信息价值的极端不均衡分布(8% 的内容可能承载 60% 的信息价值),其结构性来源为语义层级、时间衰减、任务相关性三类不对称。Context 工程需将这些理论分析转化为按信息密度时效性的分层架构——层级越高,信息密度越高,抗淘汰性越强。

不同来源的信息,其信息密度排序为:

系统指令 > 当前任务规范 > 工具返回结果 > 历史对话摘要 > 原始历史记录

实际系统的 Context 由以下五个层次构成,每层有不同的更新频率和淘汰优先级:

层 0:系统指令(信息密度极高,不变,绝不淘汰)
层 1:任务规范(信息密度高,任务开始注入,任务内不淘汰)
层 2:工具返回结果(信息密度中等,每步更新,按相关性淘汰)
层 3:状态快照(信息密度视任务而定,按需刷新,超期后淘汰)
层 4:历史摘要(信息密度低,压缩后保留,token 上限前优先淘汰)

淘汰策略:接近 token 上限时,淘汰顺序从层 4 向层 0 逐级推进;同层内按时效性淘汰(最旧的先淘汰)。随机截断等价于忽视信息密度差异,在 Rate-Distortion 意义下是次优选择,应避免。

8.2 上下文熵与模型的“认知负荷”

上下文熵的定义

将 Context 窗口划分为 n 个信息单元 C = {c₁, c₂, …, cₙ},每个单元对当前任务的相关度权重为 rᵢ,归一化后得到概率分布 pᵢ = rᵢ / Σrⱼ。上下文熵定义为:

H(C) = -Σ pᵢ · log₂(pᵢ)

H(C) 的工程含义:

  • 高熵:信息均匀分散,Context 中无主导信号——模型难以聚焦,类似在噪声中检索。典型场景:将大量无关工具返回结果原样堆积。
  • 低熵(焦点集中):信息高度集中于少数单元——任务聚焦,但若压缩过度则丢失必要上下文。
  • 最优区间:中等熵值,且高相关单元的权重峰值显著——任务清晰、背景完整。

Compaction 的熵视角:Compaction 不是单纯的”截断”,而是一次熵塑形操作——目标是在缩减 token 总量的同时,降低 H(C) 并提升高相关单元的 pᵢ,即提高信噪比。

模型的“认知负荷”

LLM 并非对 Context 中所有位置等权注意。实证研究(“Lost in the Middle”,Liu et al. 2023)揭示了明显的位置偏差:模型对上下文头部(系统指令、任务描述)和尾部(最近交互)的注意力显著高于中间段。随着 Context 长度增加,这种 U 型注意力分布愈加明显。

这产生两类工程后果:

  1. 信息位置效应:关键约束若被埋入中间段,在长 Context 下实际权重大幅衰减。设计原则:不可忽略的信息放置在头部(层 0/1)或通过工具结果在尾部强化(层 2);历史摘要(层 4)若位于中间应视为”弱约束区”。

  2. 推理能力退化:随上下文长度增加,模型在多跳推理、长距离依赖等任务上的准确率系统性下降——有效注意力被稀释,推理链条中的中间变量更难被正确激活。

认知负荷指标:可将”有效认知窗口”估算为实际 token 数量的折扣版本——越靠近中部的信息,其有效权重越低。工程启示:即使 Context 预算充裕,也要警惕”无效填充”——堆砌低相关信息不仅消耗 token,还会通过提高 H(C) 与压缩有效注意力带宽,实质性损害推理质量。

8.3 动态更新机制

哪些状态需要实时刷新?哪些可以缓存?答案取决于状态的”改变频率”与”错误状态代价”的乘积。文件系统状态在每次写操作后必须刷新(改变频率高,错误代价高);系统配置通常可以缓存(改变频率低)。

状态表示在三个相互制约的维度上展开设计权衡:

维度设计问题错误选择的代价
完整性哪些信息是决策所必需的?缺少关键信息 → Agent 在错误假设下行动
新鲜度状态需要多频繁地重新采样?过期状态 → Agent 在已不存在的子空间中搜索
密度状态表示消耗多少 Context 带宽?过度冗余 → 有限信道上挤走更重要的信息

三个维度相互制约:提升完整性往往增加密度;追求高新鲜度会增加采样成本。最优设计点取决于任务的错误容忍度与 Context 预算。

实际 token budget 策略:一个生产系统的 Context 预算分配示例:

  • 系统指令:~2K token(固定)
  • 当前任务:~4K token
  • 工具结果:~8K token(动态)
  • 历史摘要:~8K token(压缩后)
  • 安全余量:~10K token

8.4 上下文腐烂(Context Rot)

Context 管理中最隐蔽的风险不是”Context 不够用”,而是”Context 在不知不觉中腐烂”。上下文腐烂(Context Rot)指的是:随着交互轮次的推进,Context 中已存在的信息逐渐失去准确性或相关性,但仍然占据 token 预算并影响模型的决策。与 token 耗尽不同,腐烂不会触发任何显式的系统警告——它是一种静默的质量退化

腐烂的三种机制

机制一:事实过期(Stale Facts)。Context 中记录的状态信息(文件内容、变量值、系统状态)在后续步骤中被外部操作改变,但 Context 中的旧记录未被更新。例如,Agent 在第 5 轮读取了文件 A 的内容,到第 20 轮时文件 A 已被修改,但 Context 中仍保留着第 5 轮的旧版本。模型基于过期事实做出的决策,可能导致覆盖他人修改、引用已删除的函数、或在已不存在的分支上操作。

机制二:目标漂移(Goal Drift)。在长对话中,用户的意图可能逐步演化——从”修复这个 bug”漂移到”顺便重构一下这个模块”。Context 中早期轮次的指令和约束仍然存在,但它们所锚定的目标已经不是当前目标。模型在两个不完全兼容的目标之间振荡,导致行为不一致。

机制三:矛盾积累(Contradiction Accumulation)。多轮交互中,用户可能修正了早期的指令(“不要用方案 A 了,改用方案 B”),但早期指令仍在 Context 中。当矛盾指令同时存在时,模型的行为取决于注意力权重的分配——在 Lost in the Middle 效应下,如果旧指令恰好位于高注意力区域(开头),而新修正位于中间段,模型可能”遵循”已被撤销的旧指令。

腐烂的信息论解释

在第六章的互信息框架下,Context Rot 可表述为:Context 与当前意图之间的互信息 I(意图;Context)I(\text{意图}; \text{Context}) 随时间单调递减——除非有主动刷新或清理介入。每轮新交互都可能改变意图或环境状态,而旧信息不会自动更新。当腐烂累积,Context 中的”信号”被”过期噪声”淹没,H(C)H(C) 上升,模型的有效认知带宽被浪费在处理已失效的信息上。

腐烂的检测与度量

理想状态下,系统应能检测 Context 中信息的”新鲜度”。实践中的近似方案包括:

  • 时间衰减标记:为 Context 中的每个信息块标注注入时间(轮次号),超过阈值的信息块被标记为”可能过期”,在下一次 Compaction 中优先处理。
  • 状态哈希校验:对于文件内容、环境状态等可校验的信息,在关键决策前重新采样并与 Context 中的记录比对。若不一致,触发更新。
  • 矛盾检测:当用户的新指令与 Context 中已有指令存在语义冲突时,显式标记旧指令为”已覆盖”,而非让两条指令共存。

Context Rot 的根本应对不是”更频繁地刷新一切”(这会大量消耗 token 与计算),而是将 Context 管理从被动累积转变为主动维护——这正是 §8.5(主动管理)与 §8.6(被动防御)要解决的工程问题。

8.5 主动管理:隔离、摘要和渐近式加载

主动管理的核心思路:在信息进入 Context 之前或进入瞬间,就控制其形态与体量,而非等 Context 膨胀后再被动压缩。§6.3 的 MDL 原则在此有直接应用:最好的 Context 在传递完整任务意图的同时使用尽可能少的 token。下面三种策略——隔离、摘要、渐近式加载——分别从不同维度逼近这一目标。

策略一:隔离(Isolation)——Sub-Agent 的信息屏障

隔离的本质是信息屏障:Sub-Agent 在独立 Context 空间中完成子任务,只将结论传回主 Agent。这等价于在信道上增加一层压缩编码器——Sub-Agent 内部可以消耗大量 token 进行探索,但返回值被压缩到主 Context 能承受的信息密度。

隔离设计的关键原则:

  • 单向信息流:主 Agent 向 Sub-Agent 传递任务描述(低 token),Sub-Agent 返回结论摘要(低 token);完整推理过程留在 Sub-Agent 内部,不污染主 Context。
  • 显式接口契约:Sub-Agent 返回结构应预先定义——哪些是必须摘要(总是注入),哪些是可选详情(按需拉取)。模糊接口会导致 Sub-Agent 返回大段原始输出,抵消隔离效果。
  • 失败信息优先传递:Sub-Agent 失败时,错误原因比成功结果更重要——主 Agent 需要这些信息决定重试策略。失败摘要应比成功摘要更详细。

策略二:摘要(Summarization)——有损压缩的主动执行

摘要是在 Compaction 被动触发之前,主动对低密度信息进行有损压缩——发生于信息进入或存续于 Context 的正常流程中,而非 token 预算告急时的应急操作。

摘要的时机选择:

  • 工具返回结果:多数工具(文件读取、搜索、API 调用)的原始输出远超任务所需。注入 Context 前应做任务导向摘要——保留与当前任务直接相关的信息,丢弃格式噪声与无关细节。
  • 对话轮次老化:一段对话距当前超过 N 轮且内容已被后续蕴含或更新时,将其从原始形式替换为摘要形式——直接对抗 §8.4 的事实过期与矛盾积累。
  • Few-shot 示例精简:示例信息密度递减——第一个示例的信息增量最大,后续示例的边际贡献递减。token 预算紧张时优先削减靠后的示例,或合并为覆盖更多模式的综合示例。

摘要质量的判断标准回到 §6.1 的失真度量原则:评估摘要质量的正确问题不是”token 减少了多少”,而是”摘要后模型输出的质量下降了多少”

策略三:渐近式加载(Progressive Loading)——按需注入而非预加载

渐近式加载的设计假设:任务开始时大部分信息尚未被需要;随任务推进,所需信息才逐步明确。因此不应在启动时一次性注入所有可能相关信息,而应建立按需拉取机制。

渐近式加载的实现模式:

  • 延迟注入:工具描述、API 文档等参考信息,仅在 Agent 明确需要时才注入,而非系统初始化时全量加载。对于拥有数十个工具的系统,这可在任务早期节省大量 token。
  • 分级详情:同一信息源提供多个粒度版本——概要(~50 token)、摘要(~200 token)、完整(~1000+ token)。初始注入概要,当模型行为表明需要更多细节(如输出不确定性增加、请求澄清)时逐级升级。
  • 检索驱动注入(RAG):背景知识库过大无法预加载时,通过检索动态选取每步最相关的片段。§6.4 已论证:检索的核心价值在于”在 token 预算约束下提高 Context 的平均信息密度”。

策略四:计划复述(Plan Recitation)——把目标推回近期注意力

前三种策略关注”信息进入 Context 的形态与体量”,计划复述关注一个正交的问题:已经存在于 Context 中的关键信息,如何避免随轮次推进被 §8.2 的 Lost in the Middle 效应吞噬

机制:将当前任务计划在每一步主动重写到 Context 末尾。典型实现是 Agent 维护一个可见的 todo 列表(如 Claude Code 的 TodoWrite,或 Manus 的 todo.md 文件),每一步开始前重读、结束后更新。

为何有效——这是 §8.2 注意力分布的直接对偶:

  • 任务计划若只在第 1 轮注入(Context 头部)且后续不再被提及,在第 N 轮时即使原文仍然存在,因 U 型注意力分布的中段塌陷,实际有效权重已大幅衰减;
  • 计划在末尾的反复重写使其始终位于”最近注意力区”——不是因为被复制了多次,而是因为最新副本始终位于尾部高注意力区,锚定模型对全局目标的注意。

这一机制与 ReAct 中”reasoning trace 作为不作用于环境的特殊 action”同源:思考与计划同样是写入 Context 的动作,值得被显式调度,而非被动留在历史中等待衰减。

工程权衡:

  • token 成本:每步重写 todo 占用 200–500 tokens,但相比因目标漂移导致的整轮重做或错误路径搜索,代价可忽略;
  • 必须 append-only:重写应是”追加新版本”而非”修改 Context 中段的旧版本”——后者会破坏 §8.7 的 KV-Cache 复用,为了缓解注意力衰减反而制造缓存失效;
  • 更新粒度匹配任务粒度:每步重写小任务列表是合理的;但若计划本身高频抖动(每步重新规划),说明 Plan 设计本身有问题,这属于第九章 Plan 的话题而非 Context 的话题。

四种策略覆盖前后两条战线:策略一至三管理”哪些信息进入 Context”,策略四管理”已进入的关键信息如何持续维持其在注意力中的权重”。它们共同构成对 Context Rot 的主动防线

8.6 被动防御:压缩

当 §8.5 的主动策略未能阻止 Context 膨胀时,系统需要一道被动防线——Compaction。它是在 token 预算即将耗尽时执行的系统性压缩操作,目标用第六章术语表达即:在 Rate-Distortion 曲线约束下,以最小信息损失换取最大 token 释放

触发时机

基本阈值为 token 使用率 > 70%(留有余量,避免关键步骤中断)。选择 70% 而非更高阈值的原因是:Compaction 本身需要消耗 token(将 Context 发送给模型摘要),若到 95% 才触发,可能连操作本身都无法完成。

触发条件也可以复合:

  • token 阈值:使用率 > 70%,最基本的触发条件
  • 轮次阈值:连续 N 轮未执行 Compaction,无论 token 使用率——这是对 Context Rot 的定时清理
  • 任务边界:Agent 切换子任务时主动触发——这是清理前一任务残余信息的天然时机

保留与淘汰的优先级

Compaction 的核心决策是”保留什么、淘汰什么”,直接映射到 §6.1 推论三(选择性保留优于随机截断)与 §6.4 的信息层级依赖模型:

必须保留(对应 §8.1 的层 0–1,信息密度极高):

  • 系统指令与角色设定——丢失后所有后续行为失去语义锚点
  • 当前活跃的 Plan 及未完成的步骤——丢失后 Agent 失去目标
  • 关键约束与规则——丢失后 Agent 可能违反安全边界

高优先级保留(对应层 2,信息密度高):

  • 最近 N 次工具调用的结果摘要——近期行动的直接上下文
  • 关键的失败记录与错误信息——避免重复犯错
  • 系统状态快照——当前环境的真实画像

可压缩为摘要(对应层 3–4,信息密度中等到低):

  • 早期对话轮次——保留结论,丢弃推理过程
  • 成功完成步骤的执行细节——保留”做了什么”,丢弃”怎么做的”
  • 重复出现的工具结果——仅保留最新一次

可直接淘汰(信息密度接近零):

  • 礼貌性寒暄与确认(“好的”,“明白了”)
  • 被后续指令明确覆盖的旧指令
  • 与当前任务完全无关的历史段落

Compaction 作为熵塑形操作

§8.2 已指出,Compaction 不是截断而是熵塑形——目标是在缩减 token 的同时降低 H(C)H(C)、提升高相关单元的权重占比。一次好的 Compaction 完成后,Context 应呈现清晰的”信号峰”:任务定义与近期上下文占据主导权重,背景噪声被大幅削减。

质量可通过事后检验评估:Compaction 前后,模型对同一问题(“你当前的任务是什么?已完成哪些步骤?下一步应该做什么?“)的回答是否一致? 若导致模型”遗忘”关键任务信息或错误重构任务理解,说明压缩失真方向不正确。

Compaction 的局限与风险

Compaction 本质是有损操作,风险不可完全消除:

  • 摘要引入的语义漂移:模型摘要时可能微妙改变原始信息含义——尤其是数值、条件、否定等精确语义。关键约束不应被摘要,而应原样保留。
  • 级联失真:每次 Compaction 都在前一次结果之上进行。多次后,早期信息可能经历”摘要的摘要的摘要”,累积失真显著偏离原始信息。
  • 不可逆性:一旦执行,原始 Context 不可恢复(除非维护快照)。高风险任务建议保存 Compaction 前快照以便回溯。

可逆压缩:对抗不可逆性的设计模式

不可逆性是上述三类风险中最难事后补救的——原文一旦被摘要替换便从 Context 中消失。除”维护快照”这种存储成本高昂的兜底外,存在一种更优雅的工程对策:让压缩本身成为可逆操作

核心是区分两类信息:

  • 可重建信息:工具结果中的文件正文、网页内容、API 返回的完整字段——可从外部源(路径、URL、查询语句)重新获取;
  • 不可重建标识符:文件路径、URL、查询语句、调用 ID——一旦丢失,通往原信息的指针即失效。

工程实现:每条工具调用记录维护 full 与 compact 两种格式。压缩时删除可重建字段,但 unique identifier 永远保留。模型如在后续步骤需要细节,可通过同一 identifier 重新读取,把内容拉回 Context:

压缩前(full):    Read(path="src/auth.py") → <8,000 tokens 完整源码>
压缩后(compact): Read(path="src/auth.py") → [content compacted, re-read by path if needed]

这一模式将 Compaction 从”不可逆有损操作”重塑为”惰性物化机制”——Context 中保留的是信息的指针,真正的内容在需要时按需拉回。它将 §8.5 的渐近式加载与 §8.6 的被动压缩在同一抽象下统一:两者都是”按需物化”在不同时点的表达——前者从未把内容拉进来,后者把内容退化为可重新拉取的指针。

适用前提:必须存在稳定的外部数据源。文件系统、HTTP 端点、数据库查询天然满足;一次性 LLM 输出、用户口头消息、不可重放的事件流则只能依赖传统摘要或快照保护——对这部分信息,§8.6 列出的摘要漂移与级联失真风险仍然适用。

可逆压缩同时对 §8.7 的 KV-Cache 友好设计有协同效应:compact 形态比 full 形态更短、更稳定,使前缀更长保持不变,间接提升缓存命中率。

Compaction 是 Context 管理的最后防线,而非常规手段。如果系统频繁触发,说明 §8.5 的主动管理设计不足——信息进入 Context 时未被充分压缩,或渐近式加载未有效执行。

8.7 KV-Cache 友好的 Context 设计

§8.1–§8.6 解决的是”Context 装什么”——在有限信道上最大化与意图的互信息。但 Context Engineering 还有一个被低估的运行时维度:Context 在推理引擎中如何被物理处理。其核心指标是 KV-Cache 命中率——生产环境 Agent 在 Q/T/C 三角中 T(首 token 延迟 TTFT)与 C(推理成本)两轴的共同杠杆。

Agent 与 Chatbot 在物理层的不对称

典型 Agent 遵循 Reason–Act–Observe 循环:每步接收当前 Context,从动作空间选择一个动作;动作执行产生观察后被追加到 Context 末尾形成下一步输入;输出通常是结构化函数调用,长度有限。这一模式使 Agent 与 Chatbot 在 prefill/decode 比例上呈现极端差异——典型生产系统中输入与输出的 token 比例可达 100:1。在这一比例下,每一步绝大多数算力都消耗在重新处理已经见过的 Context 前缀上。

KV-Cache 的数量级杠杆

具有相同前缀的 Context 可被推理引擎复用 KV-Cache,跳过该前缀的 prefill 计算。命中与未命中的成本差距是数量级的——以 Claude Sonnet 为例,缓存输入 token 价格约为非缓存价格的 1/10。换言之:每提升 10% 的 cache 命中率,整体推理成本下降幅度远超 10%——因为 Agent 工作流中前缀 token 占比本就极高。

KV-Cache 命中率因此不是”锦上添花的优化项”,而是 Context 设计的一阶约束。即便 §8.1–§8.6 在内容层面优化得再充分,破坏缓存复用的设计仍会使运行时成本与延迟线性放大。

三条工程原则

KV-Cache 的物理特性决定:LLM 自回归性质下,token nn 的 KV 依赖于 token 00n1n-1;前缀任何位置的差异都会使该位置之后的缓存全部失效。三条工程原则由此推导。

原则一:保持前缀稳定(Prefix Stability)

System Prompt 的开头是缓存命中率的最高杠杆点——此处任何 token 差异会使整个 Context 的缓存全部作废。常见反模式:

  • System Prompt 开头嵌入精确到秒的时间戳——每次调用前缀均不同,命中率归零;
  • 在系统级文本中拼接随机 ID 或 trace ID;
  • 工具列表、角色描述在不同请求间微调措辞。

对应实践:精确时间戳若必须存在应置于 Context 末尾而非开头;高频变动的元数据通过日志系统携带而非进入 Context;System Prompt 一旦稳定不应频繁微调。

原则二:上下文只追加(Append-Only Context)

修改 Context 中已有内容(更正过去工具返回、合并历史记录)会使该位置之后的所有缓存失效。这对 §8.5 主动管理提出额外约束:摘要、修正、清理操作应集中在 Compaction 这样的明确边界点执行,而非在每一步散点修改。

序列化的确定性同样关键——多数语言/库的 JSON 序列化不保证键顺序稳定。语义相同但 token 序列不同的工具结果会静默破坏缓存复用。工程实践:所有进入 Context 的结构化数据使用确定性序列化(键按字典序排列、浮点数固定精度、时间统一为 ISO 8601 等)。

原则三:显式标记缓存断点(Explicit Cache Breakpoints)

部分推理框架(包括某些 vLLM 配置与 API 提供商)不支持完全自动的增量前缀缓存,需在 Context 中显式插入缓存断点。在这种环境下:

  • 至少在 System Prompt 结尾设置断点——稳定性最高的边界;
  • 任务级稳定信息(层 0–1)与动态信息(层 2 及以下)之间设置断点;
  • 自托管分布式推理(如 vLLM 集群)需通过会话级 affinity 路由,确保同一对话的连续请求落到同一 worker 节点,否则缓存仅在单节点本地有效。

与分层架构的耦合

KV-Cache 的物理约束与 §8.1 的五层信息架构高度同构——这不是巧合:

层级信息密度(§8.1)缓存稳定性
层 0:系统指令极高全局稳定,断点之前
层 1:任务规范任务内稳定,可作为二级断点
层 2:工具结果中等追加式增长,断点之后
层 3–4:状态 / 摘要中–低动态变化,缓存复用价值低

这意味着 §8.1 推导的分层架构在运行时维度同样最优——信息密度的层级分布与缓存稳定性的层级分布天然对齐。设计良好的 Context 在内容工程与运行时工程两个维度同时收敛。

反之,违反分层的设计——在系统指令中嵌入易变信息、或在历史段落中插入本应稳定的约束——会同时损害两个维度:信息密度被稀释,缓存命中率被破坏。

KV-Cache 命中率是 Context Engineering 在 Q/T/C 三角中 T 与 C 两轴的具象指标。一个 Context 设计若在信息论意义上最优却破坏缓存复用,其生产环境总成本仍可能数倍于一个略有冗余但缓存友好的设计。

8.8 跨越 Session:从 Context 到 Memory

§8.4–§8.6 的所有策略——检测腐烂、主动管理、被动压缩——都在解决同一个问题:如何在单个 Context 窗口生命周期内维护信息质量。但 Context 窗口有一个比 token 上限更根本的局限:它随 session 结束而消亡。无论窗口内管理多精细,新 session 开启时一切归零。

如果说 Context Rot 是 session 内的渐进退化,session 边界则是彻底的信息断崖——不是腐烂,而是遗忘。

约束的时空坐标系

理解这个局限需要将”约束”从 Context 窗口中抽象出来。Harness 系统中的约束可以沿两个独立维度刻画:

  • 作用范围(Scope):该约束影响的是特定任务,还是跨任务的全局行为?
  • 作用周期(Period):该约束在当前会话内有效,还是需要跨 session 持久存在?

两个维度构成一个坐标系:

           短周期(Session 内)     长周期(跨 Session)
窄范围     In-context 指令          持久化规则(如 AGENTS.md)
宽范围     System Prompt            Memory / 用户画像

§8.1–§8.6 处理的全部是左列——无论是层 0 系统指令还是层 4 历史摘要,都随 session 结束消失。右列的需求——跨 session 的个性化约束、用户偏好、项目状态、已建立的约定——无法在同一上下文窗口中维护。这正是 Memory 出现的根本动机。

Memory 的信息论定位

用第六章框架来理解:Memory 的作用是在 session 边界处保存互信息。一段长对话结束时,Context 中积累了大量关于用户意图、项目状态、行为偏好的信息,与未来任务之间存在非零互信息。不外化则被丢弃;选择性持久化后可在下一次 session 启动时重新注入 Context,等价于”信息热启动”。

但 Memory 不是 Context 的简单延伸——它是一种跨时间的有损压缩。与 Compaction 的类比是精确的:

维度CompactionMemory
压缩时机session 内,token 逼近上限session 结束时,信息即将消亡
压缩对象当前 Context 的低密度部分整个 session 中值得跨期保留的信息
失真来源摘要引入的语义漂移时间推移导致的事实过期
不可逆性原始 Context 不可恢复原始 session 不可重放

两者的核心区别在于失真的主导来源:Compaction 的失真源自压缩操作本身(§8.6 的语义漂移);Memory 的失真主要来自时间——即使写入时完全准确,随时间推移记录的状态可能已不再成立。

Memory 的两个结构性挑战

挑战一:选择性——什么值得记住?

并非所有 Context 中的信息都值得跨 session 保留。§6.3 的 MDL 原则在此有直接应用:值得持久化的信息,是无法从其他持久化来源(代码库、git 历史、文档)重新推导出的信息。用户行为偏好(“这个用户不喜欢过度解释”)、项目非显式约定(“这个模块的测试覆盖率目标是 90%”)、已验证的工作模式(“对这个用户,单个大 PR 比多个小 PR 更合适”)——这些信息 Kolmogorov 复杂度低(少量 token 即可表达),信息密度极高(难以从代码推断),是 Memory 的理想候选。

相反,代码的具体实现细节、文件路径、函数签名——虽在当前 session 中重要,但可通过读取代码库重新获取,不需要 Memory 承载。Memory 的 token 预算(注入新 session 时同样消耗 token)应像 Context 一样被精心管理,而非无限制追加。

挑战二:时效性——记忆何时过期?

每条 Memory 都隐含一个时间戳——记录的是”彼时的状态”。越持久的记忆,越可能与当前现实产生漂移。这种漂移与 §8.4 的 Context Rot 具有相同的信息论结构:Memory 与当前意图之间的互信息随时间递减。但跨 session 的漂移更难检测——系统没有连续的对话流来发现矛盾,只能在读取时校验。

工程应对策略:

  • 读取时校验:Memory 读取不应盲目注入,而应伴随有效性检查。文件路径或函数名先验证是否存在;项目状态先检查最近的 git 历史。
  • 置信度衰减:为 Memory 附加写入时间,读取时按时间间隔降低置信权重——一周前的偏好记忆可高度信任;三个月前的项目状态需谨慎对待。
  • 主动清理:定期审查 Memory 库,移除过期或已被覆盖的条目——这是 Compaction 在时间维度上的延伸。

Memory 是 Context 的”时间维度延伸”——它将约束的作用周期从单 session 扩展到用户生命周期,代价是引入了时效性维护的复杂度。


章末案例剖析

同一个长时运行的调试任务,两种 Context 管理策略——被动累积与主动维护——在相同 token 预算下走向截然不同的结局。差距不在于 Agent 的推理能力,而在于 Harness 是否将本章的分层架构、主动摘要与 Compaction 策略落地为实际工程机制。

任务设定:批量任务调度系统在生产环境出现约 3% 的任务静默丢失——任务被标记为”已领取”但实际未执行,且无任何报错日志。系统由 4 个微服务组成,部署在 12 个节点上。Agent 被要求定位根因并输出可验证的修复方案。

可用材料:

材料规模
3 个服务的生产日志文件各约 8,000 tokens,合计 24,000 tokens
15 个源码文件平均每文件约 2,000 tokens,合计 30,000 tokens
12 轮历史调试记录约 9,600 tokens
系统架构说明文档约 3,000 tokens
合计可用材料约 66,600 tokens

Context 窗口上限:32,000 tokens。目标 G\mathcal{G}:精确到代码层面的根因报告 + 可验证的修复方案。


策略 A:被动累积

初始化阶段(轮次 1–2)

Harness 将所有”可能相关”材料一次性注入 Context:

组件Token 数
系统提示(角色 + 任务描述)2,100
日志文件 A、B、C(全文)24,000
历史调试记录(12 轮)9,600
注入总量35,700(超出上限)

35,700 tokens 超过 32K 窗口上限。系统在截断历史记录末端(轮次 10–12,约 2,400 tokens)后强制开始。

第 1 轮 Context 状态诊断

历史记录轮次 10–12 被截断——这正是此前调试会话中记录”已排除假设”的部分(排除了网络分区和节点崩溃两类假设),丢失导致后续 Agent 可能重走已排除路径。日志原文 24,000 tokens 中,与任务丢失直接相关的片段仅占约 15%(约 3,600 tokens),其余 85% 是正常请求记录。上下文熵 H(C) 极高——大量低相关内容均匀分散,无任何信号峰值。

推理阶段(轮次 3–12)

Agent 逐步加载源码文件(每轮 2–3 个,每次 4,000–6,000 tokens),Harness 将最旧的对话轮次移出 Context 以维持 32K 上限。

第 6 轮:被动 Compaction 触发(使用率 74%)

此时 Agent 刚加载了 job_dispatcher.pyworker_pool.py——调度逻辑的核心文件,合计约 3,800 tokens,位于 Context 末尾 30% 区域。被动 Compaction 对末尾 30% 均匀摘要,将 3,800 tokens 压缩为 550 tokens;关键的双重检查锁实现(第 847–863 行的非原子”先查后写”操作序列)被描述为”包含并发控制逻辑”——精确语义丢失。

Context Rot 的累积

机制一(事实过期):日志文件 A 第 1 轮注入,记录 48 小时前的数据库连接超时。第 9 轮 Agent 已通过工具确认该问题被 DBA 独立修复,与任务丢失无关,但旧日志仍占 8,000 tokens 并持续暗示数据库方向。

机制三(矛盾积累):第 5 轮假设”数据库超时导致状态写入失败”;第 11 轮在新证据下提出替代假设”Worker 节点并发领取导致重复消费”。两假设并存——由于”数据库超时”分析位于 Context 前段(高注意力区),Agent 在两方向间持续振荡。

失败轨迹(轮次 13–25)

  • 第 13–16 轮:Agent 沿数据库假设继续搜索,调用数据库分析工具(每次约 1,500 tokens 返回),未发现根因
  • 第 17 轮:再次触达 70% 阈值,第二次被动 Compaction。Worker 并发假设的 600 tokens 分析记录被压缩为 80 tokens:“Worker 并发假设:待验证”——推理依据完全丢失
  • 第 18–22 轮:Agent 重新审查 Worker 方向,但 job_dispatcher.py 详细内容已在首次 Compaction 中失真,不得不重新加载(重复消耗),加载后 H(C) 进一步升高
  • 第 23–25 轮:token 预算接近耗尽,关键文件已历经两次语义漂移的摘要,精确细节无法从”包含并发控制逻辑”重建

结果:25 轮后任务失败。Context 峰值使用率 92%(两次 Compaction 后仍迅速回升),根因未定位。


策略 B:主动 Context 管理

第一步:分层初始化

按 §8.1 五层架构建立保护等级,工具调用前完成层级声明:

层 0(固定,绝不淘汰):系统指令 + 角色定义          → 2,100 tokens
层 1(任务内不淘汰):任务描述 + 已知症状 + 根因假设框架 → 800 tokens
层 2(按相关性管理):工具返回结果(当前活跃)          → 动态
层 3(超期后压缩):当前假设的支撑证据                 → 动态
层 4(已关闭假设的摘要):关闭假设的结论摘要             → 动态

历史调试记录(12 轮,9,600 tokens)不直接注入——交给 Sub-Agent 在独立 Context 中摘要,返回关键结论列表(420 tokens),注入层 4。其中”已排除:网络分区、节点崩溃”等关键约束完整保留。

第二步:Sub-Agent 隔离日志分析(轮次 1–3)

为三份日志各启动一个 Sub-Agent(各自使用约 12,000–14,000 tokens 进行深度分析),向主 Agent 返回结构化摘要:

  • 日志 A 摘要(290 tokens):“数据库连接超时集中于 48 小时前 23:00–01:00,已由 DBA 确认为独立问题,与任务丢失时间窗口无重叠”
  • 日志 B 摘要(320 tokens):“发现 23 条 Job ID 重复声明记录——同一 Job 在不同 Worker 节点被标记为’已领取’,两次声明时间差均 < 50ms,疑为并发竞争” ← 关键线索,完整保留于层 2
  • 日志 C 摘要(285 tokens):“Worker 节点心跳记录正常,无异常退出,排除节点崩溃假设”

第 3 轮结束主 Context 状态:层 0–1(2,900 tokens)+ 日志摘要(895 tokens)+ 历史调试摘要(420 tokens)= 4,215 tokens(使用率 13.2%)。日志 B 的关键线索被精炼到 320 tokens 置于末尾(高注意力区),H(C) 处于最优区间。

第三步:假设驱动的渐近式加载(轮次 4–8)

基于日志 B 的”< 50ms 重复声明”线索,并发竞争成为最高优先级假设,按需拉取:

  • 第 4 轮:仅加载 job_dispatcher.py 函数签名版(~220 tokens),确认其包含 claim_job() 领取逻辑
  • 第 5 轮:加载 job_dispatcher.py 完整版(~1,800 tokens),识别第 847–863 行:claim_job() 使用非原子的”先查后写”——读取 job.status == 'pending' 与写入 job.status = 'claimed' 之间存在时间窗口,日志 B 中的 < 50ms 重复声明与此精确对应
  • 第 6 轮:加载 worker_pool.py 完整版(~1,600 tokens),确认两个 Worker 实例可同时通过 pending 检查

第 6 轮 Context 状态:

层 0–1:2,900 tokens(受保护)
层 2:两个关键文件(3,400 tokens)
层 3:日志摘要(895 tokens)
层 4:历史摘要(420 tokens)
合计:7,615 tokens(使用率 23.8%,未触发 Compaction)

第 7 轮:根因确认——claim_job() 第 847–863 行非原子操作序列。修复方案:将操作替换为数据库层的原子 CAS(Compare-And-Swap)原语。

第 8 轮:本地并发测试验证修复有效,G\mathcal{G} 满足。全程未触发 Compaction,Context 峰值使用率 38%。


两种策略的量化对比

维度策略 A(被动累积)策略 B(主动管理)
第 1 轮 Context 大小35,700 tokens(溢出截断)4,215 tokens
第 1 轮上下文熵 H(C)极高(24,000 tokens 日志原文均匀分散)低(关键摘要集中,信号峰值清晰)
关键线索(日志 B 并发记录)状态淹没于 8,000 tokens 日志原文的中段320 tokens 精确摘要置于 Context 末尾
Compaction 次数2 次(被动触发,失真方向不可控)0 次
关键代码文件(job_dispatcher.py)状态第一次 Compaction 中压缩为”包含并发控制逻辑”完整保留,精确定位第 847–863 行
Context Rot事实过期(旧 DB 日志)+ 矛盾积累(双假设共存)无(Sub-Agent 摘要在注入前已消除噪声)
Context 峰值使用率92%(两次 Compaction 后仍迅速回升)38%(全程未触发 Compaction)
总轮次25 轮(失败)8 轮(成功,含 3 轮 Sub-Agent)
任务完成否(根因未定位)
KV-Cache 命中模式(§8.7)两次 Compaction 改写中段 Context,断点之后缓存全部失效;旧日志被淘汰、关键文件被重新加载,前缀反复重建——多数轮次以低命中率运行主 Context 严格 append-only,前缀(层 0–1 共 2,900 tokens)跨 8 轮全程稳定;每个 Sub-Agent 在其内部 Context 上同样保持前缀稳定
计划复述 / 注意力锚定(§8.5 策略四)无显式 todo 维护;任务计划仅在第 1 轮注入头部,25 轮内未重写——叠加 U 型注意力衰减后,新假设位于中段低权重区,旧假设位于高权重区,加剧矛盾积累与振荡三步流程(分层初始化 / Sub-Agent 隔离 / 假设驱动加载)的每一步都在 Context 末尾刷新”当前最优假设”,假设链本身充当隐式 plan anchor——目标始终位于高注意力区,未发生振荡
压缩可逆性(§8.6 可逆压缩)关键文件被压缩为”包含并发控制逻辑”——既丢失内容也丢失指针,第 18–22 轮重新审查 Worker 方向时只能从头加载,重复消耗 token 且前缀缓存全部作废工具结果天然以 path/URL 为指针,Sub-Agent 摘要完整保留所有 unique identifier;job_dispatcher.py 经”签名版 → 完整版”分级加载,原始内容始终可按路径重读,Compaction 与渐近式加载在同一指针抽象下统一

策略 B 中三个 Sub-Agent 各使用约 12,000–14,000 tokens 内部分析,总计约 38,000 tokens;加上主 Agent 的 8 轮 × 平均约 6,500 tokens = 约 52,000 tokens,整体输入 token 量约为策略 A 的 35%。若进一步代入 KV-Cache 折算(§8.7:缓存 token 价格约为非缓存的 1/10):策略 A 因频繁前缀重建,估计仅约 25% 的输入 token 命中缓存;策略 B 主 Agent 前缀全程稳定,估计约 75% 命中。按 Claude Sonnet 价位计算,策略 B 的实际推理成本约为策略 A 的 15%–20%——优势从”信息密度”扩展到”运行时经济性”两条独立轴。


理论工具的工程落点

理论工具在本案例中的具体作用
五层分层架构(§8.1)层 0–1 全程受保护,不参与任何 Compaction;日志摘要落入层 3;已关闭假设的结论落入层 4,对应淘汰优先级
上下文熵 H(C)(§8.2)策略 A 第 1 轮 H(C) 极高(24,000 tokens 日志原文均匀分布);策略 B 三份精准摘要在 895 tokens 内集中承载关键信号,模型有效认知带宽全部用于推理而非过滤噪声
Context Rot(§8.4)策略 A 同时出现事实过期(旧 DB 日志持续干扰)与矛盾积累(双假设共存,旧假设位于高注意力区);策略 B 通过 Sub-Agent 摘要在入境时消除噪声,矛盾从未进入主 Context
主动管理(§8.5)隔离:三份日志各 8,000 tokens 的内部探索不污染主 Context;渐近式加载:函数签名版先行,并发假设确立后才加载完整源码;历史记录摘要在初始化时以 Sub-Agent 完成,关键约束完整保留
Compaction(§8.6)策略 A 的两次被动 Compaction 缺乏分层感知,均将关键文件压缩至语义漂移;策略 B 将 Context 维持在 38% 以下,从未触及 70% 阈值——Compaction 作为最后防线,前端主动管理到位时本不需要出现
Lost in the Middle(§8.2)策略 A 中日志 B 的关键线索位于原文中段(Context 的 45%–55%),处于 U 型注意力低谷;策略 B 将精确摘要置于末尾,始终处于高注意力区
KV-Cache 友好设计(§8.7)策略 A 违反”上下文只追加”原则——两次中段 Compaction 与重新加载使前缀缓存反复作废;策略 B 主 Context 严格遵循 append-only,前缀稳定在层 0–1,恰好对应 §8.7 推荐的”高稳定性置于断点之前”模式,缓存命中率与信息密度两条曲线同向收敛
计划复述(§8.5 策略四)策略 A 缺失此机制:早期假设位于头部高注意力区,新假设在中段低权重区,缺乏”将当前活跃假设持续推回末尾”的设计,矛盾积累与振荡正是 Lost in the Middle 在缺少 anchor 时的必然结果;策略 B 的”假设驱动渐近式加载”在每轮 Context 末尾都刻入当前最优假设,等价于隐式 plan recitation——若进一步显式维护 todo 列表,效果可在更长任务中放大
可逆压缩(§8.6)策略 A 的两次 Compaction 把关键源码摘要为”包含并发控制逻辑”——既无指针也无可重建路径,是不可逆压缩的典型反例(信息与指针同时丢失);策略 B 的层 2 工具结果天然以 path/URL 为指针,Sub-Agent 摘要保留所有 unique identifier,使后续轮次可按需重读完整内容——Compaction 退化为”惰性物化机制”,与渐近式加载在抽象上同构

核心工程结论:Context 管理的目标不是”让模型看到尽量多的信息”,而是始终维持 H(C) 的最优区间——高相关信息占据主导权重,低密度噪声在进入 Context 之前就被主动清除。策略 A 的失败根源不是信息量不足(实际上信息过剩),而是低密度原文日志侵占了高价值信号的注意力带宽,并在被动 Compaction 的随机失真中逐步损毁了根因定位所需的精确语义;同时,Compaction 对中段 Context 的反复改写还破坏了 KV-Cache 的前缀复用,使运行时成本独立于内容质量进一步恶化。策略 B 以 Sub-Agent 隔离 + 渐近式加载 + 分层保护,将同样的 token 预算集中在驱动推理收敛的关键信号上,并自然形成 append-only 的前缀稳定结构——这是 §8.2 认知负荷管理、§8.5 主动管理与 §8.7 KV-Cache 友好设计的三重联合体现:信息密度的层级分布与缓存稳定性的层级分布在良好设计下天然同构