Context Packing for Agents:Agent 上下文打包怎么设计
这篇文章解决什么问题
Agent 失败并不总是模型不行,很多时候是上下文打包失败:任务目标不清楚、历史太长、RAG 证据顺序混乱、工具结果没有摘要、约束条件被挤出窗口、审批状态没有传进去。
Context Packing 的目标是把用户任务、系统约束、历史摘要、RAG 证据、工具结果、Memory 和输出格式装成一个可控、可审计、可复现的上下文包。
上下文不是越多越好
| 常见做法 | 问题 | 更好的做法 |
|---|---|---|
| 把全部历史塞进模型 | 成本高、噪声大、旧指令污染当前任务 | 分层摘要 + 最近关键轮次 + 当前任务状态 |
| 把 RAG top-k 原文全部塞入 | 证据重复、权限难控、引用难对齐 | 按 claim 需要挑证据,保留 citation_id |
| 工具结果原样塞入 | JSON 太长,模型抓不到重点 | 工具结果标准化 + 摘要 + 原始结果引用 |
| Memory 全量注入 | 隐私风险、陈旧记忆误导 | 只注入本任务相关且未过期的记忆 |
| 只靠 system prompt 控制 | 运行状态缺失,难以复盘 | 每次 run 生成 context_pack 快照 |
Context Pack 的推荐结构
| 层级 | 内容 | 作用 |
|---|---|---|
| task_brief | 用户目标、当前阶段、成功标准 | 防止模型偏离任务 |
| constraints | 权限、预算、风险等级、禁止动作 | 控制安全和副作用 |
| state_snapshot | run_id、step_id、workflow_state、approval_state | 支撑长任务恢复 |
| conversation_summary | 重要历史结论、未完成事项、用户偏好 | 控制历史长度 |
| evidence_pack | RAG 证据、citation_id、权限过滤结果 | 支撑可信回答 |
| tool_result_pack | 工具结果摘要、结构化字段、原始引用 | 支撑工具后续推理 |
| memory_pack | 与当前任务相关的长期记忆 | 提供个性化但不过度注入 |
| output_contract | 输出格式、拒答策略、引用要求 | 让输出可集成 |
打包流程
- 先确定任务阶段:澄清、检索、规划、执行、审批、总结、复盘分别需要不同上下文。
- 再做预算分配:为任务、约束、历史、证据、工具结果和输出格式分配 token 预算。
- 再过滤证据:按权限、时间、知识版本、相关性和去重过滤 RAG 证据。
- 再压缩历史:把历史压成决策摘要,而不是聊天流水账。
- 再标准化工具结果:提取 status、key_fields、errors、next_actions。
- 最后生成快照:记录 context_pack_id、hash、输入来源和被裁剪内容。
Token 预算示例
| 模块 | 建议占比 | 说明 |
|---|---|---|
| 当前任务和约束 | 15% | 永远优先保留 |
| Workflow 状态 | 10% | 长任务和审批必备 |
| 历史摘要 | 15% | 只保留影响当前决策的内容 |
| RAG 证据 | 35% | 按 claim 和引用需求选择 |
| 工具结果 | 15% | 只保留可行动字段 |
| 输出契约 | 10% | schema、格式、拒答规则 |
比例不是固定值,关键是不能让某一类内容无限挤占其它内容。
需要记录的字段
| 字段 | 说明 |
|---|---|
| context_pack_id | 本次上下文包唯一 ID |
| run_id / step_id | 对应 Agent 执行轨迹 |
| token_budget | 总预算和各层预算 |
| included_sources | 被纳入的历史、证据、工具结果、记忆 |
| excluded_sources | 因权限、过期、低相关或超预算被排除的内容 |
| pack_hash | 用于回放和审计 |
| policy_version | 上下文策略版本 |
| knowledge_version | RAG 知识版本 |
面试表达
可以这样讲:
> 我没有把上下文当成字符串拼接,而是把它建模成 context pack。每次 Agent 执行都会记录任务、状态、证据、工具结果、Memory、预算和输出契约,这样既能控制 token 成本,也能在失败后复盘到底是证据缺失、历史污染、工具结果过长还是约束没有传进去。
常见坑
- 只做 prompt template,不记录 context 快照。
- RAG 证据没有 citation_id,答案无法追溯。
- 工具结果过长,导致任务目标被挤掉。
- Memory 不做过期和权限过滤。
- 只看总 token,不看各层预算。
落地检查清单
- [ ] 是否有 context_pack_id 和 pack_hash?
- [ ] 是否能看到哪些内容被纳入、哪些被裁剪?
- [ ] 是否区分任务、历史、证据、工具结果、Memory?
- [ ] 是否记录知识版本和 Prompt 版本?
- [ ] 是否能把失败样本回放到同一个上下文包?