Skip to content

Context Engineering 怎么做:别把所有信息都塞给模型

做 Agent 时,我更愿意把上下文看成一张不断变化的工作台。台面太空,模型找不到材料;什么都堆上去,真正要用的那张纸反而被压在最下面。

Prompt Engineering 关注“这句话怎么写”,Context Engineering 关注“模型做出下一次决策前,工作台上应该留下什么”。这两件事有关,但不是一回事。

  • 上下文的目标是足够、相关、可信、能行动,不是尽可能长。
  • 当前任务状态要结构化保存,聊天历史只保留理解当下所需的近因信息。
  • RAG 负责为当前问题取证,Memory 负责保存未来仍有价值的事实和经验。
  • Compaction 是有损视图,关键事实、权限和终态必须回到结构化来源读取。

对 Agent 来说,上下文通常由这些部分组成:

系统规则
+ 当前目标
+ 已确认状态
+ 最近对话
+ 检索结果
+ 长期记忆
+ 工具定义
+ 工具输出
+ 剩余预算

全部塞进去并不会更聪明,通常只会更慢、更贵,也更容易被无关内容带偏。

负责不应该负责
System Prompt稳定角色、边界、决策原则长篇业务知识、动态状态
Task State当前目标、约束、已完成步骤用户全部历史
Conversation当前交互所需的近因信息永久记忆
RAG从外部知识中即时检索证据保存用户长期偏好
Memory跨会话保存经过筛选的事实和经验原样堆积聊天记录
Tool Result支撑下一次决策的最新观察无限日志、完整二进制

不要等上下文溢出才临时裁剪。可以预先分配:

系统规则与工具定义 15%
当前任务状态 15%
最近对话 20%
检索与记忆 30%
工具结果 10%
输出预留 10%

比例不是固定答案,但必须为模型输出和异常情况留空间。

监控:

  • 每一类上下文占用;
  • 每轮增长速度;
  • 被裁剪的信息;
  • 检索命中后是否真的被引用;
  • 上下文长度与成功率、延迟、成本的关系。

System Prompt 保持短、稳、可版本化

Section titled “System Prompt 保持短、稳、可版本化”

System Prompt 适合写:

  • Agent 的职责;
  • 允许和禁止的动作;
  • 如何处理不可信内容;
  • 何时调用工具;
  • 何时停止或请求人工;
  • 输出的基本契约。

不适合写:

  • 全部 API 文档;
  • 所有客户资料;
  • 每次都会变化的任务状态;
  • 数百条相互冲突的边缘规则。

给 Prompt 计算哈希或版本号,并让评测记录对应版本。

对于多步任务,维护结构化状态:

{
"goal": "生成并提交月度报告",
"constraints": [
"只使用已批准数据源",
"发布前必须人工确认"
],
"completed": [
"collect_data"
],
"current_step": "validate_metrics",
"open_questions": [
"是否排除测试租户"
],
"artifacts": {
"raw_metrics": "artifact://metrics-123"
}
}

每轮只把当前决策需要的字段放入上下文。结构化状态也更容易持久化和恢复。

RAG 解决“外部知识太多,当前应该看哪些”。

一个可靠链路包括:

  1. 查询改写;
  2. 权限过滤;
  3. 混合召回;
  4. rerank;
  5. 去重和多样性;
  6. 片段压缩;
  7. 来源引用;
  8. 无足够证据时明确返回不足。

不要只用向量相似度。产品名、错误码、订单号等精确实体通常需要关键词或结构化查询。

检索结果也是不可信数据,不能改变系统权限和目标。

Memory:只保存未来有价值的信息

Section titled “Memory:只保存未来有价值的信息”

建议区分:

  • 偏好记忆:用户明确表达且允许保存的偏好;
  • 事实记忆:稳定事实,带来源和有效期;
  • 情景记忆:过去任务发生了什么;
  • 程序记忆:经过验证的操作经验;
  • 受保护状态:身份、权限和安全策略,由系统维护。

写入前执行:

候选提取 → 类型判断 → 来源验证 → 敏感数据检查
→ 租户绑定 → 去重/合并 → 过期策略 → 写入

模型不能通过普通对话修改受保护状态。

Tool Result:结构化、截断、可追溯

Section titled “Tool Result:结构化、截断、可追溯”

工具返回:

{
"summary": "3 个测试失败,均与时区有关",
"items": [
{
"test": "scheduleAtMidnight",
"error": "expected UTC+8, got UTC"
}
],
"truncated": true,
"artifact_uri": "artifact://test-log-456"
}

Agent 获得当前决策所需摘要,需要深入时再按引用读取。不要每轮重复附带完整日志。

Compaction:压缩的是历史,不是事实来源

Section titled “Compaction:压缩的是历史,不是事实来源”

上下文接近预算时,可以把旧轨迹压缩成:

  • 已确认事实;
  • 已完成步骤;
  • 未解决问题;
  • 关键工具结果引用;
  • 用户最新约束;
  • 已否决方案及原因。

压缩摘要必须和原始 trace 分开保存。后续需要审计或纠错时,应能回到原始记录。

错误压缩可能把“不确定”变成“确定”,或丢失否定词。高风险事实应该从结构化状态重新读取,而不是依赖摘要。

不要在任务开始时把所有可能相关的信息加载进来。让 Agent 通过受限工具按需获取:

先给目录和摘要
→ 选择相关对象
→ 获取局部内容
→ 必要时继续深入

这和工程师先看 tree、再打开相关文件,而不是一次 cat 整个仓库是同一个道理。

可以缓存:

  • 稳定系统前缀;
  • Tool Schema;
  • 文档解析结果;
  • Embedding;
  • 权限过滤后的检索候选;
  • 确定性工具结果。

缓存键至少包含:

  • 内容哈希;
  • 模型或解析版本;
  • 租户和权限范围;
  • 数据版本;
  • 过期时间。

不要跨用户复用含私有信息的 Prompt cache。

长上下文增加成本,也可能让模型忽略真正关键的指令。

RAG 面向当前问题查外部知识;Memory 面向未来任务保存经过筛选的内部状态。

摘要是有损视图,重要状态应存结构化字段和来源。

工具过多会增加选择错误。按任务阶段只暴露必要工具。

权限必须由执行层强制,不属于 Context Engineering 能解决的问题。

  1. 为上下文分类并记录 token 占用;
  2. 把当前任务状态改成结构化对象;
  3. 工具输出增加摘要、截断和 artifact 引用;
  4. RAG 增加权限过滤和引用;
  5. 长期记忆增加来源、类型、租户和过期时间;
  6. 超预算时生成可审计的 compaction;
  7. 用 eval 比较不同上下文策略的任务成功率。

Context Engineering 的目标不是把所有信息都交给模型,而是在每一次决策前提供足够、相关、可信且能行动的信息

延伸阅读: