上下文管理
运行时的纪律 — 注意力预算、压缩谱系、即时上下文加载、渐进式披露,以及把子 Agent 本身作为上下文工程手段
运行时问题
提示词设计定住了静态骨架。记忆设计决定了窗口之外留什么。压缩处理窗口还是溢出时的那一刻。上下文管理是围绕这些的所有事 — 运行时的纪律:一轮一轮地决定此刻窗口里应该有什么 —— 哪些输入该载入、哪些该修剪、何时该委托、怎么恢复、怎么察觉出事了。
难在正确答案一直在变:
- 第 3 轮相关的工具结果,在第 30 轮就是噪音。
- Agent 刚编辑过的文件,在第 10 轮至关重要,第 20 轮就该忘。
- 子 Agent 的完整 trace 在它运行时有意义,回传摘要的那一刻就变成了杂物。
好的上下文管理器在解一个序贯决策问题:给定当前窗口状态,下次模型调用之前该保留、修剪、加载、摘要什么?把这件事做对,就是”100 轮保持连贯”的 Agent 和”15 轮就跑偏”的 Agent 的分野。
注意力预算
把上下文窗口当成有软上限的预算,不是硬极限。上限不是由模型标称的上下文长度决定,而是由可测量的质量开始下降的那个点决定 — 通常远低于标称最大值。
一条可用规则:
定义一个水位线(watermark) — 大约是可用上下文的 40-60%。窗口越过水位,上下文管理器行动;水位之下,什么都不做。
为什么是水位而不是每轮都压:
- 压缩有代价(用 LLM 就花 token、用简单截断就花信息)。稀疏使用便宜,每轮使用浪费。
- 最便宜的上下文操作是不操作。别为 Agent 还不需要的管理付费。
- 有些任务压根没到水位就完事了 — 它们的”最优压缩”是零。
预算也不只是窗口。还包括:
- Token 成本 — 缓存命中比写入便宜 10×,保持稳定前缀完整有真实的美元价值。
- 延迟 — 每次调用 LLM 的压缩都是用户要等的往返。
- 质量 — 任何有损操作都是一个赌注:赌掉的比留下的不值钱。
压缩在这里的角色
水位被越过时,运行时的答案就是压缩 —— 这个操作在 上一页 已经详讲过。本页不重教它,而是覆盖运行时为了让压缩不必那么频繁触发所做的所有其他事 —— 懒加载(JIT)、隔离子 Agent 工作、checkpoint 持久状态、提早抓住失败模式。
压缩是最后手段。接下来的技术都是为了”不要走到最后手段”。
即时上下文 (Just-in-Time Context)
与其预加载所有可能相关的东西,设计良好的 Agent 维护轻量级标识符,按需加载内容。
Agent 维护轻量级标识符(文件路径、存储的查询、URL),在运行时用工具动态加载数据到上下文。 — Effective Context Engineering for AI Agents
这映射了人的工作方式。你不背整个代码库 — 你记得去哪查。好的 Agent 持有指针,不是负载。
例子:
- 任务开始时不调
read_file("large_config.json"),而是先通过glob发现路径,确实需要时才读。 - 不把历史对话全部 dump 出来,Agent 的记忆索引里只列出标题;只为相关条目取内容。
- 不读模块里的每个文件,Agent
grep出符号,只读匹配项。
为 JIT 设计的工具
JIT 要奏效,工具必须先返回元信息、再返回内容:
glob返回路径、大小、时间戳 — 不返回内容grep流式返回匹配行 — 不返回整个文件read_file接受 offset 和 limit — 不是”全读”search返回排序过的片段 — 不是完整文档
不能分级返回(每次都返回整坨)的工具,会把 Agent 逼向”要么预加载、要么昂贵压缩”。设计工具时问:“常见情况下,Agent 仅凭元信息就能行动吗?” 能的话,先返回元信息、让 Agent 自己钻下去。
渐进式披露 (Progressive Disclosure)
好的 JIT 工具设计自然带来渐进式披露:Agent 逐层构建理解,只在决策需要细节时才拉取。
- 文件大小暗示复杂度
- 命名规范暗示用途
- 时间戳暗示相关性
- 目录结构暗示架构
每一层,Agent 决定继续下钻还是转向。上下文保持小,是因为大多数分支根本没被探索。
混合策略
纯 JIT 不现实,因为总有些上下文值得常载入。纯 JIT 的 Agent 每次任务都要重新发现项目约定一次。通常的甜蜜点是混合:
- 预计算检索用于已知重要的上下文 — 启动时载入的
CLAUDE.md或项目简报。小、稳、永远相关。 - 自主探索通过工具 — 其余一切,按需加载。
预载入那部分必须小且真正通用。一份文档如果只对 20% 的任务相关,它属于 JIT 层,不属于常载入层。
子 Agent 作为上下文工具
委托常被当成编排模式讲。更准确地说,它首先是一种上下文工程技术。
子 Agent 跑在干净的上下文窗口里。它收一个委托 prompt、执行工作(可能几十次自己的工具调用),然后返回一个精炼结果 — 通常 1-2k token。父 Agent 的窗口只看到委托和摘要;子 Agent 的中间 trace 从不进入父上下文。
这件事很重要,因为跑长内部循环的 Agent — 搜索、提取、点击、再搜索、再提取 — 产生大量中间上下文,对它自己有意义但对父 Agent 是噪音。把那条 trace 挡在父窗口之外,保住父的注意力给真正需要它判断的任务。
什么时候该委托:
- 深度、聚焦的探索 — “在代码库里找到所有 X 的引用”生成大量父 Agent 永远不会重读的文件读取
- 有本地状态的多步循环 — 浏览器导航、数据库探索、迭代搜索
- 可并行的工作 — 扇出到多项,每个结果都独立有用
设计委托
子 Agent 的结果质量几乎完全由委托 prompt 的质量决定。好的委托 prompt:
- 说明目标,不是流程(“找到处理 X 的那个函数” — 不是”先 grep Y 再读 Z”)
- 指定回传契约 — 形态、长度、要包含什么
- 列出已知约束 — “不改文件”、“预算 10 次工具调用”、“找到第一个就停”
- 提供子 Agent 无法推导的上下文 — 相关文件路径、要试的假设
坏的委托 prompt卸载了思考却没框住问题。子 Agent 乱撞、回传一个 dump、父要重读来提炼答案 — 把节省全抹平。
委托的成本
子 Agent 不免费:
- 委托 prompt 要在父轮次之外付费
- 子 Agent 自己的工具调用要计费
- 协调(子 Agent 真的理解任务了吗)增加延迟
当节省下来的上下文价值超过多付的 token 时才委托。粗糙经验:几步的任务直接做更便宜;几十步、输出狭窄定义的任务几乎总是委托更便宜。平衡点取决于模型价格、缓存命中率、以及子 Agent 的工作本来会多大程度污染父窗口 — 先量再下默认值。
Checkpoint 与可恢复性
长时 Agent 跨越的不止一次连续会话。用户可能关闭标签页、连接可能掉线、进程可能崩溃。上下文管理器必须让恢复的代价低 — 理想情况下是 O(摘要大小),不是 O(完整历史)。
关键洞察:完整对话历史从来不是恢复真正需要的东西。真正需要的,是上一个一致 checkpoint 的状态:压缩摘要、工作文件集、待办 todo。这份状态比原始历史小得多。
一份可用的 checkpoint 形态:
| 元素 | 为什么需要 |
|---|---|
| 压缩摘要 | 替代已被摘要的那部分历史 |
| 未压缩尾部 | 最近 N 轮原样保留 |
| 开放的 todo | Agent 正在做什么 |
| 工作文件集 | 当前任务的文件范围(路径,不是内容) |
| 记忆索引 | 可召回的持久记忆的标题 |
恢复的含义是:载入 checkpoint、从中重建上下文、继续。用户感知不到任何不连续,因为所有本质信息都在 — 即便原始消息历史从未被重放。
这个机制和压缩互动:压缩执行时也应该更新 checkpoint,这样恢复永远不需要从零重建压缩状态。把 checkpoint + 压缩状态视为”Agent 在哪”的持久描述,把消息历史视为在其之上的 append-only 日志。
失败模式
运行时问题 —— 即便 prompt 和 memory 都设计得好,上下文管理循环本身也会出岔子。对应的设计时反模式见 提示词设计 和 记忆设计 各自的”反模式”小节。
| 失败模式 | 信号 | 修复 |
|---|---|---|
| 上下文膨胀 | 窗口过 70%,Agent 开始漏掉早期决策 | 提前水位线;后期轮用更轻的压缩技术 |
| 压过头 | 压缩事件后 Agent 问”我刚在做什么” | 多保留近期轮;原样保留文件编辑状态 |
| 骨架漂移 (Skeleton drift) | 系统提示词随规则堆积长到 15k token | 审计骨架;把少用内容挪到 JIT 层 |
| 子 Agent 上下文泄漏 | 子 Agent 返回完整 trace 而不是摘要 | 收紧回传契约;更短的委托 prompt |
| JIT 颠簸 | 同一文件一轮内重读 5 次 | 保一个本轮已取缓存,用标识符引用 |
| 过期 checkpoint | 恢复后 Agent 落在一个已与现实不符的状态(文件变了) | 恢复时校验文件哈希;过期就重读 |
策略组合
没有单一技术能独自处理长时上下文。设计良好的系统在每个技术最擅长的地方用它:
| 策略 | 最擅长 | 配搭 |
|---|---|---|
| 工具清除 | Agent 已处理的常规大工具输出 | 所有其他技术 — 它是基线 |
| 压缩 | 有自然轮次边界的长来回对话 | 结构化笔记,这样关键信息不会丢 |
| 结构化笔记 | 有清晰里程碑、跨会话需要恢复的迭代开发 | 压缩,这样笔记活下来 |
| 子 Agent | 中间 trace 对父是噪音的深度聚焦工作 | 记忆,这样子 Agent 的习得持久 |
| JIT 加载 | Agent 很少需要的大型参考资料 | 好的工具设计 |
这些策略组合:压缩处理对话历史、结构化笔记处理跨会话状态、子 Agent 处理深入研究、JIT 处理多数文件读取、工具清除作为常开的卫生 — 每个用在最有效的地方,注意力预算是共同的货币。
底层纪律
这页讲的每一个技术 — 压缩、JIT、子 Agent、checkpoint — 都是一个纪律的实例:
让窗口里填着、且只填着、Agent 此刻需要做的事。
这是 overview 的指导原则 在运行时维度的专属翻译:overview 问的是”哪些 token”,这页问的是”本轮该进哪些、哪些该让位”。同一个想法,不同的轴。你写一次的 prompt,运行时每一轮都会被重新解读 —— 上下文管理就是那套重新解读的纪律。
不是它可能需要的。不是它以前需要的。不是”以防万一”的安全网。窗口越贴近这个目标,Agent 表现越好;越偏离,劣化越早。
上下文管理是决定静态骨架(提示词设计)和持久存储(记忆设计)能不能兑现的那根支柱。好的提示词和好的记忆是必要的,却不是充分的。在运行时没有持续把对的 token 在对的时间送到位之前,Agent 的测量表现会远远不及同样提示词和记忆本应达到的水平。
如何度量 (Measuring It)
上下文管理每轮指标和每任务指标都要看:
- 上下文占用率 —— 跟踪任务生命周期里的窗口充满度。贴近水位线的平线是健康的;越过水位再被压缩砸下去的锯齿说明水位设得太高。
- 压缩触发频率 —— 每 100 轮每层各触发几次?重型摘要频繁触发 = 前面几层没干够活。
- 缓存命中率 —— 缓存感知排序是否起作用的直读指标。稳定任务上瞄准 80%+。
- 从 Checkpoint 恢复的成功率 —— 对可恢复 Agent,多大比例的恢复落在可用状态?低于 ~95% 说明 checkpoint 形态缺东西。
- 压缩后回归 —— 合成测试:拿一段成功的长任务,在不同点强制压缩、重放。只在压缩后失败的任务,说明压缩器丢了不该丢的东西。
一个值得接上报警的信号:实际 token 数和模型自报 token 数的偏差。漂移大说明你的 token 计账是错的,水位线也就无意义了。
相关阅读
- 提示词设计 —— 每一种压缩技术都必须保住提示词稳定前缀,缓存才能继续生效。废掉缓存的压缩要付两遍钱。
- 记忆设计 —— 对那些本来要被上下文管理器跨压缩保留的信息,记忆给出了外置策略。记忆和压缩组合:耐用的进记忆,易逝的被压缩。
来源
- Effective Context Engineering for AI Agents — Anthropic, 2026
- Prompt caching — Anthropic, Claude API 文档
- Effective Harnesses for Long-Running Agents — Anthropic, 2025
- Lost in the Middle: How Language Models Use Long Contexts — Liu et al., 2023, “context rot”和位置敏感检索的实证基础
- Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection — Asai et al., 2023,即时检索的相关研究框架