Context Engineering 怎么做:别把所有信息都塞给模型
做 Agent 时,我更愿意把上下文看成一张不断变化的工作台。台面太空,模型找不到材料;什么都堆上去,真正要用的那张纸反而被压在最下面。
Prompt Engineering 关注“这句话怎么写”,Context Engineering 关注“模型做出下一次决策前,工作台上应该留下什么”。这两件事有关,但不是一回事。
- 上下文的目标是足够、相关、可信、能行动,不是尽可能长。
- 当前任务状态要结构化保存,聊天历史只保留理解当下所需的近因信息。
- RAG 负责为当前问题取证,Memory 负责保存未来仍有价值的事实和经验。
- Compaction 是有损视图,关键事实、权限和终态必须回到结构化来源读取。
对 Agent 来说,上下文通常由这些部分组成:
系统规则+ 当前目标+ 已确认状态+ 最近对话+ 检索结果+ 长期记忆+ 工具定义+ 工具输出+ 剩余预算全部塞进去并不会更聪明,通常只会更慢、更贵,也更容易被无关内容带偏。
六类信息各自负责什么
Section titled “六类信息各自负责什么”| 层 | 负责 | 不应该负责 |
|---|---|---|
| System Prompt | 稳定角色、边界、决策原则 | 长篇业务知识、动态状态 |
| Task State | 当前目标、约束、已完成步骤 | 用户全部历史 |
| Conversation | 当前交互所需的近因信息 | 永久记忆 |
| RAG | 从外部知识中即时检索证据 | 保存用户长期偏好 |
| Memory | 跨会话保存经过筛选的事实和经验 | 原样堆积聊天记录 |
| Tool Result | 支撑下一次决策的最新观察 | 无限日志、完整二进制 |
先分配 token 预算
Section titled “先分配 token 预算”不要等上下文溢出才临时裁剪。可以预先分配:
系统规则与工具定义 15%当前任务状态 15%最近对话 20%检索与记忆 30%工具结果 10%输出预留 10%比例不是固定答案,但必须为模型输出和异常情况留空间。
监控:
- 每一类上下文占用;
- 每轮增长速度;
- 被裁剪的信息;
- 检索命中后是否真的被引用;
- 上下文长度与成功率、延迟、成本的关系。
System Prompt 保持短、稳、可版本化
Section titled “System Prompt 保持短、稳、可版本化”System Prompt 适合写:
- Agent 的职责;
- 允许和禁止的动作;
- 如何处理不可信内容;
- 何时调用工具;
- 何时停止或请求人工;
- 输出的基本契约。
不适合写:
- 全部 API 文档;
- 所有客户资料;
- 每次都会变化的任务状态;
- 数百条相互冲突的边缘规则。
给 Prompt 计算哈希或版本号,并让评测记录对应版本。
Task State 比聊天历史更可靠
Section titled “Task State 比聊天历史更可靠”对于多步任务,维护结构化状态:
{ "goal": "生成并提交月度报告", "constraints": [ "只使用已批准数据源", "发布前必须人工确认" ], "completed": [ "collect_data" ], "current_step": "validate_metrics", "open_questions": [ "是否排除测试租户" ], "artifacts": { "raw_metrics": "artifact://metrics-123" }}每轮只把当前决策需要的字段放入上下文。结构化状态也更容易持久化和恢复。
RAG:按当前问题取证
Section titled “RAG:按当前问题取证”RAG 解决“外部知识太多,当前应该看哪些”。
一个可靠链路包括:
- 查询改写;
- 权限过滤;
- 混合召回;
- rerank;
- 去重和多样性;
- 片段压缩;
- 来源引用;
- 无足够证据时明确返回不足。
不要只用向量相似度。产品名、错误码、订单号等精确实体通常需要关键词或结构化查询。
检索结果也是不可信数据,不能改变系统权限和目标。
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 分开保存。后续需要审计或纠错时,应能回到原始记录。
错误压缩可能把“不确定”变成“确定”,或丢失否定词。高风险事实应该从结构化状态重新读取,而不是依赖摘要。
Just-in-time Context
Section titled “Just-in-time Context”不要在任务开始时把所有可能相关的信息加载进来。让 Agent 通过受限工具按需获取:
先给目录和摘要 → 选择相关对象 → 获取局部内容 → 必要时继续深入这和工程师先看 tree、再打开相关文件,而不是一次 cat 整个仓库是同一个道理。
可以缓存:
- 稳定系统前缀;
- Tool Schema;
- 文档解析结果;
- Embedding;
- 权限过滤后的检索候选;
- 确定性工具结果。
缓存键至少包含:
- 内容哈希;
- 模型或解析版本;
- 租户和权限范围;
- 数据版本;
- 过期时间。
不要跨用户复用含私有信息的 Prompt cache。
上下文越长越好
Section titled “上下文越长越好”长上下文增加成本,也可能让模型忽略真正关键的指令。
RAG 等于 Memory
Section titled “RAG 等于 Memory”RAG 面向当前问题查外部知识;Memory 面向未来任务保存经过筛选的内部状态。
摘要等于事实
Section titled “摘要等于事实”摘要是有损视图,重要状态应存结构化字段和来源。
所有工具永远可见
Section titled “所有工具永远可见”工具过多会增加选择错误。按任务阶段只暴露必要工具。
把权限写进 Prompt
Section titled “把权限写进 Prompt”权限必须由执行层强制,不属于 Context Engineering 能解决的问题。
- 为上下文分类并记录 token 占用;
- 把当前任务状态改成结构化对象;
- 工具输出增加摘要、截断和 artifact 引用;
- RAG 增加权限过滤和引用;
- 长期记忆增加来源、类型、租户和过期时间;
- 超预算时生成可审计的 compaction;
- 用 eval 比较不同上下文策略的任务成功率。
Context Engineering 的目标不是把所有信息都交给模型,而是在每一次决策前提供足够、相关、可信且能行动的信息。
延伸阅读: