很多 Agent 的失败并不是模型不会推理,而是模型在关键时刻没有看到正确的信息。把整个仓库、所有历史消息和一大段文档塞进上下文,表面上增加了信息量,实际却可能让目标、约束和最新观察结果互相淹没。

上下文工程关注的不是“提示词写得更长”,而是:在每一轮决策前,应该把哪些信息以什么顺序、什么格式交给模型。

一、上下文是一个有生命周期的状态

一次 Agent 运行至少包含几类信息:

信息作用变化频率
任务目标和不可变约束定义成功标准
工具定义和权限定义行动空间低到中
用户偏好与长期记忆提供个性化背景
当前计划和进度说明已经完成什么
工具返回值和错误提供最新事实很高

这些内容不应该被同等对待。目标和权限需要稳定、明确;工具结果要尽量新;过时的中间推理则应该被压缩或删除。

二、先设计稳定前缀,再放动态内容

许多推理引擎会尝试复用相同前缀的 KV Cache。即使具体缓存策略由模型服务决定,保持前缀稳定也有两个直接好处:减少重复输入,降低每轮上下文组织的复杂度。

一种实用的排列方式是:

系统规则与安全边界
固定的工具协议和输出格式
任务目标与验收标准
相关记忆和参考资料
当前状态与最近观察结果
本轮用户消息

把当前时间、随机请求 ID 或不断变化的统计信息塞进开头,会让整个前缀频繁失效。动态信息应该靠近上下文末尾,并且只保留对当前决策有帮助的部分。

三、工具描述也是上下文的一部分

工具 schema 不只是给程序校验参数,也在告诉模型“什么动作是合法的”。好的工具描述应当说明用途、参数语义、单位、失败条件和副作用。例如 delete_file(path) 至少要区分“文件不存在”“路径超出工作区”和“需要人工确认”这几种结果。

工具过多时,不要把所有细节一直放在上下文里。可以先提供工具目录和简短能力摘要,在模型选中某个工具后,再加载完整 schema 或使用 Skill。这样既减少噪声,也让工具发现过程可观察。

四、Skills 和状态栏解决两个不同的问题

Skill 可以理解为按需加载的操作知识:它包含适用条件、输入输出约定和执行步骤,但不必在每一轮都展开完整正文。Agent 先知道“有这项能力”,需要时再读取细节。

状态栏则是给模型和用户看的压缩状态,例如:

目标:完成数据迁移并通过校验
已完成:读取配置、生成迁移草稿
当前:执行只读校验
阻塞:生产写入需要确认
下一步:等待校验结果

它不是新的记忆库,而是把长轨迹重新整理成一份可快速恢复的工作面板。状态栏必须由真实事件更新,不能让模型自行宣称“已完成”。

五、上下文压缩要保留事实,不要保留废话

当上下文接近预算时,压缩的目标不是简单截断最早的消息,而是提炼仍然会影响决策的信息:已确认的事实、失败原因、尚未解决的约束、重要的文件路径和待验证假设。

压缩后最好保留结构化摘要,并记录来源或时间:

事实:接口要求 amount 为整数,来源:schema.ts,第 18 行
失败:第一次测试因时区断言失败,来源:test output,14:32
待验证:重试后需要检查数据库事务是否回滚

如果摘要没有来源,下一轮 Agent 可能把猜测误当成事实。压缩也应当可观测:记录压缩前后的 token 数、丢弃了哪些内容,以及压缩后任务成功率是否下降。

六、一个可执行的检查表

设计上下文时,可以逐轮检查:

  1. 模型是否能直接找到任务目标和完成标准?
  2. 最近一次工具结果是否比旧的推理草稿更醒目?
  3. 动态内容是否污染了本来可以稳定的前缀?
  4. 被压缩的内容是否包含来源、失败原因和未决事项?
  5. 工具和记忆是否按当前任务最小化加载?

上下文窗口变大,不会自动带来更强的 Agent。真正重要的是让每一轮都围绕“当前决策所需的最小事实集”组织信息。

参考阅读

  • 李博杰:《深入理解 AI Agent:设计原理与工程实践》,v1.3,2026-07-29。