上下文加载:解释「怎样加载上下文」本身也在消耗上下文

用证据优先级、可重建句柄与新鲜度指纹控制每一轮推理真正需要看到的材料。

本页目录 · 18 节

Context Engineering 不是把更多材料塞给模型,而是在每次推理前回答一个更困难的问题:哪些信息在当前时刻最可能改变正确决策?

在代码任务里,信息量和正确率并不单调相关。一份内容完整但过期的设计文档,可能比完全没有文档更危险;成批领域规范同时进入上下文,也可能让真正相关的约束被淹没。

Marshall 的 Progressive Context 因此不是简单的按目录加载,而是一套证据排序、句柄展开和新鲜度校验机制。

Context 的最小单位不是文件,而是决策价值

我把上下文材料分成四个优先级:

优先级 内容 处理方式
P0 当前目标、直接需求来源、接受范围、非目标、当前源码、阻塞问题 立即进入上下文
P1 必须遵守的仓库规则、相关领域契约、权限与风险约束 在对应 Goal/Domain 命中时加载
P2 历史背景、旧讨论、相邻模块、趋势性日志 先压缩成带来源的摘要
P3 整个仓库树、完整日志、历史 Ticket 集、全部 Schema、无关领域 只保留 Locator,需要时再展开

这个排序不是按文件类型决定。当前 Provider Readback 即使只有几行,也可能是 P0;一份很长的「架构权威文档」如果对应旧版本,也只能是 P2 或 P3。

核心原则是 Source Proximity:越接近当前行为、当前版本和当前风险的证据,优先级越高。

一次 Context Selection 怎样工作

成熟版在每个非平凡 Stage 开始时运行 Perception Bootstrap。它不直接解决业务问题,而是建立本轮推理的证据边界:

1. 确认 Goal、Stage、Branch、HEAD 与 Worktree 状态
2. 识别直接来源:用户输入、Jira、PRD、Figma、PR 或运行证据
3. 找出受影响的仓库、领域、接口和高风险面
4. 将材料分入 P0-P3
5. 为大材料保存路径、URL、Revision、Hash 或 Query Locator
6. 只展开当前决策仍缺少的部分
7. 生成 Input Fingerprint,绑定到 Node/Worker

这和一次性构造巨型 Prompt 的最大区别是:Context 不是静态前置步骤,而是随着决策逐步展开。读到调用方后,才知道需要追踪哪个 Provider;确认没有数据写入后,就不再加载整套 Data Runtime 规范。

「地图」和「百科全书」是两种完全不同的入口

入口文件应该告诉 Agent 去哪里找,而不是试图把所有答案放进去。

OpenAI 的 Harness Engineering 文章总结过类似经验:超大的 AGENTS.md 会挤占任务与代码,让所有规则看起来同等重要,还会快速积累过期内容。因此入口更适合作为目录,稳定知识则放在可定位、可维护、可机械检查的结构中。

Marshall 的控制平面也采用这种结构:

  • constitution.md 只放少量全局不变量;
  • Goal Command 指向当前目标需要的规则;
  • Domain Index 再指向受影响领域;
  • Risk Lens 只在命中权限、数据、Provider 或发布风险时加载;
  • 运行产物通过 Artifact Role 和 Hash 定位,不复制进每个 Prompt。

这相当于先给模型一张目录树,再让它为当前问题走最短路径。

Locator 比摘要更重要

摘要可以帮助推理,却不能成为不可追溯的事实来源。成熟版的 Context Pack 要为关键材料保留:

source_type
locator
observed_revision / commit
content_sha256
observed_at
scope
why_selected

这样做有两个好处。

第一,Compaction 后不必保存全部原文,只要保留能重新读取的 Locator 和当时的版本。第二,当摘要中的结论变得可疑时,可以回到源头核对,而不是在多个压缩版本之间猜哪一份正确。

因此,Working Note 最重要的内容不是复述所有代码,而是:目标、已确认事实、决定、未解决问题、下一步,以及每项事实的可重建句柄。

Freshness 不是一个时间戳

「文件昨天更新过」并不能证明它仍适用于当前运行。真正的新鲜度要绑定会改变语义的输入:

  • Git HEAD、Base Ref 与 Worktree Diff;
  • Provider Object ID、Revision 或 Updated Time;
  • Requirement Source 的版本;
  • Domain Spec 与关联代码 Hash;
  • 上一 Stage 的不可变 Result;
  • Worker 实际读取的 Context Manifest。

成熟版将这些输入计算成 Fingerprint。节点开始、Worker Dispatch、Node Result 和 Stage Completion 都会重新校验。输入漂移时,旧结果不是简单标记「可能过期」,而是失去继续推进的资格。

这能阻止一种隐蔽错误:设计基于 Commit A,用户在运行过程中更新到 Commit B,Agent 却继续使用 A 的摘要完成实现。仅靠聊天上下文很难发现这种漂移。

Context Pack 是数据,不是新指令

把 Jira、网页、日志或 RAG 结果交给 Agent 时,外部内容可能包含看起来像指令的文本。成熟版因此要求:进入 Worker 的 Evidence 是 Data,不能覆盖系统、仓库或 Goal Contract。

一个 Worker 只得到:

  • 与该风险视角相关的最小上下文;
  • 明确的 Source Locator;
  • 自己的只读能力;
  • 输出 Schema 和 Report Path;
  • 不确定时允许走的 Route。

它不读取整个控制平面,也不能从证据文本中获得新工具或写入权限。这既减少 Token,也降低 Prompt Injection 跨越信任域的机会。

Progressive Discovery 的停止条件

按需加载很容易退化成无休止探索。每读一个文件又发现一批关联文件,最后还是把整个仓库拖进上下文。

所以每一轮展开都要有停止条件:

  1. 当前 Material Decision 是否已经有直接证据;
  2. 新材料是否可能改变方案,而不只是增加背景;
  3. 关键调用链是否已经从入口追到最终副作用;
  4. 风险边界是否已覆盖权限、数据、异步、缓存和 Provider;
  5. 剩余未知是可发现事实,还是必须由用户选择的产品决定。

如果下一份材料只会重复已确认结论,就应停止读取;如果剩余问题是 Material Choice,就进入 Question Gate,而不是继续用更多上下文替用户做决定。

Compaction、笔记和 Subagent 分别解决什么

这三种机制经常被当成同一套「长上下文方案」,其实适用形状不同:

技术 最适合 主要风险
Compaction 同一任务持续对话,保留主要决策与最近工作 过度压缩会丢掉当时看起来次要的关键细节
结构化笔记 跨会话、里程碑清楚、需要稳定交接 笔记可能过期或把推论写成事实
Subagent 子问题独立、需要深挖、结果可干净汇合 Token、延迟、重复探索和综合成本

Anthropic 的 Context Engineering 文章也把三者作为不同手段,并强调 Context 是有限资源。我的实践结论是:先用 Locator 和窄读取降低输入量;任务真的跨窗口时再用 Working Note;只有独立探索能带来新证据时才用 Subagent。

常见失败模式

Source Authority Inversion

旧聊天或 RAG 摘要排在当前代码前面,模型用过期解释覆盖真实实现。解决方式是明确证据优先级,并在结论前回到 Source Readback。

Context Flooding

因为担心遗漏而加载所有领域、所有测试和完整日志。结果是注意力被低价值材料分散,Compaction 更早发生。解决方式是 P0-P3 与按决策展开。

Handle without Freshness

只保存文件路径,不保存当时 Commit/Hash。路径仍存在,但内容已经变化,恢复时会把新字节当成旧证据。Locator 必须和版本绑定。

Summary Becomes Authority

一份自动摘要被多轮复制,后来没人再读原文。摘要应显式标注 Fact、Inference 和 Unknown,并始终保留源句柄。

Loader Self-weight

为了按需加载,先让模型理解复杂 Loader Schema、Context Ledger、Triage、Pack 和 Re-entry 协议。加载器说明本身可能成为最大的常驻上下文,抵消按需加载节省出的注意力预算。

Unbounded Discovery

没有停止条件,Context Selection 变成全仓审计。每次读取必须回答「它可能改变哪个当前决定」。

怎样衡量 Context 设计是否有效

只统计 Prompt Token 不够。一个过短 Prompt 也可能因为缺关键规则而反复返工。更有用的指标包括:

  • 首次有效修改前读取了多少无关文件;
  • 关键决定能否回到当前 Source;
  • 任务中出现多少次因旧证据导致的重做;
  • Compaction 次数及每次恢复耗时;
  • Context 中规则、业务源码、工具输出分别占多少比例;
  • Subagent 返回内容的重复率和实际采用率;
  • 因上下文缺失产生的评审问题,与因上下文过载产生的遗漏。

目标不是最少 Token,而是单位 Token 带来的决策增益最高。

适用边界与 Trade-off

Progressive Context 适合跨仓库、跨来源、持续多个上下文窗口,或必须说明证据版本的任务。此时 Manifest、Fingerprint 与 Working Note 能把「模型记得什么」转换为可重新读取的事实边界。

对于文件和调用路径都已经明确的短任务,完整 Context Pack 可能比直接读取目标源码更重。判断是否启用复杂上下文机制,不看材料总量,而看恢复、漂移校验和多执行者隔离是否真的构成当前风险。

参考资料

相关文章

在做类似的事情?

很乐意就分布式系统、交付流程和应用 AI 交换意见。

[email protected]