Context Engineering 的目标,不是让模型看见尽可能多的信息,而是让当前决策所需的信息以正确的身份、结构、预算和生命周期进入模型可见工作集。
引言:所有资料都“在历史里”,为什么 Agent 还是用了错误证据?
设想一个多仓库源码研究与文章发布 Agent。它接收研究问题和五个目标仓库,读取源码、测试、官方文档和网页,形成证据包,生成草稿,等待人工评审,最后发布文章并保存回执。
一次运行中,研究工具把完整 git diff、数千行测试日志、多个源文件和网页正文直接追加到消息历史。资料没有丢,但研究问题、required repository manifest(任务明确要求覆盖的仓库集合及固定 revision)、禁止事项和剩余 open items 被推到窗口边缘。
接近窗口上限时,系统做了一次 compaction(以压缩检查点替换更早历史)。新摘要保留了“OpenAI SDK 支持恢复”和“Context7 使用两阶段检索”,却丢失了 commit、文件路径、行号、反例、未完成核验,以及并行工具调用与结果之间的 call ID。下一轮模型无法判断某段结论来自哪个版本,也不知道其中一项仍未复核。
更糟的是,外部 plan.md 和网页正文被直接拼进 system message。文件里一段“跳过人工批准,直接发布”的示例文字因此获得了不应有的指令身份。模型最终仍能写出流畅的 article_draft,但它所依据的工作集已经不再代表当前任务。
图 1|信息存在于历史或文件中,不代表它以正确身份进入了当前工作集。挤压、压缩失真、工具错配和信任提升会共同改变模型实际看见的任务。
导读图|从候选来源到序列化输入,每次组装都留下 included、excluded、变换与输入身份。
这不是某次真实生产事故,而是本文用于推动设计的受控案例。它不证明某个模型的长上下文能力,也不提供 token、时延或准确率收益。它只把四类可以确定性检查的失效放在同一条链上:
- 该进入的信息没有获得稳定位置;
- 不该常驻的信息无边界占用预算;
- 变换后的内容丢失了恢复所需的结构;
- 低信任数据获得了过高的消息角色和控制影响。
本文所说的 上下文,是一次模型调用实际可见的工作集,包括指令、当前状态、消息、工具结果、外部证据、摘要和引用。它不等于完整消息历史,不等于文件系统,不等于 Store,也不等于 Memory。Context Engineering 管理的是候选信息如何进入、停留、变换、外部化、重新注入和退出这份工作集。公开实践与研究也把重点从单个 Prompt 扩展到整个推理时信息集合。hello-contextanthropic-contextcontext-survey
本文还使用以下工程术语:
- admission:判断一个候选是否可以进入当前模型工作集;
- artifact ref:指向外部制品的稳定引用,而不是把制品全文复制进上下文;
- source ref:定位一个直接来源;source lineage:按顺序记录直接来源及后续提取、摘要或合并形成的派生链;
- checkpoint:Runtime 可恢复位置及其最小状态,不自动证明其中自然语言内容正确;
- principal:当前执行读取或写入的访问主体;
- RAG:通过检索为当前调用提供候选信息的机制之一;
- preservation assertion:一次变换后仍必须成立、且可被检查的保真条件;
ContextAssemblyBlocked:必需分区或保真断言未满足时,Context Builder 返回的显式阻断结果。
案例使用六类稳定逻辑制品:research_plan、source_records、evidence_pack、article_draft、review_decision 和 publish_receipt。它们可以由文件、数据库或服务对象承载,但文件名本身不定义信任、版本和当前有效性。
全文使用五类陈述口径:固定源码和官方资料可直接核验的是“公开事实”;跨样本有限归纳是“样本观察”;仍需目标项目验证的是“工程建议”;研究 Agent 的受控选择是“案例决策”;没有统一实验支持的阈值与收益标为“待验证”。
入口问题只有一句:
什么信息在当前任务和当前阶段有资格进入模型上下文,并以什么形态、成本、权限和生命周期进入?
1. 先诊断:这真的是 Context 问题吗?
失效问题
本节先定位开场四类症状的责任边界,避免把“工具没有取回”或“模型已经看见但判断错误”误修成 Context 问题。
模型没有使用某条信息时,团队很容易把原因概括为“上下文不够好”。这个说法过于宽泛。信息可能从未被工具取回,可能已经进入模型但被错误理解,也可能是 Runtime 在错误阶段调用了模型。只有断裂发生在“候选信息到模型可见工作集”之间,才是本文讨论的 Context 问题。
| 观察到的失败 | 优先责任边界 | 何时进入 Context Engineering |
|---|---|---|
| 工具没有返回目标文件或返回错误数据 | 工具、查询、数据源 | 正确信息已经可用,但组装时未选入或被截断 |
| 模型已经看见完整证据但判断错误 | 模型、Prompt、业务 validator | 证据位置、角色或结构持续影响使用时再评估 |
| Runtime 在错误阶段调用模型 | Framework | 组装时机正确,但本轮工作集内容或形态错误 |
| 跨 session 信息没有保存或被错误更新 | Memory/Store | 对象已经存在,但本轮召回、资格或呈现错误 |
| 最终制品不满足要求 | Evaluation、业务验收 | 失败可追溯到缺失、陈旧或污染的模型输入 |
| 历史很长,关键约束、来源或工具配对消失 | Context Engineering | 立即进入资格、预算、结构和变换设计 |
Tool 负责产生候选 observation、read result 或 action result;RAG 只是其中一种候选获取机制。Tool 和 RAG 都不决定候选是否获得 admission,也不拥有 trust、role、budget、transform 或 lifecycle policy。Framework 决定何时调用 Tool 和 Context Builder;Context Builder 决定候选怎样进入本轮模型输入。
可核验事实与样本观察
[公开事实] pi 的 Agent 接口将 transformContext 与 convertToLlm 分开:前者在应用消息层做裁剪或外部上下文注入,后者把消息转换为特定模型可接受的格式,源码见 sources/pi/packages/agent/src/types.ts:149-200。pi-context
[样本观察] 这个接口边界支持把“保存了哪些消息”“怎样选择和变换”“最终怎样发给模型”分开观察。它不能证明 pi 的默认策略适合本文案例,但足以说明最终模型输入可以成为独立、可记录的工程对象。
路线与代价
最便宜的诊断不是立刻增加检索器或扩大窗口,而是保存一次失败的四份材料:
- 候选来源清单;
- admission 与排除结果;
- 变换前后的 item;
- 最终模型输入或其受控 hash 与可审计引用。
如果目标信息根本不在候选集,先修工具和数据源。如果它在最终输入中完整、角色正确、版本正确,先检查模型、Prompt 和 validator。如果它被错误排除、挤出、摘要失真或提升为错误角色,才修 Context Policy。
完整保存模型输入会增加隐私、存储和访问控制成本。高敏系统可以保存受控快照、字段级 hash、脱敏内容与可重建引用,但不能只记录“本轮大约用了这些资料”,否则故障归因仍然依赖猜测。
案例决策
[案例决策] 本文案例把每次组装尝试的 source acquisition outcome、candidate set、included/excluded、transform record、token estimate、assembly input identity 和 serialized model input identity 保存为 ContextAssemblyManifest。article_draft 使用错误来源时,先沿 manifest 判断是没有取回、取回失败、资格错误、预算淘汰、变换失真、adapter 序列化改变了结构、版本陈旧,还是模型已经看见却没有正确使用。
章节图|Tool、Model、Runtime、Memory、Evaluation 与 Context Engineering 由不同诊断材料划分责任。
待验证
模型输入需要保存到什么粒度、保留多久、怎样脱敏,取决于项目的故障定位和合规成本。
保守默认
先保存可重建的组装清单和最终 input identity,再增加检索、摘要或长窗口机制。
升级信号
同类遗漏、错配、污染、预算挤压或恢复失真能够稳定复现,并且断裂明确发生在候选到模型输入之间。
2. 先列来源,再判断上下文资格
失效问题
本节解决开场中的旧版本、来源不明和外部内容越权问题:候选即使高度相关,也必须先证明自己有资格进入。
“与问题相关”不能单独构成进入资格。一个高度相关的旧文档可能已经过期;一段正确代码可能属于另一个 commit;一份 plan.md 可能包含外部内容;另一位 Agent 的结论可能没有来源;一条 Memory 可能越过当前 tenant 或 project scope。
在研究型 Agent 中,候选信息通常至少来自:
- 系统与开发者指令;
- 用户任务和显式约束;
- 项目规则与代码约定;
- 当前消息历史;
- 工具调用与工具结果;
- 仓库代码、测试和日志;
- 官方文档与网页;
- 任务状态与 checkpoint;
- 文件化计划和证据包;
- 跨会话 Memory;
- 其他 Agent 的交付物。
可核验事实与样本观察
[公开事实] hello-agents 将 Context Engineering 描述为对模型完整工作集的管理,并把系统指令、工具、外部数据和消息历史都纳入候选信息范围;相关固定文档见 sources/hello-agents/docs/chapter9/Chapter9-Context-Engineering.md:38-58,80-109。hello-context
[样本观察] 候选来源越多,单纯按相似度或新近度排序越危险。相关性可以帮助排序合法候选,却不能替代权限、版本、来源和完整性检查。
路线与代价
本文把资格拆成硬门与软选择:
| 维度 | 需要回答的问题 | 默认作用 |
|---|---|---|
| 任务相关 | 它会改变当前决策吗? | 合法候选内排序 |
| 阶段相关 | 现在需要,还是以后再取? | 决定加载时机 |
| 来源/生产者 | 它来自哪里,由谁生成? | 建立身份与血缘 |
| 信任 | 系统允许把它当作什么级别的依据? | 决定权威上限 |
| 允许角色 | admission 后可以怎样影响模型? | trust-role compatibility 硬门 |
| 时效 | 是 valid、refresh_required、expired 还是 unverifiable? | 硬门或刷新 |
| 版本 | 对应哪个代码、文档、草稿或策略 revision? | 硬门 |
| 权限/scope | 当前 principal 有权看见吗? | 硬门 |
| 完整性 | 截断、缺页或缺配对会不会改变含义? | 硬门 |
| 成本 | token、时延与 cache 代价是多少? | 预算选择 |
| 安全/隔离 | 是否含外部指令、秘密或跨边界数据? | 隔离与防护硬门 |
source、trust、role 和 security 是四个独立维度:来源说明身份,信任说明可承担的权威,角色说明 admission 后允许的影响,安全说明隔离要求。硬门至少覆盖 permission、scope、required revision、freshness、integrity 与 trust-role compatibility;task relevance、stage relevance、evidence priority 和 cost 只在合法候选中排序。
retrieved=true、mentioned_recently=true、similarity=0.92 或“窗口还有空间”都不构成单独资格。硬门失败的 item 应进入 excluded,并保留受控原因;不能让后续排序把越权、陈旧或不完整对象“救回来”。
一个候选 item 至少需要能表达:
ContextItem {
item_id
source_ref
source_lineage
source_type
producer
content_hash
revision
scope
observed_at
freshness
trust
intended_role
security_class
completeness
estimated_tokens
}
source_ref 回到当前 item 的直接来源;source_lineage 则按顺序记录原始来源、提取、摘要和合并等派生节点。一个未变换的源码片段可以只有单节点 lineage;一个跨来源摘要必须能回到全部输入 item,而不能只写“来自若干文档”。
这不是通用行业 Schema,而是资格判断所需的最小信息。若当前项目没有版本或权限边界,相应字段可以简化;但一旦实际失败需要回答“来自哪里、属于谁、是否仍有效”,就不能只保留一段 content。
来源获取和 admission 结局也要分开记录:
source_acquisition = retrieved | not_retrieved | retrieval_failed
excluded.reason =
hard_gate_rejected
| permission_denied
| stale_revision
| expired
| unverifiable
| ranking_lost
| budget_evicted
| security_rejected
| transform_blocked
not_retrieved 表示没有得到候选,retrieval_failed 表示获取过程失败;二者不能伪装成“策略已审查并排除”。hard_gate_rejected 还应携带具体失败维度,便于区分 trust-role 不兼容、完整性失败和其他硬门。
案例决策
[案例决策] 仓库代码只有在 repo、commit、path 和 line range 完整时才进入证据候选;网页正文默认是 untrusted_external_data;research_plan 是当前任务状态数据,不是系统指令;review_decision 必须绑定 article_draft revision/content hash;其他 Agent 的摘要只有在带 source refs 和 producer identity 时才进入合成阶段。
被排除的旧 commit 仍保留 excluded.reason=stale_revision,这样失败时可以区分“没有取回”“获取失败”“检索到了但资格拒绝”和“合法但在排序或预算阶段未进入”。
章节图|permission、scope、revision、freshness、integrity、trust-role 与 security 先于相关性排序。
待验证
不同来源的 freshness、完整性和信任分级没有通用阈值。代码 commit 可以精确固定,持续更新网页可能只能保存访问时间和内容 hash。
保守默认
先做 permission、scope、required revision、freshness、structural integrity、trust-role compatibility 与 security policy 硬过滤,再按任务、阶段、证据优先级和成本排序。
升级信号
出现跨租户泄漏、旧 revision 混入、截断改变含义、来源冲突或外部数据指令提升时,增加更细的资格字段和拒绝原因。
3. 划分常驻、按需与渐进披露
失效问题
本节解决开场中硬约束被大对象挤到窗口边缘的问题:不是所有合法候选都需要以同一种加载方式进入。
所有内容常驻可以减少“忘记检索”,却会持续占用预算、放大过期污染并破坏稳定前缀。全部按需可以缩短输入,却把正确性押在 Agent 每次都能主动发现并下钻。渐进披露(progressive disclosure,先索引/摘要,后按需细节)提供索引和入口,但摘要或目录也可能误导。后文 Schema 中的 disclosure 就表示这套加载策略。
三种加载方式不是成熟度等级:
| 方式 | 适合 | 新增风险 |
|---|---|---|
| 常驻 | 极少量稳定目标、权限、硬约束和当前阶段 | 持续占 token、过期污染、cache 失效 |
| 按需检索 | 可查询的代码、文档、Memory 和历史制品 | 漏检索、时延、工具失败 |
| 渐进披露(progressive disclosure) | 规模大且有目录、索引或 manifest 的材料 | 不下钻、索引失真、导航成本 |
可核验事实与样本观察
[公开事实] Context7 当前 agentic tools 先用 resolveLibraryId 确定 library identity,再以该 ID 调用 queryDocs 获取具体文档。流程见 sources/context7/docs/agentic-tools/overview.mdx:40-79,两个工具的行为见 sources/context7/docs/agentic-tools/ai-sdk/tools/resolve-library-id.mdx:48-59 与 sources/context7/docs/agentic-tools/ai-sdk/tools/query-docs.mdx:49-67。context7
[样本观察] 这是一种“先收窄身份,再按需取内容”的公开实现。它支持将导航与正文加载分开观测,但不能推出所有来源都应采用两次工具调用。
路线与代价
划分边界时先问:
- 信息若遗漏,损失有多大?
- 信息多久变化一次?
- 能否通过稳定 ID 精确取回?
- Agent 是否知道何时下钻?
- 常驻内容是否会破坏稳定前缀或挤压直接证据?
高损失且极少变化的约束适合常驻;体积大、可定位的原文适合按需;有天然层级的大材料适合渐进披露。一个来源也可以组合三种方式,例如常驻仓库 manifest,按需读取具体文件,用目录和 symbol index 渐进导航。
案例决策
[案例决策]
- 常驻:研究问题、required repository manifest、禁止事项、当前阶段、open items 摘要和本轮预算状态;
- 按需:具体源码、测试日志、官方文档正文、旧 trace 和跨会话 Memory;
- 渐进披露:仓库目录、证据索引、
article_draftoutline,先给摘要、版本和 source ref,再读取原文。
review_decision 在发布前必须显式加载并校验,但不会在每一个研究步骤中常驻。publish_receipt 是环境事实,在恢复或状态确认时按需读取,不作为写作阶段背景材料。
章节图|Resident、Retrieve 与 Progressive disclosure 是可组合的并列策略,不是成熟度阶梯。
待验证
Agent 主动下钻的漏检率、按需工具时延和常驻前缀的实际 cache 收益只能在目标任务中测量。
保守默认
极少量稳定约束常驻,大对象按需,规模大但可导航的材料使用渐进披露,先索引/摘要,后按需细节。
升级信号
固定任务显示 Agent 经常漏掉必要下钻时,增加自动 retrieval 或阶段触发;常驻区频繁变化、重复或过期时,继续缩小稳定前缀。
4. 结构化组装:保留来源、信任与调用结果配对
失效问题
本节解决开场中的 call ID 丢失和消息角色提升:选对内容之后,还要保留对象身份、信任边界和调用配对。
即使选中了正确信息,把所有内容拼成一段文本也会破坏责任边界。模型需要区分哪些是控制指令、哪些是用户目标、哪些是当前状态、哪些是工具观察、哪些是外部数据、哪些只是压缩摘要。
并行工具调用还增加了一个常见失效:结果按完成顺序到达,压缩或重放后却失去 call ID,模型把 Repo A 的输出配给 Repo B 的参数。
可核验事实与样本观察
[公开事实] pi 将 transformContext 和 convertToLlm 分开,见 sources/pi/packages/agent/src/types.ts:149-200;其 Agent 文档说明并行工具可以按完成顺序发出事件,但持久化的 tool result message 仍按 assistant source order 保存,见 sources/pi/packages/agent/README.md:87-124。pi-context
[公开事实] Continue 在组装消息时查找最近 conversation summary,并只保留摘要之后的历史;工具结果按 tool call ID 重新插入,summary 最后进入 system 内容。相关源码见 sources/continue/gui/src/redux/util/constructMessages.ts:48-60,125-159,206-224 与 sources/continue/gui/src/util/toolCallState.ts:8-69。continue-context
[样本观察] 这些机制支持三个边界:应用消息与模型消息可以分离;tool call 与 result 需要稳定配对;summary 一旦进入高影响消息位置,就必须拥有来源、版本和校验责任。
路线与代价
本文把上下文分成四个信任区域:
| 区域 | 内容 | 允许的影响 |
|---|---|---|
| Control | system/developer/runtime policy | 定义行为、权限和不可违反约束 |
| Task intent | 用户目标与显式选择 | 定义任务,但受更高层 policy 约束 |
| State and observations | 业务状态、工具结果、代码、文档、Memory | 提供事实候选,不自动产生控制权 |
| Derived context | 摘要、模型提取、其他 Agent 结论 | 帮助导航,权威不高于其来源 |
结构化并不要求某个特定 API 消息角色,但至少需要以下不变量:
- 每次调用都有唯一
call_id;即使 tool name 和参数完全相同,也不能复用 ID; canonical_argument_hash基于 tool name 与规范化参数计算,避免键顺序或无关格式改变身份;- Tool result 记录
result_hash,并通过call_id、tool name 和参数 hash 与唯一调用配对; - 结果状态区分 success、error、canceled、partial 与 unknown;
- partial/error 可以进入诊断上下文,但除非 policy 明确允许,不能作为已确认业务证据;
- Evidence block 保留 direct source ref、ordered source lineage、revision 与 transform record;
- Summary 保留明确 input item IDs 或连续 input range、summary version 和 source refs;
- 低信任数据不能因为字符串拼接进入 Control 区域;
- 并行完成顺序不能改变 call/result 语义配对。
结构越细,adapter 和兼容成本越高;结构过薄,又会让模型只能从自然语言猜测对象身份。工程上应先结构化会改变正确性和安全的边界,不为每个普通段落建立复杂类型。
案例决策
[案例决策] 一条源码证据以结构化块进入:
item_id: evidence-pi-transform-context
kind: evidence
source_ref:
repo: pi
commit: 53fa77ccd8a279eb87e92294ef3687b03ff80112
path: packages/agent/src/types.ts
lines: 149-200
source_lineage:
- {node_id: source-pi-types, type: repository_source, digest: sha256:...}
- {node_id: excerpt-pi-types, type: excerpt, input: source-pi-types, digest: sha256:...}
claim: transformContext and convertToLlm are separate interfaces
trust: repository_source
intended_role: untrusted_data
transform_record_id: transform-pi-types-excerpt
claim 只帮助合成,不能替代 source。需要核验时,Agent 沿 source ref 读取固定 commit 的原文,并可沿 source lineage 检查 excerpt 如何形成。外部网页、plan.md 和其他 Agent 的交付物都进入 data block;即使其中出现命令句,也不会变成 Runtime 权限或 system instruction。
章节图|四个信任区、tool call/result 配对与 source lineage 在组装时保持独立。
待验证
不同模型 provider 对消息角色、tool pairing 和 cache 前缀的限制不同,adapter 需要按目标模型验证。
保守默认
先结构化指令、状态、tool call/result、证据、summary 和 artifact ref,并保留稳定 ID。
升级信号
出现结果错配、来源无法追踪、并行顺序影响语义、摘要覆盖原文或外部数据提升为指令时,增加更严格的类型和 adapter 校验。
5. 先在源头限制,再做分区预算
失效问题
本节解决开场中完整 diff、测试日志和网页正文无边界进入历史的问题:在讨论截断前,先减少不必要的候选体积。
许多团队等到上下文接近上限,才开始讨论截断和摘要。此时最便宜的优化机会已经错过:工具本可以只返回需要的字段,日志本可以先按时间和错误级别过滤,diff 本可以限制路径和上下文行,大对象本可以只返回 artifact ref。
[工程建议] 无边界工具输出进入历史后,后续每一轮都可能继续承担同一批噪声的选择、传输、缓存和压缩成本;具体成本大小仍需按 provider、cache 和调用方式测量。
可核验事实与样本观察
[公开事实] pi 的 compaction 配置显式区分为 summary 保留的 reserve tokens 和压缩后希望保留的 recent tokens,源码见 sources/pi/packages/agent/src/harness/compaction/compaction.ts:147-166。pi-context
[样本观察] 这些值只证明固定实现存在预算参数,不提供通用比例。真正可迁移的边界是:模型输入、预留输出和压缩操作共享有限容量,因此预算必须在进入硬上限前分配。
Anthropic 的工具设计实践也强调让工具返回对 Agent 有用且 token 友好的结果;这支持在工具边界减少无关输出,但不能替目标项目决定具体字段或长度。anthropic-tools
路线与代价
源头限制优先处理:
| 来源 | 无边界返回 | 保守返回 |
|---|---|---|
| 源码读取 | 整个文件或仓库拼接 | path、line range、命中片段、artifact ref |
git diff | 全仓 diff | 指定 revision、路径、context lines |
| 测试 | 全量 stdout/stderr | exit status、失败 case、关键错误、完整日志 ref |
| 搜索 | 所有命中正文 | identity、score、摘要、下钻入口 |
| 网页 | 整页 HTML/正文 | title、URL、访问时间、相关段落、content hash |
| 并行 Agent | 原始探索轨迹 | 结构化结论、source refs、冲突与未决项 |
只有源头已经给出足够紧凑的候选后,才分配模型输入预算。一个实用但仍需项目验证的表达是:
usable_input_budget =
model_context_limit
- response_reserve
- protocol_and_tool_overhead
- safety_margin
usable_input_budget 再按责任分区,而不是给每个来源平均份额:
| 分区 | 最小保护 | 超预算时的默认动作 |
|---|---|---|
| Control 与硬约束 | 完整、不可被普通内容挤出 | 拒绝组装或缩减其他分区 |
| 当前状态与 open items | 保留可恢复字段 | 结构化压缩,外部化历史细节 |
| 当前决策直接证据 | 保留来源、版本和关键原文 | 减少候选数量,不切断证据身份 |
| 最近交互与 tool pairs | 保留未闭合调用与必要近因 | 按完整 turn/pair 裁剪 |
| 背景与旧 trace | 默认可按需再取 | 先外部化或排除 |
分区可以设置最小保留、最大上限和借用规则。未使用预算是否可以转给其他区,需要显式政策;不能让低优先级背景借走约束区的最低保护。token estimate 也不是事实,manifest 应同时保存估算方法和 provider 返回的实际 usage,便于后续校准。
案例决策
[案例决策] 研究工具默认返回命中片段、repo/commit/path/line、结果状态和 artifact ref。完整源码、完整测试日志与网页正文保留在外部。
本轮预算先保护:
- 研究问题、required repository manifest 与禁止事项;
- 当前阶段、open items 和草稿 revision;
- 当前主张的直接证据与冲突;
- 未闭合 tool call/result;
- 最后才是背景材料和旧 trace。
如果直接证据仍超预算,Runtime 不把每条证据平均截断,而是减少本轮主张数量、按主张分批生成,或要求 Agent 下钻更窄范围。
章节图|预算治理先收窄来源,再保护 Control、Task 与直接 Evidence 等关键分区。
待验证
response reserve、safety margin、各分区最小值和 token estimator 偏差都需要按目标模型、工具协议和任务长度验证。
保守默认
先限制工具和来源输出,再用有最低保护的分区预算组装;不从全量历史直接做平均截断。
升级信号
即使源头已经收窄,某类关键内容仍频繁被裁剪或挤出时,再调整分区、阶段化生成或增加专用压缩。
6. 在截断、摘要、内容压缩与 Prompt Cache 之间选择
失效问题
本节解决开场中 compaction 丢失 commit、行号、反例、open items 和 call ID 的问题:任何缩短都必须声明它要保留什么。
截断、摘要、压缩和 cache 经常被统称为“上下文优化”,但它们解决的问题不同:
| 机制 | 主要作用 | 典型损失或误解 |
|---|---|---|
| 截断 | 立即满足硬窗口 | 无语义判断地丢失内容 |
| 摘要 | 保留任务叙事与关键状态 | 精确值、来源、反例和未决项丢失 |
| 内容压缩 | 针对当前决策提取必要信息 | 压缩目标错误、来源覆盖不足 |
| Prompt Cache | 复用稳定前缀的计算 | 不减少逻辑污染,不解决过期和权限 |
cache hit 不能证明输入正确;摘要更短也不能证明恢复完整。二者都不能让不合格信息获得上下文资格。
可核验事实与样本观察
[公开事实] pi 的 compaction cut point 不会落在 toolResult 上,并会定位完整 turn 的边界,源码见 sources/pi/packages/agent/src/harness/compaction/compaction.ts:312-343,373-421。其结构化 summary 提示要求保留 Goal、Constraints、Progress、Key Decisions、Next Steps 与 Critical Context,并特别要求精确文件路径、函数名和错误,见同文件 :428-498。pi-context
[公开事实] Continue 会让最近 conversation summary 替代更早历史,并把 summary 追加到 system message,源码见 sources/continue/gui/src/redux/util/constructMessages.ts:48-60,206-224。continue-context
[样本观察] 好的压缩不只是“更短”,而是保留下一阶段继续工作所需的状态、否定结论、配对关系和证据入口。summary 一旦进入高影响位置,就必须被视为有版本、有输入范围、有误差风险的派生对象,而不是自动升级为事实。
路线与代价
变换前先定义 preservation assertions,也就是变换后仍必须成立、且可确定性检查的保真条件:
required_after_transform = {
goal,
hard_constraints,
current_stage,
done_in_progress_blocked,
open_items,
source_refs_and_revisions,
exact_values_and_errors,
conflicts_and_negative_findings,
unresolved_tool_calls,
article_draft_revision,
artifact_and_checkpoint_refs
}
不同变换承担不同责任:
- 截断 只能在完整 item、完整 turn 或完整 tool pair 边界发生;
- 摘要 要保留任务连续性和恢复状态,并能回到输入 item;
- 内容压缩 要声明当前 decision objective,不能把面向“写结论”的压缩结果拿去恢复“核验来源”;
- cache 只复用字节稳定、身份稳定的前缀,并记录 prefix hash、policy version 与失效条件。
一个最小 TransformRecord 可以包含:
record_id
type
input_item_ids
input_digest
objective
policy_version
transformer_version
preservation_assertions
output_digest
token_estimate_before
token_estimate_after
trust_before
trust_after
summary 还必须记录明确的 input_item_ids;若输入来自连续历史,则同时记录起止 item ID 或 turn range。压缩器可能也是模型,因此仍会随机、遗漏或受输入注入影响。高风险摘要需要确定性检查 source refs、open items、revision 和 tool pair;无法自动判断的语义保真度进入人工或离线 grader,而不是靠摘要自己声明“完整”。
trust_after 不得高于 trust_before 所允许的上限;摘要或压缩不能因为进入更高影响位置而自动获得更高权威。Prompt Cache 的稳定前缀也需要退出规则。目标、权限、项目规则、Runtime policy 或 Context policy version 变化时,旧前缀即使仍可命中,也不应继续使用。cache metadata 属于 manifest 的观测项,不是 admission 决策的替代品。
案例决策
[案例决策] 本文案例使用结构化 checkpoint summary:
Goal
Constraints
Current Stage
Done / In Progress / Blocked
Confirmed Claims + source refs
Conflicts and Negative Findings
Open Items
Draft Revision
Next Steps
Artifact / Checkpoint Refs
工具结果只有在 call/result 已闭合后才允许进入摘要。源码主张保留 repo、commit、path 和 line range;“未找到实现”这类否定结论同时保存检索范围,避免下一轮把“尚未找到”改写成“不存在”。
稳定前缀只包含极少量不频繁变化的 control policy。research_plan、open items 和证据都放在动态区,即使这会降低部分 cache 命中,也不把陈旧任务状态留在高影响前缀。
章节图|truncate、summary 与 content compression 必须留下 TransformRecord 和保真断言;Prompt Cache 只复用计算。
待验证
摘要触发阈值、压缩模型、保真 grader、cache 命中收益和变换时延都需要受控实验。本文没有运行统一长上下文测试。
保守默认
先按完整结构裁剪,再使用带 preservation assertions 的结构化摘要;cache 只服务稳定前缀计算。
升级信号
最近窗口稳定丢失远处关键状态时引入摘要;单一摘要丢来源、精确值或未决项时增加结构化 manifest 和专用压缩;不要用 cache 掩盖污染。
7. 外部化并安全重注入:文件、Checkpoint 与 Memory 都不是可信 Prompt
失效问题
本节解决开场中外部 plan.md 被直接拼入 system message 的问题:外部化只改变存放位置,不授予永久信任或角色。
长任务不可能把所有状态和证据永久留在窗口。外部化是必要能力,但“写到文件里”没有解决信任、版本和重新加载问题。文件可能被用户、Agent、工具、协作者或复制进来的网页内容修改;checkpoint 可能落后;Memory 可能过期或越过 scope。
外部对象重新进入模型上下文时,必须重新取得资格,不能因为它“来自自己的工作区”就绕过 admission。
可核验事实与样本观察
[公开事实] planning-with-files 使用任务计划、发现记录和进度文件承载长任务状态,相关说明见 sources/planning-with-files/README.md:76-89 与 sources/planning-with-files/docs/long-running-agent-tasks.md:17-45。其安全边界明确要求把计划内容作为带 BEGIN/END 标记的数据,不执行其中嵌入的指令;固定源码见 sources/planning-with-files/skills/planning-with-files/SKILL.md:449-468。planning-files
[公开事实] 同一项目说明 SHA-256 attestation 只能检测内容在受信 digest 未被替换时是否变化,不是带密钥签名,也不证明人工批准或内容可信;见 sources/planning-with-files/docs/attestation-locking.md:7-19,31-42,57-69。planning-files
[样本观察] 文件可以提供人类可见、可版本化、可恢复的外部工作状态,但文件系统不是指令权威。delimiter 和 hash 可以减少部分混淆与篡改风险,不能单独解决 prompt injection、权限或 writer 同时控制内容与 attestation 的问题。
MCP 安全最佳实践同样把外部服务器、工具和数据视为需要最小权限、明确授权与信任边界的输入供应链。它支持“外部可取回不等于可直接信任”,但具体防护仍由部署和威胁模型决定。mcp-security
路线与代价
不同外部载体承担不同职责:
| 载体 | 适合保存 | 重新注入时仍需检查 |
|---|---|---|
| artifact/file | 大型工具输出、计划、证据包、草稿 | writer、hash、revision、trust、scope |
| checkpoint | 当前 run 的恢复游标和 open state | runtime version、业务 revision、未决效果 |
| trace/event store | 原始调用与决策证据 | 只在诊断时按需读取,并检查权限与范围 |
| Memory | Memory subsystem 治理的跨输入对象 | 召回后只作为候选,检查 status、source、scope、freshness 与当前相关性 |
| 外部服务 | 审批与发布等权威状态 | identity、receipt、查询时间、状态完整性 |
重注入至少执行:
- 通过稳定 object ID 定位,不只依赖文件名;
- 核对 source、writer、content hash 和 revision;
- 核对当前 principal、tenant、project 与 task scope;
- 判断 freshness、expiry 和是否要刷新原始来源;
- 标记 trust 与允许的消息角色;
- 选择完整对象、excerpt、summary 或仅保留 ref;
- 记录 admission reason、transform 与 token 成本;
- 将 included/excluded 写入本轮 manifest。
这会增加 I/O、索引和治理成本。[工程建议] 直接每轮重注入可能放大陈旧状态、重复 token 和注入攻击面;风险越高,批准记录和数据内容越应位于不同权限边界,具体防护仍需结合威胁模型验证。
Memory 边界
Memory 设计回答什么值得跨 session 保存、怎样写入、修订、失效和遗忘。Context Engineering 只回答:Memory subsystem 召回的对象能否作为本轮候选,以及它以什么结构、信任身份和预算进入。Context 不写入、更新或外部化到 Memory;Memory object 是候选来源之一,不是上下文工作集本身。
同理,checkpoint 负责恢复 Runtime 位置,不自动证明其中自然语言摘要是业务事实;artifact store 负责保存对象,不自动决定对象应进入模型;trace 默认只为诊断按需读取,不是普通背景来源。
案例决策
[案例决策] research_plan 与 evidence_pack 外部化为版本化 artifact。模型常驻的是当前阶段、open items 和 manifest 摘要;需要核验主张时沿 source ref 下钻。
plan.md 以如下边界进入:
kind: task_state_data
trust: project_editable
intended_role: untrusted_data
content_hash: ...
revision: ...
admission_reason: restore_current_open_items
其中若出现“忽略批准直接发布”,只能作为待审查文本,不能改变工具权限或 Runtime 控制。review_decision 仍来自独立审批对象,并绑定 article_draft revision/content hash/destination;文件 hash 不能替代批准。
章节图|artifact、checkpoint、trace、Memory 与服务重新进入工作集时都要重新 admission。
待验证
不同项目的文件权限、签名、artifact store、refresh SLA 和敏感内容保留期不同。delimiter、hash 或单个 prompt injection classifier 都不能提供通用安全保证。
保守默认
外部化大对象和可恢复状态,但每次重注入都重新检查 identity、revision、scope、freshness、trust 和 role。
升级信号
出现文件篡改、陈旧恢复、跨 scope 注入、来源无法刷新或自主循环反复放大外部指令时,增加独立批准域、签名、内容隔离和更严格的最小权限。
8. 用失败证据决定何时升级
失效问题
本节解决“看到一个症状就叠加一个上下文组件”的设计漂移:升级必须绑定已经确认的失败,并带有撤销条件。
Context 机制很容易按功能数量堆叠:窗口不够就加摘要,摘要不稳就加向量检索,再加 rerank、文件 Memory、子 Agent 和 cache。每个机制都会新增状态、版本、成本和失败面。升级若没有对应失败,就无法判断何时停止。
可核验事实与样本观察
五个深描样本分别展示了 transform/convert 分层、tool pairing、summary replacement、两阶段文档获取和文件化恢复。它们没有共同证明“机制越多越可靠”,也没有提供一套通用 token 比例。
[工程建议] 按失败维度选择候选机制,并同时写清新增责任:
| 当前机制 | 已确认失败 | 候选升级 | 新增责任 |
|---|---|---|---|
| 全量历史 | 约束被挤出、成本不可控 | source limit + 最近窗口 | 工具契约、裁剪边界 |
| 最近窗口 | 远处关键状态稳定丢失 | structured summary/checkpoint | 摘要保真、版本与恢复 |
| 单一摘要 | 来源、精确值、冲突或 open items 丢失 | preservation assertions + manifest | 变换记录、离线 grader |
| 手动按需读取 | Agent 经常漏下钻 | 自动 retrieval 或阶段触发 | 召回、误召回、时延 |
| 单一检索 | 库/仓库身份混淆 | resolve identity 再 query | identity mapping、两阶段错误 |
| 进程内状态 | 中断后无法继续 | file/artifact/checkpoint | revision、迁移、权限 |
| 直接重注入 | 陈旧内容或 prompt injection | trust boundary + refresh | writer、hash、role、威胁模型 |
| 单一预算 | 关键分区频繁被裁剪 | 分区预算与阶段化生成 | 配额、借用、拒绝策略 |
| 单 Agent 工作集 | 独立探索持续污染主上下文 | 隔离的子任务上下文 | 交付契约、来源与合并 |
表中的候选机制不构成成熟度阶梯。一个短任务可能只需要源头限制;一个长但线性的任务可能只需文件化 checkpoint;一个高风险系统即使输入很短,也需要严格 trust boundary。
案例决策
[案例决策] 本文案例先使用:
- 结构化工具返回;
- 常驻硬约束和 open items;
- source ref 驱动的按需读取;
- 分区预算;
- 结构化 summary;
- 文件/artifact 外部化;
- 每轮 manifest。
没有“Agent 经常漏下钻”的固定证据,就不自动加入向量 retrieval。没有独立研究任务持续污染主工作集的证据,就不为上下文隔离而默认增加多 Agent。任何升级都记录它解决的失败、新增错误、运行成本和撤销条件。
章节图|机制升级由已确认失败触发,并在最简单达标方案处停止或回滚。
待验证
每种机制的 token、时延、质量和维护收益都依赖目标任务。本文只给出可检查的升级依据,不给通用窗口、摘要或检索阈值。
保守默认
从 source limit、稳定结构、按需引用和 manifest 开始,一次只增加一个机制。
升级信号
固定任务证明当前机制仍产生可归因的遗漏、污染、错配、陈旧、不可恢复或注入失败。
停止条件
当前最简单机制已经满足上下文检查清单。停在最近窗口、文件引用或结构化摘要,都可能是正确选型。
9. 把八个决策串成上下文生命周期
八个决策最终形成一条循环,而不是一次 Prompt 拼装:
source inventory
-> source acquisition outcome
-> eligibility
-> permission / scope / revision / freshness / integrity / trust-role checks
-> resident / retrieve / progressive disclosure decision
-> structured assembly
-> source limits and budget allocation
-> keep / truncate / summarize / compress
-> model-visible context
-> externalize artifact / file / checkpoint
-> refresh / re-inject / restore
-> expire or exit
图 2|候选信息只有经过资格、加载、结构、预算和变换,才进入模型可见工作集;是否外部化由 policy、体积、中断和恢复需要决定,外部对象重新注入时再次经过资格门。图中的阶段不是另一套“九个决策”编号。
这条生命周期有六条不能交换的不变量:
- 获取结局先于候选判断:
not_retrieved与retrieval_failed不伪装成 admission 排除。 - 硬门先于排序:permission、scope、required revision、freshness、integrity、trust-role compatibility 和 security policy 不合格的 item 不进入相关性竞争。
- 结构先于变换:先建立 tool pair、source lineage 和 role,再截断或摘要。
- 预算不覆盖资格:窗口有空位,也不能加入过期、越权或低完整性对象。
- 重注入重新 admission:文件、checkpoint、Memory 和旧 summary 不继承永久通行证;其中 Memory 只是外部候选来源,不是 Context 的写入目标。
- 每次组装尝试都有 manifest:ready 状态记录最终模型输入身份;blocked 状态记录阻断原因且不调用模型。
章节图|获取、硬门、结构、预算、重准入与 manifest 记录构成六条不可交换顺序。
一个最小组装过程可以保持简单:
assemble_context(request, runtime_state, policy):
acquisition, candidates = inventory_sources(request, runtime_state)
eligible, hard_rejected = policy.hard_filter(candidates)
ranked, ranking_lost = policy.rank(eligible)
loaded = load_by_mode(
resident=ranked.resident,
retrieve=ranked.retrieve,
disclose=ranked.disclose
)
structured = pair_and_label(loaded)
limited = apply_source_limits(structured)
budgeted, budget_evicted = allocate_partitions(limited, policy.budget)
transformed, transform_blocked = transform_with_assertions(
budgeted,
policy.transforms
)
staged_manifest = record_stage(
acquisition=acquisition,
candidates=candidates,
exclusions=[hard_rejected, ranking_lost, budget_evicted],
loaded=loaded,
budgeted=budgeted,
transforms=transformed + transform_blocked
)
if required_partition_missing or transform_blocked:
manifest = seal(
staged_manifest,
status=blocked,
blocked_reason=required_partition_missing | transform_blocked,
assembly_input_hash=absent,
serialized_model_input_hash=absent
)
return ContextAssemblyBlocked(manifest.id)
assembly_input = render(transformed)
serialized_input = provider_adapter.serialize(assembly_input)
manifest = seal(
staged_manifest,
status=ready,
blocked_reason=none,
adapter_version=provider_adapter.version,
serialization_policy_version=provider_adapter.policy_version,
assembly_input_hash=hash(assembly_input),
serialized_model_input_hash=hash(serialized_input)
)
return serialized_input, manifest
hard_filter 不能调用排序器绕过硬门;pair_and_label 不能把外部数据升级为控制指令;transform_with_assertions 不能只返回自然语言摘要而丢失输入引用。[案例决策] 若任何必需分区或 preservation assertion 失败,本文案例先封存 status=blocked、受控 blocked_reason 和全部阶段记录,再返回 ContextAssemblyBlocked(manifest.id);此时两个输入 hash 都是 absent,模型不会被调用。
assembly_input_hash 标识 Context Builder 输出的结构化组装结果;serialized_model_input_hash 标识 provider adapter 完成角色、工具定义和消息序列化后实际发送的输入。跨模块 ContextRef.input_hash 指向后者,并同时保存 adapter 与 serialization policy version。
Prompt Cache 只发生在最终输入的稳定部分。命中 cache 不跳过 admission、revision 检查和 manifest 记录。外部对象刷新后,即使文本相似,content hash、revision、Runtime policy 或 Context policy version 变化也应让对应身份更新。
10. Schema 是决策结果:推导最小上下文制品
前文的失效已经落在资格、加载、结构、预算、变换、外部化与重注入。到这里才有理由定义两个主制品:
ContextPolicy表达系统打算怎样组装;ContextAssemblyManifest记录某一次实际怎样组装。
前者是版本化规则,后者是运行事实。只保存 policy 无法证明某轮输入真的遵守了它;只保存最终 Prompt 又无法解释候选为何进入或被排除。
图 3|Policy 规定资格、变换与序列化约束,Manifest 同时记录组装层和 provider 最终序列化层的输入身份;Runtime、Trace 与 Evaluation 只引用 manifest,而不拥有上下文策略。
ContextPolicy
下面是本文案例的最小策略骨架,不是行业标准:
policy_schema_version: context-policy/v1
policy:
id: source-research
revision: 3
digest: sha256:...
scope:
task_type: multi_repository_source_research
principal_policy: research-agent/v2
revision_authority:
required_revision_sources:
- task_spec
- artifact_manifest
- runtime_business_state
freshness:
states: [valid, refresh_required, expired, unverifiable]
refresh_required: fetch_authoritative_source_before_admission
expired: reject
unverifiable: reject_or_request_resolution
source_acquisition:
outcomes: [retrieved, not_retrieved, retrieval_failed]
admission:
hard_filters:
- permission
- tenant_and_project_scope
- required_revision
- freshness
- trust_role_compatibility
- structural_integrity
- security_policy_compliance
ranking:
- current_decision_relevance
- stage_relevance
- evidence_priority
- retrieval_cost
exclusion_reasons:
- hard_gate_rejected
- permission_denied
- stale_revision
- expired
- unverifiable
- ranking_lost
- budget_evicted
- security_rejected
- transform_blocked
trust:
default_by_source:
system_policy: control_authority
user_request: task_authority
runtime_state: trusted_state
repository_source: repository_evidence
official_document: external_evidence
editable_project_file: project_editable
model_summary: derived_context
memory_object: governed_memory_candidate
role_limits:
control_authority: [control]
task_authority: [task_intent]
trusted_state: [state]
repository_evidence: [untrusted_data]
external_evidence: [untrusted_data]
project_editable: [untrusted_data]
derived_context: [derived_context]
governed_memory_candidate: [state, untrusted_data, derived_context]
security:
external_instruction_text: isolate_as_data
secret_material: deny_or_redact
cross_scope_data: deny
required_assessments:
- external_instruction_isolation
- secret_handling
- cross_scope_check
resident:
include:
- goal
- required_repository_manifest
- hard_constraints
- current_stage
- open_items_summary
retrieval:
default_sources: [repository, official_docs, artifacts]
diagnostic_sources: [trace]
governed_candidate_sources: [memory]
require: [stable_source_ref, scope_check, revision_check]
disclosure:
mode: index_then_detail
indexes: [repository_tree, evidence_index, article_outline]
structure:
preserve:
- source_lineage
- tool_call_result_pair
- revision
- trust
- intended_role
- result_status
source_limits:
repository: {default: excerpt_with_line_range}
test_log: {default: failures_plus_artifact_ref}
web_document: {default: relevant_sections_plus_hash}
budget:
model_context_limit: ...
response_reserve: ...
protocol_overhead: ...
safety_margin: ...
partitions:
control: {minimum: ..., eviction: never}
state: {minimum: ..., eviction: structured_summary}
direct_evidence: {minimum: ..., eviction: reduce_candidates}
recent_tool_pairs: {minimum: ..., eviction: complete_pair_only}
background: {maximum: ..., eviction: first}
borrowing: preserve_all_minimums
transforms:
trigger: ...
allowed: [none, truncate_item, summarize, decision_compress]
preserve:
- goal
- constraints
- open_items
- source_refs
- exact_values_and_errors
- conflicts_and_negative_findings
- unresolved_tool_calls
- article_draft_revision
- artifact_refs
serialization:
adapter: provider-specific
policy_version: ...
preserve:
- message_roles
- tool_definitions
- tool_call_result_pair
- instruction_data_boundary
cache:
stable_prefix_sources: [system_policy]
identity:
- ordered_source_ids
- source_content_hashes
- context_policy_revision
- runtime_policy_revision
invalidate_on:
- context_policy_revision
- runtime_policy_change
- permission_change
- project_rule_change
- stable_source_identity_change
externalization:
targets: [artifact_store, file, checkpoint]
reinjection:
require:
- object_identity
- writer_and_source
- content_hash_and_revision
- scope_and_permission
- freshness_or_refresh
- trust_label
- trust_role_compatibility
- structural_integrity
- security_classification
- security_policy_compliance
- admission_reason
expiry:
on: [source_expired, revision_replaced, permission_revoked, task_closed]
策略将“不允许进入”和“超预算后先淘汰什么”分开。required revision 来自任务、artifact manifest 或 Runtime 业务状态,不由检索结果自行声明;freshness 也使用受控状态,而不是一个模糊时间戳。trace 只列为诊断来源,Memory 只列为受治理候选来源,二者都不是普通背景默认加载项。
一个 item 可能完全合法,但因为当前阶段不需要或背景区已满而被排除;manifest 必须记录具体原因,避免把预算淘汰误判为检索失败。Context 的 externalization target 只包含 artifact、file 和 checkpoint,不把 Memory 写入纳入自身职责。
ContextAssemblyManifest
assembly:
id: assembly-...
run_id: run-...
step_id: step-...
status: ready
blocked_reason: null
policy: {id: source-research, revision: 3, digest: sha256:...}
model:
provider: ...
name: ...
api_version: ...
context_limit: ...
adapter:
name: ...
version: ...
serialization_policy_version: ...
candidate_set_digest: sha256:...
assembly_input_hash: sha256:...
serialized_model_input_hash: sha256:...
created_at: ...
source_acquisition:
- source_request_id: source-request-pi-types
source: {type: repository, id: pi}
outcome: retrieved
result_digest: sha256:...
- source_request_id: source-request-plan-v4
source: {type: artifact, id: plan-42, revision: 4}
outcome: retrieved
result_digest: sha256:...
- source_request_id: source-request-missing-doc
source: {type: official_document, id: missing-doc}
outcome: not_retrieved
reason: no_candidate_matched_fixed_identity
candidate_items:
- item_id: source-pi-types-raw
source_request_id: source-request-pi-types
source_ref:
repo: pi
commit: 53fa77ccd8a279eb87e92294ef3687b03ff80112
path: packages/agent/src/types.ts
lines: 149-200
source_type: repository
producer: read-source-tool/v2
content_hash: sha256:...
revision: 53fa77ccd8a279eb87e92294ef3687b03ff80112
scope: tenant-x/project-y/task-42
freshness: valid
trust: repository_evidence
intended_role: untrusted_data
security_class: repository_content
estimated_tokens: ...
- item_id: stale-research-plan-v4
source_request_id: source-request-plan-v4
source_ref: {artifact_id: plan-42, revision: 4}
source_type: artifact
producer: artifact-store/v1
content_hash: sha256:...
revision: 4
scope: tenant-x/project-y/task-42
freshness: valid
trust: project_editable
intended_role: untrusted_data
security_class: project_content
estimated_tokens: ...
budget:
usable_input: ...
estimated_used: ...
actual_input_tokens: ...
partitions:
control: {used: ..., minimum: ...}
state: {used: ..., minimum: ...}
direct_evidence: {used: ..., minimum: ...}
recent_tool_pairs: {used: ..., minimum: ...}
background: {used: ..., maximum: ...}
included:
- item_id: evidence-pi-transform-context
source_ref:
repo: pi
commit: 53fa77ccd8a279eb87e92294ef3687b03ff80112
path: packages/agent/src/types.ts
lines: 149-200
source_lineage:
- {node_id: source-pi-types-raw, type: repository_source, digest: sha256:...}
- {node_id: evidence-pi-transform-context, type: excerpt, input_node_ids: [source-pi-types-raw], digest: sha256:...}
content_hash: sha256:...
revision: 53fa77ccd8a279eb87e92294ef3687b03ff80112
scope: tenant-x/project-y/task-42
trust: repository_evidence
intended_role: untrusted_data
security_class: repository_content
hard_gate_results:
permission: passed
required_revision: passed
trust_role_compatibility: passed
structural_integrity: passed
security_policy_compliance: passed
security_assessment:
external_instruction_isolation: passed
secret_handling: passed
cross_scope_check: passed
admission_reason: supports_current_context_claim
load_mode: retrieve
transform_record_id: transform-pi-types-excerpt
excluded:
- item_id: stale-research-plan-v4
source_ref: {artifact_id: plan-42, revision: 4}
reason: stale_revision
hard_gate: required_revision
hard_gate_results:
required_revision: failed
security_policy_compliance: not_evaluated
security_class: project_content
security_assessment: not_evaluated_after_required_revision_failure
refresh_condition: load_required_revision_5
transforms:
- record_id: transform-pi-types-excerpt
type: excerpt
input_item_ids: [source-pi-types-raw]
input_digest: sha256:...
objective: preserve_interface_boundary_evidence
policy_version: source-research/3
transformer_version: excerpt-tool/v2
output_item_id: evidence-pi-transform-context
output_digest: sha256:...
preservation_assertions:
source_ref_present: passed
revision_present: passed
line_range_present: passed
token_estimate_before: ...
token_estimate_after: ...
trust_before: repository_evidence
trust_after: repository_evidence
- record_id: transform-checkpoint-summary
type: summarize
input_item_ids: [turn-17, turn-18, turn-19]
input_range: {start_item_id: turn-17, end_item_id: turn-19}
input_digest: sha256:...
objective: restore_current_research_state
policy_version: source-research/3
transformer_version: checkpoint-summarizer/v2
output_item_id: summary-checkpoint-19
output_digest: sha256:...
preservation_assertions:
goal: passed
open_items: passed
source_refs: passed
unresolved_tool_calls: passed
token_estimate_before: ...
token_estimate_after: ...
trust_before: mixed_admitted_sources
trust_after: derived_context
tool_pairs:
- call_id: call-...
tool_name: read_source
canonicalization: tool_name_plus_canonical_json_args/v1
canonical_argument_hash: sha256:...
result_item_id: source-pi-types-raw
result_hash: sha256:...
status: success
pairing_assertion: exactly_one_result_for_call
evidence_use: confirmed_by_policy
summaries:
- summary_id: summary-...
input_item_ids: [turn-17, turn-18, turn-19]
input_range: {start_item_id: turn-17, end_item_id: turn-19}
input_digest: sha256:...
transform_record_id: transform-checkpoint-summary
preservation_assertions:
goal: passed
open_items: passed
source_refs: passed
unresolved_tool_calls: passed
artifact_refs:
- {kind: research_plan, id: plan-42, revision: 5, hash: sha256:...}
- {kind: source_records, id: sources-42, revision: 8, hash: sha256:...}
- {kind: evidence_pack, id: evidence-42, revision: 3, hash: sha256:...}
- {kind: article_draft, id: draft-42, revision: 2, hash: sha256:...}
- {kind: review_decision, id: review-42, revision: 1, hash: sha256:...}
- {kind: publish_receipt, id: publish-42, revision: 1, hash: sha256:...}
checkpoint_ref: checkpoint-...
cache:
prefix_hash: sha256:...
prefix_identity: sha256:...
policy: eligible
status: hit | miss | bypassed
示例展示的是 status=ready。若组装被阻断,同一 Schema 使用:
assembly:
status: blocked
blocked_reason: required_partition_missing | transform_blocked
assembly_input_hash: absent
serialized_model_input_hash: absent
budget:
actual_input_tokens: absent
前面已经完成的来源获取、候选、排除、预算和 transform failure 仍然保留。
actual_input_tokens 可能只有调用后才能回填;这不影响 manifest 在调用前先保存估算和 admission 结果。canonical_argument_hash 对 tool name 与规范化参数计算;相同参数可以再次调用,但必须使用不同 call_id。每个 result 同时保存 result_hash 和配对基数断言,避免完成顺序改变语义;当 result 直接形成 candidate 时,result_hash 必须与该 candidate 所引用 payload 的 content_hash 一致。
partial/error 结果可以保存在 tool_pairs 和诊断上下文中,但默认使用 evidence_use=diagnostic_only,不能因为“已经返回一段文本”就成为确认事实。summary 同时记录 input item IDs 和范围;included item 保留 direct source ref 与 ordered source lineage。若系统不能保存原始敏感内容,hash、脱敏 item 与访问受控的重建位置仍需保留。
从字段回到失效
| 字段或策略 | 对应失效 | 最小断言 |
|---|---|---|
source_acquisition.outcome | 无法区分没有结果与策略排除 | not_retrieved、retrieval_failed 不进入 candidate 集 |
hard_filters | 越权、旧 revision、不可信角色或安全分类失败 | 不合格 item 不进入排序与预算 |
trust.default_by_source / role_limits / security | plan.md 或网页命令提升为 system | source、trust、role、security 独立检查;来源默认值不能绕过兼容性硬门 |
tool_pairs.call_id/tool_name/canonical_argument_hash/result_hash | 并行结果错配 | 每个结果只配对一个调用和规范化参数身份 |
source_ref/source_lineage/revision/content_hash | 压缩后来源丢失或旧文档混入 | 任一主张可回到固定来源和完整派生链 |
partitions.minimum/eviction | 约束被背景材料挤出 | 低优先级内容不能借走硬保护 |
transforms / preservation_assertions / trust_before/after | 摘要丢 open items、精确值和反例或提升权威 | 变换失败时阻止模型调用,且不提升信任 |
excluded.reason | 无法区分硬门、排序、预算与变换失败 | 每个候选都有受控结局 |
artifact_refs/checkpoint_ref | 中断后无法恢复精确信息 | summary 可下钻到权威外部对象 |
cache.prefix_hash/invalidate_on | cache 复用陈旧前缀 | policy、权限或规则变化后失效 |
assembly_input_hash / serialized_model_input_hash / adapter version | adapter 后结构变化,无法确认模型实际看见什么 | 前者绑定 Context Builder 输出,后者绑定实际发送输入 |
Runtime 可以只保存一个 ContextRef(manifest_id, policy_revision, input_hash=serialized_model_input_hash);它负责在正确步骤调用 Context Builder,不拥有 admission、预算和压缩规则。[案例决策] 本文案例中的 Evaluation 使用 manifest 检查 required item 是否进入、unauthorized item 是否为零、tool pair 是否完整、security policy 是否通过、变换是否通过保真断言,以及最终序列化输入是否绑定正确 adapter;这些是本案例 policy 的验收条件,不是所有项目的通用指标。Evaluation 不直接修改生产 run。
这些制品不是完整 Context Platform。删减规则仍然简单:
如果一个字段不能回到真实失效、资格边界、预算决策、恢复需要或确定性检查,就先删除;如果一个关键决策没有字段或外部机制承载,再补回来。
章节图|ContextPolicy 与 ContextAssemblyManifest 从六个设计问题和三类可观察失效反推。
结语:让每一轮模型输入都能解释自己
回到源码研究与文章发布 Agent,真正的问题不是它拥有多少仓库资料,而是当前写作步骤是否看见了正确版本的直接证据、required manifest、open items 和反例;工具结果是否与调用配对;摘要是否保留 source refs;外部文件是否仍只是数据;旧对象重新进入时是否重新核验。
一个项目可以从五个动作开始:
- 保存一次上下文失效、组装层 identity 和 provider 最终序列化输入 identity。
- 列出候选来源,分开记录 source、trust、role 和 security,并为 permission、scope、revision、freshness、integrity、trust-role compatibility 与 security policy 定义资格门。
- 将极少量稳定约束常驻,大对象按需读取,复杂材料使用渐进披露,先索引/摘要,后按需细节。
- 为预算、tool pairing、压缩、外部化和重注入写确定性不变量。
- 每次组装尝试保存
ContextAssemblyManifest;ready 才调用模型,blocked 保留原因后停止,当前机制达标后不再升级。
长窗口、RAG、summary、文件和 cache 都可以成为有效机制,也都可能被错误使用。Context Engineering 的工作不是选择一个万能组件,而是让每一条进入模型的内容拥有可解释的资格,让每一次变换保留必要结构,让每一次退出和重新进入都经过受控生命周期。
Context Engineering 的成熟度,不在于窗口里装了多少信息,而在于团队能否解释:模型这一轮看见了什么,为什么看见,以及它经过了什么变换。
附录 A:源码深描样本矩阵
外部资料访问截止日为 2026-09-06;目录与规格文件使用已经确认的 2026-09-07 版本标识。
| 项目 | 固定版本 | 直接观察到的机制 | 工程推断 | 不可外推 |
|---|---|---|---|---|
| hello-agents | 4f7682ceafe573d07cd8a7d0b89908500e83227d | 将系统、工具、外部数据和历史纳入完整工作集,并讨论 JIT、压缩和笔记 | Context 应管理整个模型可见信息集合 | 不能把教程中的经验结论当作统一实测 |
| pi | v0.84.1 / 53fa77ccd8a279eb87e92294ef3687b03ff80112 | transform/convert 分层、tool result 顺序、compaction cut point、结构化 summary | 选择、模型适配、配对和压缩可分离 | 不能据此声称默认 reserve 或 recent token 是最佳值 |
| Continue | 5522c6f44ca0ac3528b37244818fbfa39b5af470 | summary 替换旧历史、tool result 按 ID 重建、summary 注入 system | summary 和 tool pairing 是显式组装责任 | 不能据此声称当前实现已经解决摘要错误或注入风险 |
| Context7 | 6836bb4720a44fbce87f71548576c3145892d75f | resolve library identity 后 query docs | 身份收窄与正文加载可分两步 | 不能据此声称所有检索都需要两次调用 |
| planning-with-files | d47a61950e784fc4237ba10ddc1e9e198bd0f275 | 文件化状态、每轮重注入、data delimiter、SHA attestation | 文件恢复需要版本和信任边界 | 不能据此把 delimiter/hash 当作签名、批准或完整注入防护 |
附录 B:上下文预算分配表
这张表描述责任顺序,不给通用 token 百分比。具体数值均为 [待验证]。
| 分区 | 典型内容 | 最小保真 | 超预算动作 | 不允许 |
|---|---|---|---|---|
| Control | system policy、权限、禁止事项 | 原文或结构化等价表示 | 阻止调用,先缩减其他区 | 被背景材料淘汰 |
| Task intent | 用户目标、required manifest | 保留目标、范围和显式选择 | 请求澄清或阶段化任务 | 被摘要改写成新目标 |
| Current state | stage、open items、revision、未决效果 | 可恢复结构 | summary + checkpoint ref | 只保留流畅叙事 |
| Direct evidence | 源码、文档、结果与反例 | source/revision/关键原文 | 减少主张或分批下钻 | 平均截断全部证据 |
| Recent tool pairs | call、args、result、status | 配对完整 | 按完整 pair/turn 裁剪 | 保留 result 丢 call |
| Navigation | 目录、索引、outline | identity 与下钻入口 | 按阶段重新生成 | 把索引当原文证据 |
| Background | 旧 trace、一般说明 | 可丢弃或按需再取 | 最先外部化/排除 | 挤占硬约束最低保护 |
| Response reserve | 模型输出与后续 tool protocol | 满足 provider 与任务需要 | 缩小输入或停止组装 | 被输入吃满 |
附录 C:离线上下文检查清单
| 层 | 最小断言 |
|---|---|
| 来源获取 | 每次请求记录 retrieved、not_retrieved 或 retrieval_failed;后两者不伪装成 candidate |
| 候选来源 | 所有候选都有 source type、producer、revision/hash、scope 与 direct source ref;不能只保存裸文本 |
| 资格 | source、trust、role、security 独立;permission、scope、required revision、freshness、integrity、trust-role compatibility 与 security policy 硬门先于排序 |
| 排除 | 每个未进入 item 有受控 excluded.reason;可区分硬门、安全拒绝、排序落选、预算淘汰、过期与变换阻断 |
| 常驻 | 常驻区只含极少量稳定目标与约束;状态变化会使旧 revision 失效 |
| 检索 | 按需 item 使用稳定 source ref;身份解析错误不会进入正文查询 |
| 渐进披露 | 先索引/摘要,后按需细节;索引含下钻入口,关键约束不依赖 Agent 自主下钻 |
| 结构 | instruction、task intent、state、observation、summary 分区明确;低信任数据不进入 Control |
| Tool pair | 每个 result 绑定唯一 call ID、tool name、canonical argument hash、result hash 和 status;并行完成顺序不改变配对 |
| Tool result | partial/error 默认只用于诊断;没有 policy 许可时不作为已确认业务证据 |
| 预算 | control/state/evidence 最低保护有效;背景不能挤出硬约束;总输入含 response reserve |
| 截断 | 只在完整 item、turn 或 tool pair 边界发生;不会从 toolResult 中间切断 |
| 摘要 | input item IDs/range、goal、constraints、open items、source refs、exact values/errors、conflicts、revision 和 artifact refs 保留 |
| 血缘 | included item 同时保留 direct source ref 与 ordered source lineage |
| 压缩 | transform 有输入 item IDs/digest、objective、policy/transformer version、输出 digest、preservation assertions、token 前后估算与 trust 前后状态 |
| Cache | cache hit 不绕过资格;Context policy、Runtime policy、权限、项目规则或稳定来源身份变化触发 prefix invalidation |
| 外部化 | Context 只外部化到 artifact/file/checkpoint;对象可按 ID 和 revision 定位,不把 Memory 写入纳入自身职责 |
| 重注入 | 每次重新检查 writer、hash、scope、freshness、trust、role、security classification、security policy 和 admission reason |
| Memory | Memory subsystem 负责写入与治理;Context 只处理召回后的候选资格与呈现 |
| Trace | 默认只在诊断时按需读取,不作为普通背景自动注入 |
| 安全 | included/excluded 记录 security class 与判定;网页、仓库、文件与其他 Agent 输出中的指令不获得额外权限,delimiter/hash 不被当作信任证明 |
| 恢复 | summary 可沿 artifact/checkpoint/source refs 恢复未完成任务,不依赖模型猜测 |
| 阻断 | 必需分区或 preservation assertion 失败时封存 status=blocked、受控原因和完整阶段记录,两个输入 hash 均 absent |
| Manifest | source outcome、candidate、included、excluded、预算、tool pair、transform、security result、adapter、两层 input hash 与实际 usage 可追踪 |
这些检查只验证组装协议自洽,不证明模型质量、token 节省、cache 收益或生产安全已经提升。
附录 D:容易混淆的边界
| 概念 | 与 Context Engineering 的交界面 | Context Engineering 不拥有 |
|---|---|---|
| Prompt Engineering | 指令是 Context 的高优先级来源 | 单独覆盖工具结果、状态、预算和生命周期 |
| Tool | 产生 observation、read result 或 action result 候选 | admission、trust、role、budget、transform 和 lifecycle policy |
| RAG/检索 | 通过检索提供候选文档与 source ref | 自动决定资格、角色、预算和最终注入 |
| Framework/Runtime | 决定何时调用 Context Builder,并保存 ContextRef | admission、压缩和重注入策略 |
| Memory | Memory subsystem 提供经过治理的跨输入候选 | 写入、更新、失效、遗忘和长期治理;Context 不外部化到 Memory |
| Checkpoint | 提供 run 恢复状态 | 证明摘要内容是业务事实 |
| Store/File | 保存制品和大对象 | 自动成为可信 Prompt |
| Prompt Cache | 复用稳定输入前缀计算 | 压缩、去污染、更新与权限 |
| Evaluation | 用 manifest 和最终输入检查上下文契约 | 直接推进生产 run 或组装输入 |
| Trace | 保存因果与观测证据,并在诊断时按需提供候选 | 作为普通背景自动注入,或替代模型输入、业务状态和外部事实 |
参考资料
参考资料
hello-agents 固定源码,重点见
docs/chapter9/Chapter9-Context-Engineering.md。本文将其作为公开教程样本,不把其中经验性结论写成统一 Benchmark 结果。 ↩ ↩Anthropic: Effective Context Engineering for AI Agents,页面主题为上下文选择、长任务、压缩、结构化笔记与子任务隔离。访问日期:2026-09-06。 ↩
Context Engineering: A Survey,用于补充 Context Engineering 的研究范围与术语边界。访问日期:2026-09-06。 ↩
pi
v0.84.1固定源码,重点见packages/agent/src/types.ts、packages/agent/README.md与packages/agent/src/harness/compaction/compaction.ts。 ↩ ↩ ↩ ↩Context7 固定源码与文档,重点见
docs/agentic-tools/overview.mdx与docs/agentic-tools/ai-sdk/tools/。 ↩Continue 固定源码,重点见
gui/src/redux/util/constructMessages.ts与gui/src/util/toolCallState.ts。 ↩ ↩Anthropic: Writing Tools for Agents,页面主题为工具接口、返回内容与 Agent 可用性。访问日期:2026-09-06。 ↩
planning-with-files 固定源码,重点见
README.md、docs/long-running-agent-tasks.md、docs/attestation-locking.md与skills/planning-with-files/SKILL.md。 ↩ ↩Model Context Protocol 2026-07-28 Specification 与 Security Best Practices,用于补充外部工具、授权、信任与最小权限边界。访问日期:2026-09-06。 ↩