用 AI 编程助手开发项目时常见这样的曲线:开局表现很好,任务推进到几十轮后开始忘掉定好的技术方案、反复尝试已经失败的方法、甚至修改无关代码。模型没变,变的是上下文——对话历史、工具返回、错误日志不断累积,真正重要的信息被淹没在噪声里。上下文工程(Context Engineering)就是解决这个问题的系统方法。
和提示词工程的分工
提示词工程管"任务怎么描述清楚",上下文工程管"模型每次推理时该看到什么信息"。类比员工办公:前者是交代任务的话术,后者是决定哪些文件放上桌面、哪些归档、哪些清掉。核心目标一句话:在正确的时间,把正确的信息,以合适的形式交给模型。
两个基础概念要钉住:上下文窗口决定单次推理能处理的 token 上限;窗口大不等于表现好——信息冗长混乱时模型定位关键内容的能力下降,这种长上下文性能退化被称为 Context Rot(上下文腐烂)。它提醒的重点不是"越长越差",而是信息的组织方式与数量同等重要。
Agent 的上下文由四类信息构成
| 类型 | 作用 | 示例 |
|---|---|---|
| 指令上下文 | 告诉模型做什么 | System Prompt、行为规则 |
| 知识上下文 | 提供任务所需知识 | 检索文档、项目资料 |
| 工具上下文 | 说明工具用法与结果 | 工具定义、调用返回 |
| 历史上下文 | 记录此前发生了什么 | 对话历史、执行记录 |
关键认知:这些信息不需要始终全部驻留在上下文里。管理的艺术在于谁进谁出。
四大策略:卸载、检索、隔离、压缩
Offloading(卸载):用外部存储替代长期占用窗口。读完整本技术文档不必常驻上下文,存文件系统、留路径和摘要,需要时再读——内存不够就换页,一个道理。
Retrieval(检索):需要什么读什么。修登录 Bug 的 Agent 不该通读整个仓库,先搜 login、auth 关键词再读相关文件。与 RAG 的区别在于检索是执行过程的一部分:Agent 根据中间结果主动决定下一步要什么信息。
Isolation(隔离):不同子任务用不同上下文。搜索、编码、测试三个 Agent 不共享全部历史,搜索只给编码传资料,编码只给测试传改动和验收要求——各自专注,互不污染。
Compaction(压缩):历史过长时提炼摘要续跑。摘要必须回答四个问题:当前目标是什么、完成了哪些、哪些方案已失败、还剩什么没解决。压缩的要害不是缩短文本,而是保留未来执行仍需要的信息。
四种失效模式,压缩是重灾区
| 模式 | 表现 |
|---|---|
| Context Poisoning(中毒) | 错误信息进入上下文,后续持续基于错误前提推理 |
| Context Distraction(分心) | 历史太多,干扰当前任务 |
| Context Confusion(混淆) | 无关信息或过多工具让模型选错 |
| Context Clash(冲突) | 不同阶段的信息互相矛盾 |
工程上最阴险的是压缩引发的中毒:Agent 曾误判某文件不存在,这个错误结论被写进摘要反复携带,之后每一轮推理都建立在错误地基上,而且因为"经过压缩整理"显得格外可信。对策有两条纪律:错误结论未经验证不得进入摘要,要么标注"未确认"要么先复核;已解决环节的冗余日志可以清,但失败原因和规避方法要保留——必要的失败记录是 Agent 不重蹈覆辙的疫苗。
和记忆系统的分工
Context 与 Memory 用内存和硬盘类比最贴切:Context 是工作内存,随推理请求构建,受窗口限制;Memory 是持久存储,跨会话保留,容量取决于外部系统。用户说过"项目统一用 TypeScript",Memory 负责长期保存这条偏好,上下文工程负责判断本轮是否把它加载进来。分工一句话:Memory 存信息,Context Engineering 决定当前用哪些信息。
落地清单与验证方法
按五步搭一个可靠的编程 Agent:加载必要信息(用户目标、项目规范、相关代码,而非整个仓库)→ 执行并记录状态 → 遇到新问题按需检索 → 历史过长触发压缩 → 用整理后的上下文续跑。
两个可直接验证的工程细节:其一,保持 system prompt 前缀稳定,支持前缀缓存的模型服务能复用已计算部分,压延迟降成本——验证方法是对比改动前后同一请求的响应延迟与缓存命中标记;其二,压缩触发点要显式设定(比如超过窗口 70% 时执行),并保留最近 N 轮原始对话不压缩,防止边界信息丢失。
最后收敛一下适用边界:单轮问答和短对话应用不需要这套机制,完整保留历史反而最简单可靠;需要持续执行几十上百步的 Agent,上下文管理直接决定任务成功率、响应速度和成本。模型负责思考,上下文工程负责让它始终拿到做出正确判断所需的信息——这套系统本身,就是 Agent 与普通 LLM 应用的分水岭。

评论0