随着开发任务持续推进,智能体需要记住的需求、代码和工具结果会不断累积。当上下文窗口接近上限时,早期关键信息容易被噪声覆盖,模型也可能出现判断失准和仓促收尾。要改善这种现象,重点并非立即训练新模型,而是重新设计信息如何进入、保留、压缩与取回。
当你在跟Agent不停地探讨开发你的项目时,刚开始可能觉得它真是太懂我了,你说出一个需求,它三两下就完美地帮你做出来。但是当对话持续地进行下去后,可能到50轮对话后,你让它修一个bug,结果它不停地改不停地错,甚至做出一些莫名其妙的行为,这时候你就要知道——它的上下文空间不够了!LLM在得知上下文空间不足时,会感到非常焦虑,这时它会一直想赶紧仓促对任务进行结尾,这会导致它的误判行为。那么你又觉得,这个Agent怎么这么蠢,我要你何用!
为了延长这次对话寿命,那就绕不开Agent的一大核心:Context Engineering——上下文工程。本文我们就来聊聊上下文工程的实现。
做 Agent 遇到效果不好,很多人的第一反应是这两条路:
这两个坑的共同点是:都在试图改模型。但绝大多数场景下,你该改的是上下文。
Context Engineering 的手段可以归成五类,每一类对应一个不同的问题:
遇到问题先判断属于哪一类,再挑手段,比一上来就调 prompt 有效得多。
遇到多个问题同时存在时,它们之间还有优先级:
Offload > Cache > Reduce(先紧凑化,实在不行再摘要化)> Isolate > Retrieve
下面按「先卸载、再瘦身、最后按需取回」的思路逐个说。
卸载的核心思路一句话:
上下文窗口是昂贵的,但是文件系统是廉价的。
能搬到文件里、数据库里的,就别堆在上下文里。这引出了两种截然不同的加载策略:
JIT 有三种落地方式:RAG、Agentic Search(运行时用工具探索)、Context Offloading(主动卸载 + 按需恢复)。
举个例子:让你排查"登录后每次都跳首页"这个 bug。
一上来就把整个项目读一遍,是最贵的做法。更聪明的做法是按成本递增排序工具调用——先用最便宜的工具,再用稍贵的,最后用最贵的拿细节:
先用便宜的工具把范围缩小,再用贵的工具拿细节。这就是 Agentic Search(运行时工具探索)——"按需加载"在实践中的样子。
记忆系统本质上也是一种卸载——把跨会话的信息搬到文件或数据库里,用的时候再捞回来。这也是为什么 Agent 需要记忆:上下文窗口就像网吧的电脑,你一下机,系统就重置了,第二天再打开,什么都没了。
不管你的 prompt 管理做得多好,Agent 跑完 50 轮,prompt 长度大概率会爆。
Claude Code 的思路是:先试轻手段,不行再试重手段。
[Old tool result content cleared]触发阈值是 effectiveContextWindow - 13k。
Auto-compact 的摘要不是随便写的,它是一套严格的 9 段结构:用户意图、技术概念、文件改动、错误修复、问题解决、用户消息、待办任务、当前工作、下一步。
压缩完还有关键一步:把最近读过的 5 个文件内容附回去。否则模型知道"要去改 auth.ts",却不知道 auth.ts 长什么样。
缓存分三层,可控程度不同:
Prompt Cache 有个很实用的设计推论:system prompt 在静态和动态之间有一条分界线。
const systemPrompt = [
// ---- 静态部分:全局可缓存,所有用户共享 ----
identitySection(), // "你是 XX,负责 YY"
systemRulesSection(), // 环境约束
taskGuidelines(), // 做事方式
riskGuidelines(), // 行动准则
toolUsageGuide(tools), // 工具指南
outputStyle(), // 输出风格
// ======== 分界线 ========
// ---- 动态部分:每会话不同 ----
envInfo(cwd, gitStatus), // 工作目录、Git 状态
userConfig(claudeMd), // 用户自定义规则
memoryContext(memories), // Memory 内容
]
分界线以上的内容所有用户共享,能命中全局缓存;以下每会话都变。把 prompt 按这条线切开、拆成独立模块,缓存友好度和可维护性都会好很多——改输出风格时,不会碰到身份和规则。
还有个细节:高频变化的信息别写进 system prompt,注入到对话消息里。比如当前打开的文件、今天的日期,这些每轮都变,写进 system prompt 就等于每轮都把缓存打穿。
一个上下文装不下所有事的时候,就拆成多个。
最后说检索。RAG 的管线是六步:
文档加载 → 数据分块 → Embedding → 向量储存 → 检索 → 注入上下文
流程不复杂,但每一步都会翻车:
还有个常见现象:搜出来 6 条,5 条都在说同一件事。这时候要上 MMR 去重。
记住这句话:
开卷考试,翻书也可能找不到答案。数据质量决定了 RAG 的效果,而不是模型聪不聪明。
用一条线串起来:
Agent Loop 是心跳,Tool System 是手脚,而 Context Engineering 是它的记忆和注意力——决定了它能跑多远,也决定了它跑到最后还记不记得自己要去哪。