很多 AI 应用失败,不是因为 prompt 不清楚。也不是因为模型不够强。而是因为模型每一步看到的信息不对。它该看到的事实没看到。不该看到的噪声塞了一堆。旧结论没有更新。工具输出太长,挤掉了真正重要的状态。用户上一轮说过的约束,被后面的检索结果冲掉。
于是系统表现得很奇怪:
第一轮答得挺好。
第二轮开始跑偏。
第三轮忘了目标。
第四轮重复查同一个资料。
最后给出一个看似完整但实际不可靠的答案。
这类问题,继续调 prompt 通常解决不了。
因为问题已经从"怎么说"变成了:
每一步到底该让模型看什么?
这就是 Context Engineering。

一、上下文窗口变大,不等于问题消失
一个常见误解是:
模型上下文窗口越来越大,所以 Context Engineering 不重要了。
这句话只对了一半。窗口变大,确实能放更多东西。
但它没有回答四个问题:
什么该放?
什么时候放?
放多久?
什么时候删?
如果这四个问题没解决,大窗口只是让你更容易制造大垃圾堆。上下文不是仓库。
上下文是工作台。仓库可以放很多东西。工作台上只能放当前步骤真正需要的工具和材料。
Agent 也是一样。它每一步推理时,应该拿到的是"当前最优 token 集合"。不是全部历史。
不是全部资料。不是全部日志。更不是所有检索结果。
二、Context Engineering 的定义
我会把 Context Engineering 定义成:
在每一步模型推理时,选择、组织、压缩、隔离和更新最适合当前目标的信息集合。
这个定义里有五个动作。
选择。
组织。
压缩。
隔离。
更新。
它不是一个单点技术。
不是 RAG。
不是 memory。
不是 prompt caching。
不是长上下文。
这些都是工具。
Context Engineering 是把这些工具放到信息生命周期里的工程方法。
三、四类核心策略
Anthropic 的 Context Engineering 文章把 Agent 上下文策略拆得很清楚。
我把它整理成四类:
Write
Select
Compress
Isolate
第一,Write。
把重要状态写到上下文之外。
比如:
progress.md
decisions.md
open-issues.md
用户偏好
任务状态
工具结果摘要
不要指望模型永远记得。
如果某个信息对恢复、审计、下一步决策很重要,它就应该写到外部状态。
第二,Select。
每一步只选择相关信息进入上下文。
比如代码审查 Agent 不应该读取整个仓库。
它应该先看 PR diff,再按需展开相关文件。
第三,Compress。
把历史、工具输出和长文档压缩成保留任务状态的摘要。
注意,不是简单缩短。
好的压缩要保留:
当前目标
已完成动作
关键事实
未解决问题
决策理由
下一步计划
第四,Isolate。
隔离不同子任务的上下文。
比如一个主 Agent 分派三个子任务:
查资料
审代码
写报告
每个子任务不一定需要看到全部历史。
上下文隔离可以降低干扰,也可以降低成本。

四、四种上下文不要混在一起
生产 Agent 里,我建议至少区分四种上下文。
第一,任务上下文。
它回答:
这次任务要做什么?
成功标准是什么?
当前进度到哪?
第二,项目上下文。
它回答:
这个系统的结构是什么?
代码规范是什么?
业务术语是什么?
架构边界是什么?
第三,用户上下文。
它回答:
用户是谁?
偏好是什么?
权限是什么?
历史交互里哪些信息仍然有效?
第四,执行上下文。
它回答:
刚才调用了什么工具?
返回了什么结果?
哪些错误需要处理?
哪些动作已经产生副作用?
这四类混在一起,Agent 很容易出问题。
比如把用户上下文当成系统规则。
比如把工具输出当成事实源。
比如把旧任务状态带进新任务。
比如把项目说明和当前执行日志混成一团。
上下文工程的第一步,就是分类。
分类之后,才谈得上选择和压缩。
五、一个上下文流
一个典型 Agent 的上下文流可以这样设计:
User Goal
-> Task Plan
-> Retrieved Facts
-> Tool Results
-> Memory Update
-> Next Step Context
每一步都要做判断。
用户目标进来后,不是直接丢给模型跑。
先拆成任务计划。
任务计划决定需要哪些事实。
事实可以来自检索、文件、数据库、MCP、用户历史。
工具结果回来后,不要完整塞回上下文。
先判断:
哪些是关键事实?
哪些只是日志?
哪些需要落盘?
哪些可以丢弃?
哪些要更新长期记忆?
最后形成下一步上下文。这才是循环。
不是每一轮都把旧上下文越堆越高。

六、RAG 只是其中一块
很多人一谈 Context Engineering,就立刻想到 RAG。
RAG 很重要,但它只解决一件事:
从外部知识库取回相关信息。
它不自动解决:
检索结果怎么排序
哪些片段进上下文
如何引用来源
如何处理冲突
如何更新任务状态
如何避免旧信息污染
如何压缩工具输出
如何隔离子任务
所以很多 RAG 系统失败,不是因为向量检索完全不行。
而是因为上下文装配失败。
检索回来 10 段,直接全塞进去。模型看到了相互冲突的信息,没有来源权重,没有时间戳,没有引用约束,最后当然会编一个听起来合理的综合答案。
Context Engineering 要问的不是"有没有检索"。
而是:
检索结果以什么形式进入当前推理步骤?
七、工具输出要先处理
工具输出是上下文污染的高发区。
比如:
测试日志 3000 行
grep 结果 500 条
数据库查询返回 60 个字段
网页抓取整页 HTML
CI 日志包含大量重复 warning
这些东西如果直接塞进上下文,会带来三个问题。
第一,贵。
第二,慢。
第三,容易让模型失焦。
更好的做法是工具输出分层。
原始输出:落盘或对象存储
结构化摘要:进入任务状态
关键片段:进入下一步上下文
索引引用:让 Agent 需要时再读取
这和人工作类似。
你不会把整本日志打印出来贴在桌上。
你会先看摘要、错误行、时间点和相关上下文。
Agent 也一样。
八、Memory 不是把所有历史都记住
"记忆"这个词很容易误导,很多人以为 memory 越多越好。但生产系统里,记忆必须有边界。
至少要区分三种:
第一,短期任务记忆:这次任务需要,任务结束后可以归档。
第二,长期用户记忆:跨任务保留,但需要用户授权、可编辑、可删除。
第三,系统经验记忆:比如失败案例、团队规范、常见解决方案。
这些更适合进入文档、Skills 或知识库,而不是塞进某个用户 session。
记忆不是"永远不忘"。
好的记忆系统必须支持:
写入
读取
更新
过期
删除
审计
否则 memory 很快会变成污染源。
九、失败模式
Context Engineering 常见失败有五类。
第一,信息过载。
什么都放,模型看不清重点。
第二,关键事实缺失。
模型答错不是因为笨,而是没看到事实。
第三,旧状态污染。
上一轮的结论已经过期,但还在上下文里。
第四,工具输出未加工。
大段日志和原始 HTML 挤占窗口。
第五,上下文越权。
用户输入、网页内容、PR 描述里的不可信指令,被当成系统指令执行。
这些问题都不是单靠 prompt 能解决的。
你需要上下文管道。
十、一个实践 checklist
设计 Agent 上下文系统前,先问这些问题:
[ ] 当前任务需要哪些事实?
[ ] 哪些事实来自可信源?
[ ] 哪些输入是不可信数据?
[ ] 哪些信息必须写入外部状态?
[ ] 工具输出是否需要摘要和索引?
[ ] 历史上下文什么时候压缩?
[ ] 哪些上下文需要隔离给子任务?
[ ] 旧状态什么时候过期?
[ ] 记忆是否可删除、可审计?
[ ] 下一步上下文是否只包含当前步骤需要的信息?
这张表比"上下文窗口够不够大"更重要。
因为真正的问题不是能放多少。
而是放进去的东西是否正确。
十一、从 Prompt 到 Context
到这里,我们完成了第一阶段 Prompt Engineering。
也进入了第二阶段 Context Engineering。
Prompt 负责把任务契约说清楚。
Context 负责让模型每一步拿到正确材料。
如果 prompt 是接口定义,context 就是运行时输入装配。
下一篇,我们会拆一个常见误区:
RAG 只是 Context Engineering 的一小块。
很多系统不是检索不够强,而是检索结果没有被正确组织、引用、验证和更新。
这才是下一篇要处理的问题。
参考资料
- Effective context engineering for AI agents | Anthropic Engineering
- Context engineering for agents | LangChain
- Claude Code context management
- Claude Agent SDK overview
- Building Effective AI Agents | Anthropic
- Prompt caching | Anthropic
参考文献: