Skip to content

A4 · Agent 如何理解和管理当前上下文? - Context ​

所属知识库:Agent 全栈技术地图
所属领域:02 · Agent
所属章节:02 · Agent 的能力由哪些部分构成? - Internal Architecture
文档类型:技术原理与工程实践研究
版本:v1.1
更新日期:2026 年 10 月 28 日
核心问题:Agent 如何在每次模型调用前,根据任务、运行状态、证据、历史、工具和 token 约束构建有效上下文?信息如何筛选、排序、压缩、恢复与校验?如何设计可测试的 Context Engineering 运行时,而不是仅依靠不断增长的聊天记录?

专题导读 ​

Context 是 Agent 在某一次模型调用中能够直接使用的工作视野,而不是 Agent 所有知识、历史、记忆和状态的总和。一个长期运行的研究 Agent 可能访问数万份文档、执行上百次工具调用,但每一轮模型决策真正需要的,只是与当前动作直接相关、足够可信、可回溯且符合 token 预算的一部分信息。因此,上下文管理的核心技术问题不是“如何把更多内容放进提示词”,而是如何把庞杂的信息环境转换为适合当前决策的、结构明确的模型输入。

本篇从一次 Agent 调用的完整生命周期入手,拆解上下文装配(Context Assembly)、候选选择、预算优化、历史压缩、状态恢复、证据定位和输出后的上下文更新。重点研究:候选信息如何表示;哪些内容必须保留;如何把选择问题建模为受约束的优化问题;如何在冗余、覆盖度、时效性与成本之间取舍;摘要如何避免事实漂移;如何处理工具输出、结构化状态和多模态信息;以及怎样用最小可运行代码验证一个上下文装配器。文中同时分析长上下文位置效应、提示缓存、KV Cache 与运行时持久化之间的差异,并以研究助理 Agent 的多阶段研究任务贯穿设计。

核心判断:Context Engineering 是围绕“当前模型决策”组织信息的运行时工程。它的质量取决于模型是否获得了正确且足够的信息,而不是输入 token 是否被填满。

01 · Context 的精确定义:工作视野与系统事实不能混淆 ​

在步骤 t,Agent 具有任务目标 G、权威运行状态 Sₜ、交互历史 Hₜ、外部检索结果 Rₜ、持久化记忆 M、可用工具集合 T、规则 P 和模型预算 B。上下文装配器选择并序列化其中的一部分,生成本次模型调用的输入 Cₜ:

text
Cₜ = Serialize(Select(G, Sₜ, Hₜ, Rₜ, M, T; P, B))
model_outputₜ = Model(Cₜ)
validated_actionₜ = Validate(model_outputₜ, Sₜ, P)
observationₜ = Execute(validated_actionₜ)
Sₜ₊₁ = Reduce(Sₜ, validated_actionₜ, observationₜ)
Cₜ₊₁ = Assemble(Sₜ₊₁, ...)

这是工程抽象,不是任何特定 API 的调用协议。其关键在于:**模型看到的 Cₜ 是状态的投影,而 Sₜ 不应等同于模型自己生成的叙述。**例如,审批是否通过,应以审批系统记录为准;模型在摘要中写“已审批”不能改变审批事实。

对象典型内容权威存储位置是否必须进入当前模型输入
Instruction系统规则、开发者指令、输出要求可信配置与请求结构相关规则通常必须
Runtime State阶段、任务 ID、审批状态、已执行操作状态机、数据库、检查点仅相关投影
Conversation History用户与助手的历史交互会话存储不必全部
Memory稳定偏好、长期经验、跨任务事实Memory Store按需检索
Knowledge文档、网页、论文、证据文档库、搜索索引、证据库按需引入证据
Tool Observation搜索结果、API 响应、执行日志运行日志、工件存储仅当前决策相关部分
Assembled Context本次调用真正提交的信息请求载荷、可选调试记录是

因此,“Context Window”指模型可接收的上下文容量约束;“Context”指实际输入;“Context Engineering”指如何生成和维护这一输入。有关模型内部注意力、位置编码和长上下文模型架构的研究,应与 AI → E3 · Context Window 交叉引用,不在此重复展开。

1.1 上下文的三种正确性 ​

上下文是否合格,至少需要区分三种正确性。内容正确性:事实、版本、条件是否准确。决策充分性:是否覆盖本次决策必需的约束与证据。权威正确性:用户消息、工具输出、网页片段与系统规则是否以正确的信任边界呈现。一个上下文即使全部是事实,也可能遗漏关键审批约束;即使足够全面,也可能把网页中的恶意指令误当作系统指令。

1.2 为什么不能把所有信息塞进去 ​

“更多上下文”不是单调增加的收益函数。加入一段材料可能带来新证据,也可能引入重复、过时事实、相互冲突的定义和注意力竞争。长上下文中的位置效应表明,相关信息在输入中的位置可能影响模型利用效果;具体幅度取决于模型与任务,不能将某篇论文的实验结论直接视为所有模型的固定规律。工程目标应是最小充分上下文(minimum sufficient context):在满足必要信息覆盖与质量要求的前提下,控制输入成本。

02 · 一次模型调用前究竟发生什么:上下文装配运行机制 ​

把装配过程拆成七个可观察阶段,比只在提示词中拼接若干字符串更容易开发与调试。

text
Task + Authoritative State
          │
          ▼
① Decision Contract(本轮需要模型决定什么)
          │
          ▼
② Candidate Acquisition(历史/记忆/证据/工具/状态投影)
          │
          ▼
③ Eligibility Filter(作用域、版本、时效、权限、去重)
          │
          ▼
④ Relevance + Coverage + Risk Scoring
          │
          ▼
⑤ Budgeted Selection(强制保留 + 优化选择)
          │
          ▼
⑥ Ordering + Serialization(分区、来源标签、输出契约)
          │
          ▼
⑦ Validation + Model Call + Trace
          │
          ▼
Output Validation → State Update → Next Turn

2.1 Decision Contract:先定义本轮决策 ​

同一个研究任务中的“搜索下一篇论文”“核查某条证据”“撰写结论”需要不同的上下文。可以用一个决策契约明确本轮目标:

json
{
  "step_id": "research-42/verify-claim-7",
  "decision_type": "verify_claim",
  "question": "这项 API 是否支持跨进程恢复?",
  "required_facts": ["目标框架及版本", "原始证据", "恢复前置条件"],
  "required_constraints": ["不得把推测写成已验证事实"],
  "allowed_tools": ["read_document", "search_docs"],
  "output_schema": "ClaimAssessmentV1"
}

如果跳过这一步,系统很难判断哪些上下文是“重要的”。相关性必须相对于当前决策定义,而不是仅相对于整个项目标题定义。

2.2 Candidate Acquisition:候选是数据对象,不是裸字符串 ​

候选片段应具有稳定 ID、来源、作用域、时间、版本、token 估计、重要性和可信边界。例如:

json
{
  "id": "evidence:E-109",
  "kind": "evidence",
  "source_id": "doc:official-v2",
  "locator": "section/persistence#paragraph-3",
  "task_scope": "research-42",
  "content": "<原文片段>",
  "estimated_tokens": 96,
  "relevance": 0.93,
  "importance": 0.85,
  "freshness": 0.90,
  "trust_class": "external_data",
  "version": "v2",
  "must_include": false
}

trust_class 用于决定如何包装和处理内容,而不是将“官方文档”自动升级为高优先级指令。工具返回的文本即使来自可信服务,仍属于数据载荷,不能改写系统规则。

2.3 Eligibility Filter:先排除不合格候选 ​

在计算语义相关性之前,应执行确定性过滤。例如:候选是否属于当前用户和项目;是否在允许的数据访问范围;是否对应当前软件版本;是否已被更新版本替代;是否存在重复的内容哈希;是否已被撤销。授权和作用域检查不能由“相关性高”覆盖。

对于存在冲突的两条事实,不应无痕合并。可以同时保留两个版本并标注差异,也可以先暂停回答并触发冲突解决流程。

2.4 选择、排序与序列化 ​

选择器先保留不可缺失的指令、当前任务契约和关键状态,再在剩余预算内选择证据与历史。排序器将规则、任务、权威状态、证据、工具观察和输出契约分区。最后序列化为具体模型接口要求的消息结构。分区是工程约定,不代表所有模型 API 都提供相同的角色或消息类型。

2.5 调用后的状态回写 ​

模型生成的“下一步行动”不应直接成为权威状态。执行器验证动作、调用工具、记录观察,然后更新任务状态。下一轮上下文从新状态重新构建。这样即使旧消息被截断,关键任务事实也不会随之丢失。

03 · 选择算法:相关性、覆盖度与 token 预算如何共同作用 ​

上下文选择可抽象为一个带约束的集合优化问题。设候选集合为 D,候选 i 的 token 成本为 cᵢ、相关性为 rᵢ、重要性为 pᵢ、新鲜度为 fᵢ,选择变量 xᵢ∈{0,1},可用预算为 B:

max∑ixi(αri+βpi+γfi)s.t. ∑icixi≤B

这是简化的工程目标函数,不是论文中统一认可的 Context 选择公式。它能表达“价值与成本”的基本取舍,但尚未处理重复信息与证据覆盖。若两个候选都在重复同一事实,简单加分会让系统浪费预算。

3.1 覆盖度:为什么不能只选分数最高的片段 ​

假设当前决策必须回答三个问题:A“当前版本”、B“持久化条件”、C“恢复限制”。候选如下:

候选相关性覆盖问题token 成本
D10.98A100
D20.96A100
D30.85B120
D40.81C100

预算为 320 token。按相关性选 D1、D2、D3 会遗漏 C;选 D1、D3、D4 则覆盖全部关键问题。因此需要在候选效用中加入边际覆盖增益,而不是只使用静态评分。

一个实用的贪心策略是:每轮选择 新增覆盖收益 + 内容价值 − 冗余惩罚 相对于 token 成本最高的候选,直到预算耗尽或关键问题被覆盖。对于有严格依赖关系或复杂约束的场景,可以进一步采用整数规划或分阶段选择,但不必在小规模任务中默认使用复杂求解器。

3.2 强制保留与可压缩内容必须分开 ​

优先级不应只由单一评分决定。建议至少划分三类:

  • 不可随意裁剪:适用规则、用户明确要求、当前任务契约、必要审批状态、输出协议。
  • 应优先保留:当前步骤必需证据、未解决冲突、最新工具失败原因、执行前置条件。
  • 可替换或压缩:较早的聊天历史、重复的检索片段、已形成可靠工件的中间讨论。

如果不可裁剪部分本身超出预算,应返回预算错误或改变执行策略(如拆分任务),而不是悄悄删除规则。

3.3 Token 估算与真实计费 ​

estimated_tokens 应由目标模型对应的 tokenizer 或供应商计数接口计算;没有对应工具时只能使用近似估算。消息角色、工具 schema、图片和音频载荷都可能影响实际计数。字符数不等于 token 数,尤其在中文、多模态和结构化请求中。预算还必须预留输出 token 与安全余量;“最大上下文窗口”不等于“可用于检索片段的容量”。

3.4 选择算法的工程取舍 ​

策略机制优点主要失效点
最近 N 轮保留最近消息简单、低延迟早期关键约束丢失
相关性 Top-k按语义或规则评分聚焦当前问题可能遗漏互补证据
贪心覆盖计算边际覆盖与成本控制冗余、提高覆盖依赖准确的需求标签
分层预算为规则/状态/证据设配额行为可预测固定配额可能浪费容量
动态路由按决策类型选不同装配器适合复杂工作流维护与测试成本增加

推荐从“强制保留 + 确定性过滤 + 贪心覆盖 + 可观测预算”起步;只有评测显示明显不足时,再增加模型辅助选择或复杂优化。

04 · 消息历史管理:为什么聊天记录不能代替状态机 ​

聊天历史记录了“谁说过什么”,但不保证能够回答“系统现在处于什么状态”。例如模型曾说“准备提交审批”,不等于审批已提交;用户曾说“我同意”,也可能指向上一版本的方案。可靠系统需要**事件记录(event log)与权威状态(state)**分离。

text
Event Log: user_requested → plan_created → tool_started
           → tool_failed → tool_retried → approval_granted
                               │
                               ▼
State Reducer: 按确定性规则更新任务状态
                               │
                               ▼
Current State: phase=execution, approval=granted, retry_count=1
                               │
                               ▼
Context Projection: 本轮仅暴露必要状态与相关事件

事件日志可用于审计和回放,状态投影可用于当前决策。摘要则是方便模型理解的自然语言辅助表示,不能成为修改权威状态的唯一来源。

4.1 滑动窗口:适用条件与隐藏风险 ​

滑动窗口保留最近 N 条消息或最近 T token,适合短任务和局部对话,但其核心假设是“越近越重要”。这一假设在长期任务中经常失效:早期用户要求的验收标准、权限边界和重要设计决策可能远比最近的十条工具日志重要。改进方式是把不可丢失的任务契约与状态单独保存,并只对普通历史使用滑动窗口。

4.2 历史摘要:压缩并非简单缩短 ​

摘要需要保留决策相关信息,而不是平均缩短所有对话。对研究任务,一份合格的历史摘要至少应保留:当前目标、已确认决定、关键证据 ID、未解决问题、最近失败、下一步以及用户明确的修改。它不应把“模型建议”误写为“用户批准”,也不应把“可能”改写为“确定”。

建议使用结构化摘要:

json
{
  "task_goal": "比较三个框架的恢复能力",
  "confirmed_decisions": ["比较版本固定为某发布日期"],
  "verified_facts": [{"claim_id": "C7", "evidence_ids": ["E2"]}],
  "open_questions": ["恢复时是否重复执行外部工具"],
  "last_failure": {"tool": "read_pdf", "reason": "document_unavailable"},
  "next_action": "获取原始文档或标记证据缺失",
  "summary_version": 3
}

4.3 摘要漂移的形成机制 ​

设原始事件为 H,第一次摘要 S₁=Summarize(H),第二次摘要 S₂=Summarize(S₁+新事件)。如果 S₁ 已遗漏某项限定,后续模型只能在不完整信息上继续摘要;多轮压缩可能逐步扩大误差。常见漂移包括:删除否定词、丢失时间条件、把未核实事实写成结论、把多个主体混为一人。

缓解方法不是“让模型更认真”,而是改变数据路径:从原始事件与结构化状态重新生成摘要,保留关键字段的不可压缩副本,给摘要附上来源事件 ID,周期性执行差异核对。摘要生成应采用可验证的输入,而不是只在上一版摘要上无限迭代。

4.4 Compaction 与 Fork ​

当历史过长时,可以创建一个新的执行上下文:保留任务契约、权威状态、已核实证据和未解决问题,舍弃大部分原始对话,再继续执行。这可称为上下文压缩或 compaction。若同时保留原分支和新分支,就形成 fork;应记录分支父节点、状态版本和共享工件,避免两个分支把相互矛盾的决定同时写回主任务。

05 · 证据进入 Context:来源、定位与模型可用性 ​

外部知识检索(A6)负责找到资料、提取证据;上下文装配负责决定哪些证据在本轮进入模型、以什么顺序呈现、如何保留可追溯标识。不能把检索 Top-k 直接等同于上下文 Top-k。

5.1 Chunking 对上下文的影响 ​

文档检索通常以 chunk 为单位,但 chunk 边界可能切断定义、条件或表格标题。一个片段说“支持恢复”,前一段却写“仅在启用数据库持久化后”。如果装配器只放入前者,模型可能形成错误结论。应允许基于文档结构扩展相邻片段(parent-child retrieval、section expansion 等工程策略),并在预算中计算扩展成本。

5.2 证据包装格式 ​

text
[EXTERNAL_EVIDENCE]
Evidence ID: E-17
Source: official-documentation / document-id=DOC-9
Version: 2.x
Locator: section=persistence, paragraph=4
Retrieved: 2026-10-28
Content: <证据原文>
[/EXTERNAL_EVIDENCE]

这样的包装帮助模型区分外部数据与指令,并为后续引用建立定位。但标注本身不能保证模型正确使用证据,仍需要结论-证据关系检查。

5.3 证据冲突不能靠排序消失 ​

如果两个版本的文档给出不同结论,简单选得分最高的片段可能掩盖冲突。应先确定目标版本;如果版本未明确,装配器可把冲突对同时保留,并要求模型回答“取决于版本”,或触发进一步核查。对于关键主张,可以将 supporting_evidence 与 contradicting_evidence 同时注入。

5.4 Context Poisoning 与 Prompt Injection ​

网页、邮件、PDF 和工具输出可能包含“忽略前面的规则”等文本。这些内容可以作为待分析的数据出现,但不应取得系统指令权限。实际防护需要结合接口角色隔离、来源标识、工具权限校验、输出动作验证和敏感操作审批。单靠在提示词中写“不要相信外部内容”并不足够。此处只讨论上下文边界,完整的工具权限模型见 A10 · Permissions & Constraints。

06 · 排序与位置:同样的证据为什么会得到不同效果 ​

装配完成后,候选的排列方式仍会影响模型行为。相关研究(如 Lost in the Middle)指出,部分模型在长输入中对位于开头或结尾的信息利用较好,中间位置的利用可能下降;这不是所有模型、任务与长度下的固定定律。

6.1 实用排序原则 ​

首先,保持角色与规则的正确层级,不用字符串顺序伪装高优先级。其次,将当前任务契约、必须满足的约束和关键状态放在易识别的位置。再次,将证据按问题分组,而不是把无关片段交错排列。最后,让输出契约明确说明需要怎样引用证据、怎样表达不确定性。

一个用于证据核查的序列化布局可以是:

text
[TRUSTED TASK CONTRACT]
当前核查问题 + 目标版本 + 输出要求

[AUTHORITATIVE STATE]
当前任务阶段 + 已确认事实 + 未解决冲突

[EVIDENCE FOR Q1]
E1 ...
E2 ...

[CONTRADICTING EVIDENCE]
E3 ...

[REQUEST]
逐项判断主张是否得到支持;保留证据 ID;无法确认则明确说明

注意:这只是内容布局示例,实际应映射为供应商接口支持的消息结构,不能依赖纯文本标签实现真正的权限隔离。

6.2 如何验证排序是否有效 ​

固定任务、模型、证据集合和生成参数,仅改变证据位置,比较事实准确率、引用准确率与漏掉关键条件的比例。对于随机性较高的模型调用,应多次重复并报告波动。不能仅凭一次人工观察断言某种排序“最优”。

07 · Token 预算:从容量计算到分配策略 ​

假设目标模型的有效请求预算为 W,预留输出为 O,安全余量为 R,固定规则与工具定义为 F,则可用于动态上下文的预算为:

Bdynamic=W−O−R−F

例如,假设某部署环境给定 W=16,000、O=2,000、R=1,000、F=3,000,则动态预算为 10,000 token。这些数值仅用于计算演示,不代表任何具体模型的实际窗口或计费方式。

在动态预算内可以按决策类型分配:检索阶段给查询背景与最近观察更多空间;证据核查阶段优先证据原文和来源;报告写作阶段优先论证结构、已确认主张与引用索引。固定配额可作为初始策略,但应允许在最低保留约束之上动态调整。

7.1 截断的正确顺序 ​

通常应先删除重复片段,再删除无关历史;之后压缩低价值观察或较早讨论;必要时把大文档转换为外部工件引用;最后才考虑拆分任务。不要在预算不足时直接截断字符串尾部:这种方式可能切断 JSON、删除否定条件或留下不完整证据。

7.2 工具定义也是预算项 ​

Agent 注册几十种工具时,工具名称、描述、参数 schema 可能占用显著上下文。可以按任务阶段暴露最小可用工具集,而不是每轮都提交全部工具定义。注意:工具路由与权限是不同概念,隐藏工具描述不能替代服务端权限控制。

7.3 Prompt Caching 与 KV Cache 的边界 ​

Prompt caching 通常指服务端对可复用输入前缀或相关计算进行缓存,可能降低重复调用的成本或延迟,具体行为取决于供应商和接口。KV Cache 是 Transformer 推理过程中用于复用注意力键值表示的机制;它属于模型推理实现层面,不等于应用持久化的任务状态,也不保证跨请求或跨进程可用。Context compaction 则是应用层缩减模型输入的策略。三者解决不同问题,不能互相替代。

08 · 工具调用循环中的 Context:观察、失败与恢复 ​

典型工具循环是:模型收到上下文 → 提议工具调用 → Runtime 验证与执行 → 返回工具观察 → 装配下一轮上下文。工具输出往往很长,例如搜索结果几十条、网页全文、数据库数千行。将原始结果完整回灌模型既昂贵又容易产生噪声。

8.1 Tool Observation Adapter ​

建议在工具结果进入上下文之前增加适配层:

text
Raw Tool Output
   │
   ├─ parse: 解析状态码、结构化字段和错误类型
   ├─ normalize: 统一来源 ID、时间、版本
   ├─ extract: 提取当前决策所需字段
   ├─ store: 原始响应写入工件存储
   └─ summarize: 生成有限长度的模型可读观察
   │
   ▼
Context Candidate + Artifact Pointer

例如,搜索工具返回 100 个结果时,模型可能只需要前 5 个高相关来源、每个来源的摘要、检索时间和原始结果工件 ID。若后续需要深入研究某一结果,再通过工具读取完整原文。

8.2 错误信息应保留可恢复性 ​

错误观察不能只写“失败了”。至少应包含工具名称、失败类别、是否可重试、关键错误码、已执行次数、是否存在外部副作用,以及下一步允许的恢复方式。对于支付、发邮件、创建记录等具有副作用的工具,模型上下文中的“可能未执行”不足以判断是否应该重试;必须查询权威执行记录或幂等键状态。

8.3 大工件的间接引用 ​

长日志、PDF、网页、图片分析结果可以保存在工件存储,并向模型提供稳定的 artifact_id、结构摘要和按需读取工具。这样可避免每轮重复注入整个工件。前提是运行时能确保引用有效、访问范围正确,并且工具读取操作可用。

09 · 多模态 Context:文本以外还需要哪些表示 ​

图片、音频、视频和结构化空间数据可能采用不同的输入编码与计费方式。工程上不能假设“图片转成一句文字描述”能够完整保留原始信息。例如,图表中的坐标、标注、图例与局部细节,可能在摘要中丢失;扫描 PDF 的版面关系和表格结构也可能因文本提取而失真。

推荐将多模态输入拆分为:原始资产引用、可检索的结构化元数据、用于当前任务的局部解释。如果需要回答“图表中第三条曲线何时超过第二条”,应优先保留可检查的图像或结构化数据,而不是只注入概括性图片描述。对时间序列视频,还需要时间戳、片段边界和采样策略。

多模态上下文的具体序列化由模型 API 决定;本文不假定所有模型都支持相同的图片、音频或视频载荷。

10 · 长任务与断点恢复:Context 如何重新生成 ​

长期任务的关键不是让模型永远记住全部历史,而是让 Runtime 在任何一次新调用前,能够从持久化状态和工件中重新构建足够的上下文。

10.1 建议的持久化对象 ​

text
Task Contract       任务目标、验收标准、约束、版本
Runtime Checkpoint  阶段、步骤、审批状态、预算、重试状态
Event Log           工具调用与用户操作的事件序列
Evidence Store      来源、证据、主张与支持关系
Artifact Store      长文档、日志、报告草稿
Context Trace       每轮装配的候选、选择、预算与版本

这些对象不必使用不同数据库,但应在逻辑上区分。特别是 Context Trace 只用于解释模型当时看到了什么,不应成为任务事实的唯一来源。

10.2 恢复过程 ​

text
Process Restart
      │
      ▼
Load Checkpoint + Verify Task Version
      │
      ▼
Reconcile External Side Effects
      │
      ▼
Determine Next Decision Contract
      │
      ▼
Retrieve Relevant Evidence / Artifacts
      │
      ▼
Assemble Fresh Context
      │
      ▼
Continue Execution

假设研究 Agent 在第 14 次检索后崩溃。恢复时不需要把此前全部 14 次搜索的原始响应都塞入模型,而应读取:当前研究问题、已核实证据索引、尚未解决的缺口、最近失败与下一步计划。只有当前决策确实需要某份原文时,再按工件 ID 读取。

10.3 上下文版本与可重放性 ​

要复现一次错误决策,需要知道当时使用的任务版本、模型与参数、候选集合、选择策略、token 估计、实际提交内容以及工具返回结果。即使保存了相同上下文,也不一定能得到字节级相同的模型输出;模型版本、采样和服务端行为可能影响结果。因此,应把“可重建输入”和“可确定性重放输出”区分开。

11 · 代表性研究与工程技术路线 ​

11.1 Lost in the Middle:信息位置影响长上下文利用 ​

Liu 等人的 Lost in the Middle 研究了语言模型在长输入中利用相关信息的表现,展示了在某些测试设置下,相关信息位于输入中间时性能可能下降。其工程启示不是“所有重要内容必须放开头”,而是:长上下文的容量指标不能代替真实任务上的证据定位评测。实际系统应测试不同长度、位置和证据密度,并对目标模型分别评估。

11.2 LongMem 与外部记忆:把历史存储与当前输入分离 ​

LongMem 等研究探索将长期历史信息与当前模型处理过程解耦,体现出一种重要方向:不必让所有历史信息都直接占用当前输入窗口。对于 Agent 工程,相关思想可以体现为外部工件、记忆索引和按需检索。但论文中的模型级机制与应用层 Memory Store 不应直接等同;本篇只提取其对上下文架构的启发,长期记忆机制见 A5。

11.3 MemGPT:分层信息管理与上下文交换 ​

MemGPT 将有限上下文与外部存储的关系类比为分层存储管理。其重要启发是:把“当前可见的信息”和“可按需调入的信息”分开,并通过明确的操作管理信息移动。Agent Context 的工程实现可以借鉴其层次化思路,例如把任务契约、工作摘要、外部工件和历史资料分层存储;但这种架构借鉴不等于复现 MemGPT 的原始实现。详细研究见 A5。

11.4 LangGraph Persistence:运行状态与模型上下文分离 ​

LangGraph 的持久化与检查点机制展示了将执行状态保存于运行时、并在后续步骤继续使用的工程路径。其对 Context 的启发是:通过状态对象与节点执行边界构建每轮模型输入,而不是仅依赖不断增长的消息历史。具体 API、存储后端与版本行为必须按实际部署版本核验;本文不将某个版本的 API 写成长期不变的规范。

11.5 三种主要工程架构比较 ​

架构核心机制适用场景主要限制
全历史回灌每轮发送大量历史消息短任务、低复杂度原型成本随历史增长,状态混淆
摘要 + 最近窗口旧历史压缩,保留近期消息中等长度对话任务摘要漂移,关键证据可能丢失
状态驱动动态装配依据当前决策检索并构建输入长任务、工具密集型研究 Agent需要数据契约、选择器和测试体系

对于复杂研究系统,第三种更值得作为架构基线;但如果任务简单,额外的状态管理成本未必合理。

12 · 工程实现:最小可运行 Context Assembler ​

下面的 Python 示例只使用标准库,实现一个可执行的上下文候选选择器,重点验证:强制保留、预算控制、覆盖增益、作用域过滤、去重和稳定排序。它不调用 LLM,也不声称能实现真实模型 tokenizer、语义检索或安全沙箱。示例中的 cost 是人工给定的预算单位,不能当作真实 token 计数。

python
from dataclasses import dataclass
from typing import FrozenSet

@dataclass(frozen=True)
class Item:
    id: str
    text: str
    cost: int
    value: float
    covers: FrozenSet[str]
    scope: str
    mandatory: bool = False

def assemble(items, budget, scope, required):
    """Greedy budgeted coverage selection; cost is an abstract unit."""
    eligible = [x for x in items if x.scope in (scope, "global")]
    unique = {x.id: x for x in eligible}
    pool = list(unique.values())
    fixed = [x for x in pool if x.mandatory]
    if sum(x.cost for x in fixed) > budget:
        raise ValueError("mandatory items exceed context budget")

    chosen = fixed[:]
    used = sum(x.cost for x in chosen)
    covered = set().union(*(x.covers for x in chosen)) if chosen else set()
    remaining = [x for x in pool if not x.mandatory]

    while remaining:
        fitting = [x for x in remaining if x.cost <= budget - used]
        if not fitting:
            break
        def score(x):
            new = len((set(x.covers) & set(required)) - covered)
            return (x.value + 2.0 * new) / max(x.cost, 1)
        best = max(fitting, key=lambda x: (score(x), x.id))
        chosen.append(best)
        used += best.cost
        covered.update(best.covers)
        remaining.remove(best)

    missing = set(required) - covered
    return {
        "selected_ids": [x.id for x in chosen],
        "used_budget": used,
        "missing_requirements": sorted(missing),
        "context_text": "\n\n".join(f"[{x.id}] {x.text}" for x in chosen),
    }

if __name__ == "__main__":
    items = [
        Item("rule", "不得把未验证信息写成事实", 30, 1.0,
             frozenset(), "global", True),
        Item("A1", "版本信息", 90, 0.98, frozenset({"A"}), "task-1"),
        Item("A2", "重复的版本信息", 90, 0.96, frozenset({"A"}), "task-1"),
        Item("B1", "持久化前置条件", 110, 0.85, frozenset({"B"}), "task-1"),
        Item("C1", "恢复限制", 90, 0.81, frozenset({"C"}), "task-1"),
        Item("other", "另一个项目的私有资料", 20, 1.0,
             frozenset({"B", "C"}), "task-2"),
    ]
    result = assemble(items, 330, "task-1", {"A", "B", "C"})
    assert result["used_budget"] <= 330
    assert "rule" in result["selected_ids"]
    assert "other" not in result["selected_ids"]
    assert result["missing_requirements"] == []
    print(result)

12.1 代码机制拆解 ​

第一步,eligible 按任务作用域过滤,避免其他任务的候选进入本轮选择。第二步,以 id 去重;真实系统应另外处理同内容不同 ID 的重复候选。第三步,强制保留 mandatory,并在其超预算时抛出错误。第四步,对剩余候选计算边际覆盖增益,优先选择能填补尚未覆盖问题的材料。第五步,输出选择 ID、预算占用、未覆盖需求和序列化文本,便于调试。

这个算法是贪心启发式,不保证全局最优。它也没有实现来源可信度评价、事实冲突检测、真实 token 计数和语义评分。在生产系统中,应把这些作为独立模块加入,而不是将此示例误认为完整的上下文管理平台。

12.2 最小实现与生产架构之间的差距 ​

维度示例实现生产系统需要增加
预算人工 cost目标模型 tokenizer/计数接口与输出预留
相关性人工 value检索评分、重排或任务相关性评估
去重ID 去重内容哈希、近重复检测
作用域简单字符串匹配用户/项目/资源授权校验
覆盖人工标注 covers从 Decision Contract 派生的需求标签
证据简单文本来源、版本、定位、支持关系
历史无事件日志、摘要、检查点
可观测性返回选中 ID完整 trace、评测指标、版本记录

13 · 贯穿案例:研究助理 Agent 的五轮上下文变化 ​

假设研究 Agent 正在比较三个 Agent 框架的恢复机制。项目持有完整的研究计划、几十份文档和数百条历史事件,但每轮上下文应随决策变化。

**第 1 轮:研究问题拆解。**需要用户目标、项目约束、已知研究范围和输出契约;不需要加载所有原始文档。模型输出研究问题列表,Runtime 将其保存为结构化任务工件。

**第 2 轮:检索来源选择。**需要当前研究问题、已检索来源索引、工具能力与预算;不需要完整的早期讨论。模型决定查询,Runtime 通过工具执行搜索并保存原始结果。

**第 3 轮:证据核查。**需要某一具体主张、目标版本、原始证据片段及可能冲突的资料;不需要所有检索结果。模型判断证据支持程度,结构化结果关联 Evidence ID。

**第 4 轮:异常恢复。**假设文档读取工具失败,Runtime 记录失败类别和重试状态。下一轮上下文包含失败原因、可用替代来源、已尝试次数及禁止重复副作用的约束,而不是简单重复“请继续研究”。

**第 5 轮:形成报告。**需要已核实的 Claim-Evidence 关系、尚未解决的研究问题、报告结构和用户要求。完整原始资料仍保留在工件库中,仅在模型需要引用或核查时按需读取。

由此可见,同一个任务的 Context 不是不断叠加的统一文本,而是对不同决策类型生成的多个工作视图。这种架构的可维护性来自:任务状态可重建、证据可回溯、上下文选择可观察。

14 · 评估体系:如何证明上下文工程确实有效 ​

上下文管理需要同时评估输入质量、模型行为和系统成本。仅测“是否超出 token 窗口”无法说明是否正确。

14.1 信息覆盖与噪声 ​

Required Fact Recall:当前决策所需的关键事实有多少进入上下文。Irrelevant Token Ratio:与本轮决策无关的输入占比。Evidence Traceability:关键事实是否保留可回溯的证据 ID。Conflict Visibility:存在重大冲突时是否向模型显式呈现。

14.2 模型决策质量 ​

测试模型是否遵守任务约束、是否遗漏重要条件、是否正确引用证据、是否在证据不足时承认不确定性,以及工具选择是否合理。指标必须结合人工标注或可验证的参考结果,不能仅由同一个模型给自己打分。

14.3 系统成本与稳定性 ​

记录每轮输入/输出 token、缓存命中情况(如果接口支持)、模型延迟、上下文装配耗时、工具结果截断率、恢复成功率和错误重试次数。成本降低但事实错误率显著上升,不应视为优化成功。

14.4 必须做的对照实验 ​

在同一任务集、相同模型和知识来源下比较:

实验组装配策略研究目的
Baseline A全历史回灌测量无策略的成本与效果
Baseline B最近窗口 + 摘要测量简单压缩收益
Variant C相关性 Top-k测量选择收益
Variant D状态驱动 + 覆盖选择测量机制组合收益

进一步做消融实验:移除权威状态、移除来源定位、移除冲突证据、改变证据位置、缩减预算、注入长工具结果。观察错误来自哪个环节。尤其需要测试跨轮约束保留与崩溃后恢复,这两类任务比单轮问答更能体现 Agent Context 的实际价值。

14.5 故障注入测试 ​

至少覆盖:历史超长、工具输出超长、重复证据、过时版本、证据互相矛盾、摘要丢失否定条件、跨项目候选混入、预算不足、外部文本包含恶意指令、运行中断后恢复。每个用例应有预期的状态变化和明确的失败判定标准。

15 · 常见失败机制与诊断路径 ​

症状可能机制优先排查
Agent 忘记早期用户约束仅保留最近窗口任务契约是否独立保存并强制注入
Agent 把未确认事项写成事实摘要漂移、缺少证据状态Claim 状态和来源是否进入上下文
Agent 重复调用同一工具失败观察或执行状态丢失事件日志、重试次数、幂等记录
Agent 引用错文档chunk 失去定位、来源标签丢失Evidence ID、版本和原文定位
输入很长但回答不完整噪声、位置效应、覆盖不足token 分布、候选选择与位置消融
Context 预算经常溢出固定工具 schema 过大、原始结果回灌工具动态暴露、工件间接引用
恢复后任务阶段错乱依赖聊天摘要重建状态检查点与权威状态恢复流程
模型执行了网页里的指令外部数据越过信任边界消息角色、动作验证和权限控制

诊断时应优先检查装配 trace:本轮任务是什么、哪些候选被过滤、哪些被选中、预算如何分配、模型实际看到了什么。没有 trace,问题很容易被误归因于“模型不够聪明”。

16 · 设计决策与技术选型 ​

对早期原型,推荐从简单、可验证的装配器开始:结构化任务契约 + 权威状态 + 最近消息 + 必需证据 + 预算上限。不要一开始就引入复杂的模型评分器、跨来源自动总结和多级缓存,因为每增加一层转换都可能引入信息损失和调试成本。

当出现明确的长任务问题,再逐步引入:结构化摘要、按需证据检索、候选覆盖优化、工件引用、上下文 trace 和恢复机制。升级依据应是评测中真实出现的遗漏、成本或恢复问题,而不是“技术栈越复杂越先进”。

对于研究 Studio 类多阶段工作流,一个可维护的职责划分是:**Orchestrator 管理执行与权威状态;Knowledge 管理来源与证据;Memory 管理长期可复用信息;Context Assembler 只负责本轮输入投影;Model 负责基于投影推理;Tool Runtime 验证并执行动作。**这既能避免所有信息都堆入提示词,也能避免把模型输出当作系统事实。

17 · 核心结论 ​

  1. Context 是单次模型决策的输入视图,不是聊天历史、知识库或运行状态的同义词。
  2. 上下文装配应当是显式、可测试的运行时管线,包含决策契约、候选获取、资格过滤、预算选择、排序序列化与调用后状态更新。
  3. 选择策略必须同时考虑相关性、覆盖度、冗余和成本;单纯 Top-k 可能遗漏关键互补证据。
  4. 摘要是信息压缩产物,不是权威事实存储;应从原始事件与结构化状态生成,并保留可追溯来源。
  5. 工具输出与检索内容是低于系统指令的数据载荷,必须在权限和动作验证层维持信任边界。
  6. 长期 Agent 的连续性来自持久化状态与按需重建上下文,而不是无限增长的提示词。
  7. Context Engineering 的最终评估标准是任务质量、可恢复性与成本的综合表现,而不是上下文窗口的利用率。

参考资料与关联研究 ​

以下列出与本专题机制直接相关的原始研究和官方资料入口。本次修订未进行实时逐项核验;链接为已知资料入口,具体内容、版本与最新 API 应在正式实施时重新确认。

  1. Liu et al., Lost in the Middle: How Language Models Use Long Contexts (2023/2024). https://arxiv.org/abs/2307.03172 - 长上下文信息位置与利用效果。
  2. Packer et al., MemGPT: Towards LLMs as Operating Systems (2023). https://arxiv.org/abs/2310.08560 - 分层记忆、有限上下文与外部信息交换。
  3. Wang et al., LongMem: Scaling Language Models with Long-Term Memory (2023). https://arxiv.org/abs/2306.07174 - 长期记忆与模型处理过程解耦的研究方向。
  4. Park et al., Generative Agents: Interactive Simulacra of Human Behavior (2023). https://arxiv.org/abs/2304.03442 - 记忆流、检索与反思,关联 A5。
  5. LangGraph Documentation, Persistence. https://docs.langchain.com/oss/python/langgraph/persistence - 状态持久化与检查点的官方文档入口。
  6. OpenAI Platform Documentation, Conversation State. https://platform.openai.com/docs/guides/conversation-state - 会话状态管理的官方文档入口。
  7. Anthropic, Building Effective Agents. https://www.anthropic.com/engineering/building-effective-agents - Agent 工作流与工程实践。
  8. A3 · Instructions - 指令结构与优先级;A5 · Memory - 长期记忆;A6 · Knowledge - 外部证据;A7 · Tools - 工具调用;AI → E3 · Context Window - 模型窗口与推理机制。

研究声明 ​

研究与验证说明 ​

本文以 A4 v1.0 的既有研究边界和主题为基础,依据《Agent 全栈技术地图》更新后的深度研究原则重写,重点新增了上下文选择的优化建模、覆盖增益机制、候选数据结构、摘要漂移的数据路径、状态恢复、工具观察适配器和可运行的选择器示例。部分架构、公式和数据契约属于本文提出的工程抽象,不是特定论文或厂商的原始定义。

最新性状态 ​

研究基准日期为 2026 年 10 月 28 日。本次修订未实时逐项查阅参考论文的最新版本、官方 API 变更日志或供应商当前计费规则;因此,不对最新接口参数、上下文窗口容量和缓存价格作未经核验的断言。

实验与适用边界 ​

第 12 节为不依赖外部服务的标准库示例;其算法使用抽象成本而非真实 tokenizer,不能直接证明模型端到端效果。本文未执行模型 API 对照实验或大规模检索基准测试。真实部署应补充目标模型计数器、作用域授权、证据定位、事件存储、运行时 trace 与故障注入测试,并通过任务级评测确认收益。