繁

从每轮推理的信息选择理解 Context Engineering:上下文窗口与 Context Rot、按需检索与渐进加载,以及压缩历史、外部笔记和子 Agent 独立上下文的区别。

Context Engineering:Agent 的上下文该怎样组织和维护?
24 分钟
4894 字

上一篇讨论了工具怎样被发现和调用。工具执行以后,结果会回到模型;任务继续推进,又会产生新的代码、资料、判断和测试输出。这些信息怎样进入下一轮推理,就是 Context Engineering 要处理的问题。

结合 Anthropic 的《Effective context engineering for AI agents》,本文从三个层次展开:

  • 管理对象: Context 与 Prompt 有什么区别,窗口容量为什么不能代表信息利用质量。
  • 每轮组织: 指令、工具、示例和历史怎样配合,怎样按需检索并逐步补齐资料。
  • 长期维护: Compaction、Structured Notes 与 Subagents 分别怎样处理历史、状态和探索细节。

下面用一个假设的 Java 项目排查贯穿全文:订单回调疑似被重复处理,需要定位原因并补充回归测试;修改范围限定在回调模块,不调整支付 SDK。

一、Context Engineering 解决什么问题h2

1. Prompt Engineering 与 Context Engineering 的区别h3

Prompt Engineering 关注怎样表达目标、规则和预期输出;Context Engineering 则进一步组织模型本轮推理能够看到的完整信息,包括指令之外的工具定义、外部资料、消息历史和执行结果。

面对回调问题,清楚的指令可以要求“定位重复处理原因,只修改回调模块”。但模型要作出具体判断,还需要看到回调入口、状态更新逻辑,以及对应的失败证据。指令说明要做什么,代码和日志提供判断的依据。

而且,不同阶段需要的信息并不相同:

阶段本轮主要需要什么
开始定位任务范围、目录和回调入口
分析原因相关调用关系、状态变化与失败日志
修改验证当前代码差异、测试结果与未解决问题

用户目标保持不变,支持行动的信息却在持续变化。因此,上下文组织要跟着执行过程更新,不能只在任务开始时准备一次。

这里还要区分外部环境拥有的信息与模型当前看见的信息。源码存在仓库中,笔记存在文件里,只有相关内容被读取并进入本轮输入,才能直接参与模型判断。这与执行环境中的文件状态,是不同层次的问题。

2. Context Window 与 Context Rot:容量与信息利用h3

Context Window 规定模型能够容纳的 token 范围,解决的是容量问题。但资料装得下,仍然需要模型从中找到、关联并正确使用关键内容。

例如,排查重复回调时,入口代码、状态更新和失败断言能够补全因果关系;整份依赖下载日志通常没有同样的价值。两者都会占用空间,却不一定同样有助于任务。

Anthropic 用 **Attention Budget(注意力预算)**描述信息处理能力的有限性。这里可以把它理解为工程上的提醒:输入越复杂,越需要有意识地组织信息,而不是一项能像 token 上限一样精确扣减的配额。

Context Rot 则指长上下文中信息利用表现可能退化的现象。Chroma 的研究通过受控任务发现,模型表现会随输入长度和干扰内容变化,并不是均匀使用窗口中的所有信息。

这意味着,评估上下文不能只看长度。需要同时检查材料是否相关、关键证据是否容易定位,以及当前模型在任务中是否能正确使用它们。长输入并非一律无效,短输入也不一定充分。

过时信息还需要单独处理。旧日志来自修改前的代码,新的测试已经覆盖了另一条路径;如果没有交代时间和版本,模型就可能把不同状态混在一起。信息选择既要控制数量,也要保持来源和状态清楚。

二、每轮推理的上下文怎样组织h2

3. System Prompt:明确目标、规则与交付要求h3

指令为行动提供方向。它需要足够具体,让模型知道依据什么判断;也要保留空间,让模型能够根据实际证据调整排查路线。

只写“你是一名优秀的 Java 工程师”,没有说明当前任务怎样完成。反过来,提前穷举所有文件和错误分支,又容易把尚未证实的判断固定进流程。

对这个排查场景,可以把任务指导整理为:

目标:定位订单回调重复处理的原因,并补充相关测试。
范围:只修改回调模块,不调整支付 SDK 或无关接口。
证据:区分已复现问题、代码推断与尚未验证的假设。
交付:说明原因、修改点、实际验证结果和未解决问题。

这些要求明确了目标、边界和交付标准,没有规定每一步必须调用什么工具。模型可以先查入口,也可以根据失败日志转去检查状态更新;路线可以变化,任务边界保持清楚。

系统指令、当前用户要求和任务资料可以分别组织,避免背景、规则与证据混成一整段。重要的是各部分职责明确,格式本身不是目的。

4. Tools、Examples 与 History:能力、用法和当前状态h3

指令之外,模型还需要知道能使用什么能力、怎样使用,以及任务已经推进到哪里。

内容提供什么回调排查中的例子
Tools可用能力、参数和结果含义搜索代码、读取文件、运行指定测试
Examples典型用法或期望输出怎样传入测试模块,怎样表达证据与判断
History 与工具结果已发生的操作和当前任务状态已读取哪些入口、哪条断言失败、哪些修改已验证

工具定义清楚,模型才容易选择合适的动作;结果清楚,模型才能继续判断。例如,测试输出需要保留失败用例、断言和定位入口,通常不需要把所有重复的构建过程同等带入下一轮。

示例也应当有代表性。展示几种不同的典型情况,比堆积大量近似例子更容易说明规则;需要覆盖的行为不同,例子才有增加的理由。

历史则要保留对后续有影响的状态:当前目标、已确认结论、必要的失败尝试和未完成项。连续三次读取相同文件产生的重复内容,可以缩减;“并发路径尚未验证”却不能因为篇幅短就被删掉。

信息是否值得保留,要看它对下一步判断的作用。 同一段日志在定位时可能需要完整读取,原因查明后则可能只需保留关键记录与原始文件入口。

5. Just-in-time Retrieval:在需要时取回资料h3

按需检索的基本做法,是先保留轻量入口,再通过工具取得当前需要的内容。入口可以是文件路径、链接、查询条件或已保存结果的位置。

排查开始时,可以先搜索回调入口。找到 PaymentCallbackService.java后,再读取相关方法;发现状态更新由另一个模块负责,再补充那部分实现。模型不必在第一次调用前读完整个仓库。

它改变的是资料进入 Context 的时机:

保存入口 → 判断当前缺什么 → 取得相关内容 → 依据结果继续行动

文件名和目录可以帮助定位,但结论仍要来自实际内容。看到 tests/里的同名文件,能推测它与测试有关,不能直接认定它覆盖了当前故障。

这种方式减少了提前加载的负担,也增加了运行时查询。资料定位错误,就会多走几步;没有合适工具,关键内容也可能一直找不到。

因此,可以把稳定且高频的目标、约定提前提供,把大体积或使用不确定的资料留到需要时再取。预先检索与 Agent 自主搜索可以配合,不必二选一。

6. Progressive Disclosure:逐层补齐相关信息h3

Progressive Disclosure(渐进加载)强调从粗到细地建立理解:每次取得的信息,帮助确定下一步应该读什么。

对回调问题,一段探索可以是:

  1. 通过目录和文件名找到候选模块。
  2. 通过搜索结果定位回调方法。
  3. 读取方法及相关调用,理解判断与状态更新。
  4. 补充测试、日志或协议说明,核对尚未确定的关系。

它与按需检索密切相关,但关注点不同:按需检索回答什么时候取资料,渐进加载回答怎样逐步深入资料。

如果幂等检查与状态更新分处两个方法,读取第一个以后还需要继续补齐第二个。逐层加载的结束条件,是当前判断已经拥有必要依据,而不是上下文已经足够短。

图 1 · 上下文不是固定资料包,而是随执行反馈持续更新
每轮推理前重新组织上下文 组织当前目标、约束与证据,交给模型判断。若请求工具执行,取得真实反馈,再更新任务状态并为下一轮筛选信息。 提交信息 若需工具执行 依据反馈修订 为下一轮筛选 组织本轮 Context模型判断下一步取得执行反馈 目标、约束与必要证据回应用户或请求工具新证据、变更与错误 更新任务状态核对来源,处理冗余历史

这一过程也说明,上下文维护可以跟着 Agent Loop 进行:先组织已有信息,取得执行反馈,再更新状态、清理冗余,并决定下一轮还需要什么。

三、长任务的上下文怎样维护h2

即使按需读取,长任务仍会积累很多历史。接下来需要区分三类工作:怎样缩短已有过程,怎样保存重要状态,怎样安排新的独立探索。

7. Compaction:压缩会话历史h3

Compaction 把较长历史整理为更紧凑的表示,让后续推理能够依据摘要和必要材料继续工作。

对回调排查,需要保留的是目标与范围、已确认原因、实际修改、验证结果和未解决问题;重复搜索或已无继续价值的工具输出,则可以缩减。

例如,下面两份摘要提供的工作条件不同:

回调模块已修复,测试基本通过。

已调整回调模块的幂等检查,顺序重复回调测试通过;并发路径尚未验证。支付 SDK 未修改。相关差异与测试日志已保存,下一步检查并发测试。

第二份保留了已完成与未完成之间的边界。下一轮据此知道应该继续做什么,也能回到代码和日志核对依据。

压缩首先要避免遗漏关键事项,再减少冗余。过度缩短可能把“部分测试通过”改写成“问题解决”,也可能丢掉设计约束。摘要越紧凑,留下可回查入口越重要。

对于已经无关或能够可靠重取的旧输出,也可以清理原文。无法重现的关键失败证据,则应先保存,不能默认再次执行一定得到相同结果。

8. Structured Notes:保存可恢复的任务状态h3

Structured Notes 把进度和关键判断写到 Context 外,再在需要继续时读取。

与 Compaction 相比,它的重点不是缩短整段对话,而是维护一份明确的工作状态。例如,任务笔记可以这样组织:

task: 排查订单回调重复处理
scope: 回调模块与相关测试;不调整支付 SDK
confirmed:
- 顺序重复回调测试已通过
pending:
- 并发回调测试
- 异常后的状态恢复
evidence:
- 当前代码差异
- artifacts/callback-test-run.log
next_action: 检查并发回调路径

已确认、待验证、证据与下一步被分开,后续不必从几十轮对话里重新整理这些关系。

笔记还需要随工作更新。代码再次修改以后,旧测试结果对应的是旧版本;假设被推翻,也要修订判断。保存和取回都成功,内容仍然可能过时,所以恢复时需要结合当前环境核对。

外部记录提供持久状态,读取操作让状态重新进入模型输入。 两个环节缺一不可,写出一个文件并不代表后续调用自动获得了它。

9. Subagents:隔离独立探索的上下文h3

当任务可以分成相对独立的探索,可以让子 Agent 使用自己的上下文处理细节,再向主 Agent 返回结论和证据。

例如,一个分支检查业务代码中的状态变化,另一个分支核对协议里的重试含义。各自可以搜索、读取和判断,主 Agent 则重点处理两份结果之间的联系。

这里的收益不是扩大主模型的窗口,而是把局部探索留在各自的 Context,减少主上下文承接的原始过程。如果最后把所有搜索记录完整拼回来,信息负担仍然会回来。

返回结果需要说明结论、依据、未确认项与覆盖范围。“没有发现问题”太模糊;“检查了顺序重复回调,尚未检查并发状态更新”才能支持下一步安排。

这种拆分也有成本:输入需要交代背景,输出可能遗漏细节,主 Agent还要汇总。需要频繁共享完整前序判断的任务,未必适合切开。

上下文隔离也不自动提供文件隔离。如果子 Agent 共用工作目录,仍需另行管理修改冲突;这里讨论的是信息分工,不是执行环境的隔离机制。

三种策略可以放在一起比较:

策略主要处理什么在当前任务中的作用
Compaction已积累的会话历史保留关键条件,缩短冗长过程
Structured Notes需要持续保存的状态记录进度、依据与待办,支持恢复
Subagents可独立开展的探索分担局部阅读,返回精选结果

它们可以组合:子 Agent 返回发现,主 Agent 将确认的状态写入笔记;历史过长时,再压缩对话。三者处理不同对象,不应全部归为一种“自动记忆”。

把信息选择、检索与状态维护连起来h2

回到回调排查,指令提供目标与边界,工具和资料提供行动能力与判断依据。按需检索控制内容进入的时机,渐进加载逐步补齐关系;任务变长以后,再分别处理历史、外部状态与独立探索。

这些安排需要随着新证据更新。出现新的失败,不应继续沿用旧摘要中的成功结论;已经保存且可重取的细节,也不必一直占据当前窗口。

我理解的上下文质量,最终要落到具体行动上:能否找到相关代码,能否区分已验证与待验证,能否保留修改范围,以及恢复以后是否能接着推进。

Context Engineering 不是尽量多放资料,也不是一味缩短输入,而是让当前信息足以支持行动,并让重要状态在执行过程中保持清楚。

几个关键问题,串起信息选择与长期维护h2

Prompt 已经写清楚,为什么还需要 Context Engineering?

指令说明目标与规则,但模型还需要代码、资料、工具定义和执行结果才能判断。任务推进后,这些内容会变化。Context Engineering 管理的是每轮完整输入,清楚的 Prompt 是其中一部分。

没有装满 Context Window,为什么模型仍可能漏掉信息?

容量上限说明能够容纳多少,不保证每条信息都被同样可靠地使用。输入长度、干扰内容和任务要求都会影响表现。需要检查关键证据是否相关、容易定位,以及模型是否实际用对了它。

按需检索和渐进加载有什么区别?

按需检索安排取资料的时机,渐进加载安排探索的层次。可以先按需取得一份完整文档,也可以从目录和摘要开始逐层深入;两者都以取得充分依据为目标。

怎样判断一段信息可以移出当前上下文?

先看它是否仍影响下一步,再看能否可靠重取。有版本和入口的源码可以按需回读;临时出现的失败日志则应先保存。可以移出当前输入,不等于可以丢失唯一证据。

Compaction 与 Structured Notes 能互相替代吗?

不能完全替代。Compaction 压缩当前历史,Notes 保存明确的外部状态。摘要可以引用笔记,笔记也可以帮助压缩后恢复,但前提是内容准确、入口可用,并在需要时实际读取。

子 Agent 怎样减少主上下文的负担?

独立处理局部探索,返回足够支持整体判断的结果,而不是全部原始过程。收益来自分工和筛选,同时要处理遗漏、证据回查与协调成本;它没有改变主模型的窗口上限。

怎样判断上下文管理确实改善了任务?

不仅看节省了多少 token,还要看目标与范围是否保留、判断是否依据当前证据、验证状态是否准确,以及恢复任务时是否减少了遗漏和重复工作。更短的输入只有仍能支持任务时才有价值。

参考资料h2