构建 Agent 应用时,最初的优化往往集中在提示词:调整角色描述、增加规则、提供更多示例。当任务仍然失败,团队继续把文档、历史消息和工具说明塞进输入,期待模型因为“知道更多”而表现更好。

上下文变长后,成本和延迟上升,关键约束反而更容易被淹没。真正的问题不是信息不足,而是没有为当前任务组织信息。

上下文工程关注的不只是一段 Prompt,而是信息从进入系统、被选择、压缩、使用到沉淀的完整生命周期。

上下文候选信息经过权限、相关性、新鲜度和预算筛选后进入模型

图 1:上下文组装器的工作不是把信息全部拼起来,而是为当前子任务选择最少但充分的输入,并保留来源与版本。

上下文是一种运行时资源

模型上下文与内存、连接数一样有限。即使窗口足够大,注意力也不是均匀分配。无关信息会增加噪声,相互矛盾的信息会迫使模型猜测,重复信息会浪费成本。

每个任务应有上下文预算。系统先放入不可违反的规则和当前目标,再加入完成任务所需事实、工具和少量相关示例。其余材料通过检索或工具按需获得。

预算需要可观测:固定指令、对话历史、检索材料、工具结果分别占用多少,哪些内容最终被引用。没有这些数据,团队只能凭感觉缩短 Prompt。

上下文还具有时间属性。用户刚刚确认的要求优先于早期假设,实时数据不能被旧缓存覆盖,已经失效的工具说明不应继续出现。信息新旧和来源可信度都应该成为选择条件。

分层组织,而不是拼接字符串

一份可靠上下文至少可以分为五层:系统规则定义行为边界;任务说明定义当前目标与完成标准;领域状态保存经过确认的事实;检索材料提供证据;工作记忆保存本次执行的中间产物。

不同层有不同写入权限。用户和系统可以修改目标,工具产生原始证据,验证步骤才有权把事实写入领域状态,临时推理不应自动成为长期记忆。

这种分层避免“模型说过的话”被误认为事实。每条长期记忆附带来源、创建时间、适用范围和置信状态。下次检索时,系统可以判断是否仍然有效。

上下文组装也应结构化。使用明确标题、Schema 和引用标识,让模型区分规则、事实与待解决问题。字符串模板只是最终序列化形式,内部应该保存可单独筛选和测试的数据对象。

检索需要理解任务意图

RAG 经常被简化为“切块、向量化、取前 K 条”。语义相似并不等于对当前任务有用。用户问“为什么这个版本性能下降”,需要的可能是变更记录、性能指标和架构说明,而不是包含“性能”一词最多的文档。

检索前先把任务转换为查询计划:需要哪些事实类型,时间范围是什么,哪些来源更可信,结果如何验证。复杂问题可以生成多个查询,再合并去重。

混合检索通常更可靠。向量处理语义相似,关键词保留精确标识,结构化过滤控制项目、版本和权限,重排模型根据完整问题重新排序。没有一种方式适合所有材料。

切块也应尊重文档结构。函数、章节、表格和决策记录有自然边界,固定字符切割会把定义和结论分开。每个片段保留标题路径、版本和原文位置,以便回答能够回到证据。

压缩不能丢失约束

长对话与工具输出需要压缩,但“总结一下”很容易删除看似细小、实际关键的条件。更稳妥的压缩是按类型提取:已确认目标、硬约束、已完成动作、开放问题和关键产物分别保存。

对日志和搜索结果,可以先用确定规则裁剪无关字段,再由模型摘要。数值、错误码、文件路径和引用标识应原样保留,不让语言模型重新表述后产生偏差。

压缩结果要带来源指针。需要细节时,Agent 可以通过工具重新读取原始内容,而不是把摘要当作不可追溯的事实。

摘要也有版本。任务范围变化后,旧摘要可能不再强调正确内容。依赖哈希或任务版本能帮助系统判断是否需要重新生成。

工具描述也是上下文

Agent 可用工具越多,选择错误工具的概率越高。把几十个工具的完整 Schema 全部放进每次调用,会占用大量预算并增加混淆。

可以先根据任务类型选择工具集合,只暴露当前阶段需要的能力。规划阶段看到搜索和任务拆分工具,执行节点只看到具体数据源,审阅节点只看到验证工具。

工具名称和描述要表达业务意图,而不是内部实现。参数有明确类型、范围和示例,错误返回可行动信息。一个设计良好的工具接口,本身就是对模型的约束。

工具结果也要控制规模。数据库查询返回一万行不应直接进入上下文,应该先聚合、分页或保存为产物,再提供摘要与句柄。模型需要知道结果在哪里和如何继续取用,不需要一次看到全部内容。

工作记忆与长期记忆分开

工作记忆服务当前执行,包含计划、节点输出和未完成问题。任务结束后,大部分内容应被丢弃。长期记忆只保存未来确实有价值、且经过验证的信息。

如果所有对话都自动进入长期记忆,错误假设、过期偏好和一次性内容会不断污染后续任务。写入长期记忆应当像写数据库:有 Schema、去重、权限、更新与删除机制。

用户偏好也需要范围。“所有回答简短”可能只适用于某个项目,不应被提升为全局永久规则。记忆条目应标注用户、组织、项目和任务层级,读取时按作用域合并。

冲突不可避免。新信息与旧记忆冲突时,系统不能悄悄选择一个。应根据来源与时间自动解决简单冲突,对关键事实请求用户确认,并保留变更历史。

多 Agent 需要最小共享事实

多个 Agent 协作时,共享全部对话会让边界消失。更好的方式是共享一块结构化任务状态:目标、约束、已确认事实、产物索引和开放问题。

每个 Agent 获得自己的局部上下文,只把通过验证的产物写回共享状态。检索 Agent 不需要知道报告的全部文风要求,写作 Agent 也不需要看到搜索过程里的每个失败查询。

产物之间保存依赖。某个事实被更正后,系统可以找到使用它的分析和报告节点,标记为过期。没有依赖关系,修正上游信息后只能从头重跑或冒险保留错误结果。

上下文传递使用引用和结构,而不是让 Agent 互相发送长篇“对话”。这更接近软件模块之间通过契约协作,也更容易测试。

安全边界必须在模型之外

检索材料可能包含提示注入,要求模型忽略规则或执行危险工具。系统不能依赖模型自行识别所有攻击。

外部内容被明确标记为不可信数据,不能覆盖系统规则。工具权限由代码控制,敏感写操作需要用户确认。检索层按用户权限过滤,不能先取回再要求模型“不许看”。

上下文日志也需要脱敏。为了调试保存完整 Prompt 很方便,却可能包含用户文件、身份与业务数据。生产系统应按字段分类保存,设置访问控制与保留周期。

安全不是在提示词里增加一句“不要泄漏”,而是让模型即使被诱导,也没有越过边界的能力。

评估上下文,而不只评估答案

最终答案错误,可能来自模型能力,也可能来自上下文缺失、检索噪声、旧记忆或工具描述不清。只给答案打分无法定位问题。

我们分别评估检索召回、证据相关性、关键约束覆盖、引用一致性和上下文成本。对固定任务,记录理想材料集合,检查系统是否取回;对答案中的事实,检查是否由上下文支持。

消融测试很有价值:删除某类上下文,结果是否变化;减少检索数量,正确率是否下降;更换摘要策略,约束是否保留。通过这些实验,可以知道哪些 Token 真正产生价值。

线上收集的失败进入回归集。上下文策略、嵌入模型、切块方式和工具描述每次调整后都重新运行,避免优化一个示例却损害整体。

上下文工程最终是信息架构

提示词仍然重要,但它只是系统向模型呈现信息的最后一步。更长期的能力是知道信息从哪里来、谁能修改、何时失效、如何检索、如何压缩,以及输出如何回到可验证来源。

当 Agent 表现不稳定时,先不要急着增加更多规则。检查它是否拿到了正确目标,是否被无关历史干扰,是否能访问需要的工具,是否把临时推断误当成事实。

模型越强,好的上下文工程越不是“教模型聪明一点”,而是让系统承担起组织复杂度的责任。Agent 应该知道完成当前任务所需的一切,同时对其余信息保持无知。

落地时我要求每段进入模型的上下文都携带来源和有效期:source、owner、权限、采集时间、版本、相关性理由和失效条件。输出引用能反查原文,任务结束后知道哪些上下文必须删除。同时统计检索到但未使用、被权限过滤、超过预算裁剪和最终被引用的比例——上下文工程不是塞得更多,而是让每一段信息都能解释为什么此刻应该在这里。

上下文在单 Agent 内部如何组织,在多 Agent 之间就变成“最小共享事实”的问题:哪些事实写回共享黑板、哪些留在局部,我在多 Agent 系统里做了展开;证据检索与权限过滤的具体评估方式,则属于RAG 评估