上下文加载:解释「怎样加载上下文」本身也在消耗上下文
用证据优先级、可重建句柄与新鲜度指纹控制每一轮推理真正需要看到的材料。
本页目录 · 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 的停止条件
按需加载很容易退化成无休止探索。每读一个文件又发现一批关联文件,最后还是把整个仓库拖进上下文。
所以每一轮展开都要有停止条件:
- 当前 Material Decision 是否已经有直接证据;
- 新材料是否可能改变方案,而不只是增加背景;
- 关键调用链是否已经从入口追到最终副作用;
- 风险边界是否已覆盖权限、数据、异步、缓存和 Provider;
- 剩余未知是可发现事实,还是必须由用户选择的产品决定。
如果下一份材料只会重复已确认结论,就应停止读取;如果剩余问题是 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 可能比直接读取目标源码更重。判断是否启用复杂上下文机制,不看材料总量,而看恢复、漂移校验和多执行者隔离是否真的构成当前风险。
参考资料
- Harness engineering: leveraging Codex in an agent-first world:短入口、结构化仓库知识与机械可验证性。
- Effective context engineering for AI agents:有限注意力预算、Just-in-time Context、Compaction、笔记和 Subagent。
- Effective harnesses for long-running agents:跨上下文任务的 Progress File、Git History 与增量工作。
相关文章
从 Workflow Harness 到轻量 Prompt:Codex 5.6 之后我删掉了什么
当模型的原生流程已经够强,Harness 会从效率放大器变成上下文负担。这次重写保留了安全边界,同时大幅精简 Prompt 和运行时。
顶层配置只留四条硬规则:Agent 在哪里必须停下来
模型可以越来越自主,但生产、持久化数据、成本和不可逆动作必须先经过明确授权。安全不是效率的对立面,而是自动化成立的前提。