从每轮推理的信息选择理解 Context Engineering:上下文窗口与 Context Rot、按需检索与渐进加载,以及压缩历史、外部笔记和子 Agent 独立上下文的区别。
上一篇讨论了工具怎样被发现和调用。工具执行以后,结果会回到模型;任务继续推进,又会产生新的代码、资料、判断和测试输出。这些信息怎样进入下一轮推理,就是 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(渐进加载)强调从粗到细地建立理解:每次取得的信息,帮助确定下一步应该读什么。
对回调问题,一段探索可以是:
- 通过目录和文件名找到候选模块。
- 通过搜索结果定位回调方法。
- 读取方法及相关调用,理解判断与状态更新。
- 补充测试、日志或协议说明,核对尚未确定的关系。
它与按需检索密切相关,但关注点不同:按需检索回答什么时候取资料,渐进加载回答怎样逐步深入资料。
如果幂等检查与状态更新分处两个方法,读取第一个以后还需要继续补齐第二个。逐层加载的结束条件,是当前判断已经拥有必要依据,而不是上下文已经足够短。
这一过程也说明,上下文维护可以跟着 Agent Loop 进行:先组织已有信息,取得执行反馈,再更新状态、清理冗余,并决定下一轮还需要什么。
三、长任务的上下文怎样维护h2
即使按需读取,长任务仍会积累很多历史。接下来需要区分三类工作:怎样缩短已有过程,怎样保存重要状态,怎样安排新的独立探索。
7. Compaction:压缩会话历史h3
Compaction 把较长历史整理为更紧凑的表示,让后续推理能够依据摘要和必要材料继续工作。
对回调排查,需要保留的是目标与范围、已确认原因、实际修改、验证结果和未解决问题;重复搜索或已无继续价值的工具输出,则可以缩减。
例如,下面两份摘要提供的工作条件不同:
回调模块已修复,测试基本通过。
已调整回调模块的幂等检查,顺序重复回调测试通过;并发路径尚未验证。支付 SDK 未修改。相关差异与测试日志已保存,下一步检查并发测试。
第二份保留了已完成与未完成之间的边界。下一轮据此知道应该继续做什么,也能回到代码和日志核对依据。
压缩首先要避免遗漏关键事项,再减少冗余。过度缩短可能把“部分测试通过”改写成“问题解决”,也可能丢掉设计约束。摘要越紧凑,留下可回查入口越重要。
对于已经无关或能够可靠重取的旧输出,也可以清理原文。无法重现的关键失败证据,则应先保存,不能默认再次执行一定得到相同结果。
8. Structured Notes:保存可恢复的任务状态h3
Structured Notes 把进度和关键判断写到 Context 外,再在需要继续时读取。
与 Compaction 相比,它的重点不是缩短整段对话,而是维护一份明确的工作状态。例如,任务笔记可以这样组织:
task: 排查订单回调重复处理scope: 回调模块与相关测试;不调整支付 SDKconfirmed: - 顺序重复回调测试已通过pending: - 并发回调测试 - 异常后的状态恢复evidence: - 当前代码差异 - artifacts/callback-test-run.lognext_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,还要看目标与范围是否保留、判断是否依据当前证据、验证状态是否准确,以及恢复任务时是否减少了遗漏和重复工作。更短的输入只有仍能支持任务时才有价值。