上下文工程:为什么你的 AI Agent 总是“断片”?

AI Agent 在处理复杂任务时经常“掉链子”。你刚告诉它的信息,它很快就忘了。给它的工具越多,它反而越混乱。这不是个例。

今年 6 月,Andrej Karpathy 发推特讨论 “Context Engineering” 和 “Prompt Engineering” 的关系后,Context Engineering(上下文工程)这个词彻底爆火。

image-20251117181809685

为什么这个概念这么火?因为它要解决的正是大家都在发愁的核心问题:AI 能记住的信息有限,如何在有限的上下文空间内为它提供最合适的信息和工具?

转眼 5 个月过去,上下文工程已经从一个新概念变成了 AI Agent 开发的核心技能。Manus、Anthropic、Cursor、Google DeepMind 等众多 AI 团队都验证并分享了许多实用方法。我在实际使用中发现,这些方法的思路其实和管理计算机内存类似——该缓存的要缓存,该压缩的要压缩,暂时用不到的信息就不要塞进上下文里。

上下文越长,模型越容易出错

Chroma 实验室做了个实验,测试了 18 个最强模型(包括 GPT-4.1、Claude 4、Gemini 2.5等),让大模型在大量重复词中找出藏入的不同词。

结果是,输入越长,模型性能退化越明显。输入较短时表现完美,但当输入扩展到数千甚至上万个词时,准确率明显下降。位置越靠后的异常词,越容易被漏掉或者放错位置。

更有意思的是,不同模型的策略差异很大。Claude Opus 4 更谨慎,遇到不确定的情况宁愿拒答。GPT 系列模型则倾向于给出一个看起来合理但可能错误的答案。

实际使用中,问题就更复杂了。AI 在某一步产生了幻觉,把错误信息写入上下文,后续推理就会基于这个错误继续,越错越离谱。或者你给 AI 提供了 50 个工具定义,它开始在工具之间反复横跳,忘了最初的任务目标。多轮对话中的信息冲突也很常见,如果前面说了 A,后面又说了相反的 B,模型往往会抓住先入为主的 A 不放,即使 B 才是正确的。

Manus 团队在实践中发现,工具越多,性能退化越严重。主要原因是动态增删工具定义会破坏 KV-cache 的前缀稳定性,导致缓存命中率下降、延迟和成本上升。LangChain 也提到了类似问题,工具数量超过一定阈值后,性能反而下降。

这些问题不是模型的错,主要是上下文窗口容量太有限了。

像管理内存一样管理上下文

程序员都懂内存泄漏、缓存失效、缺页异常这些老问题。AI 的上下文窗口其实就像计算机的内存——容量有限,访问有开销。

上下文工程面对的,本质上就是内存管理的经典问题:

  • 无用数据占用空间,挤掉有用信息,这就是 Memory Leak(内存泄漏)。
  • 常用数据被挤出去,需要重新加载,这就是 Cache Miss(缓存未命中)。
  • 需要的信息不在上下文里,需要你来告诉它,这就是 Page Fault(缺页错误)。

五种应对策略

过去几个月,Manus、Anthropic、Cursor 和 DeepMind 等公司验证并分享了许多关于上下文工程的实践经验。根据他们的经验,我总结出五种主要策略。

Offload:写入文件系统

写本地文件系统是最常用、最简单的上下文工程方法。

比如 Manus 在处理复杂任务时,会创建一个 todo.md 文件。任务进行过程中,Agent 会不断更新这个文件:

## Current Task: 优化登录流程

- [x] 检查数据库连接
- [ ] 分析JWT token过期问题
- [ ] 测试Redis缓存
- [ ] 更新文档

这样做有两个好处。任务列表不需要一直占用上下文窗口,需要时读取就行。每次读写 todo.md,相当于提醒 AI 当前的任务是什么,防止跑偏。

Anthropic 的研究团队也用类似方法。他们在构建多 Agent 研究系统时,会把研究计划写入文件。每个子 Agent 完成任务后,把结果保存到文件里。主 Agent 不需要在上下文中记住所有细节,只需要知道"研究计划在 plan.md 里,实验结果在 results/ 目录"。

Cache:缓存常用上下文

Claude 的提示词缓存功能能让成本大幅降低。缓存命中的输入 token 价格比未命中便宜 10 倍。但前提是前缀必须字节级完全相同。

很多开发者犯的错误是在 system prompt 开头加时间戳:

# ❌ 错误做法:每次时间都变,缓存永远失效
system_prompt = f"""
Current time: {datetime.now()}

You are a coding assistant...
"""

正确的做法是把变化的部分放后面:

# ✅ 正确做法
system_prompt = """
You are a coding assistant...

---
Current time: {datetime.now()}
"""

Manus 团队发现,通过保持前缀稳定,并强制只允许追加和确定性更新,KV 缓存命中率能大幅提升。他们的 Agent 在处理 50 次工具调用时,输入输出比达到 100:1,缓存节省的成本非常可观。

要让 Claude 的缓存机制生效,需要满足几个条件:前缀必须字节级完全相同,变动信息必须后置(如时间戳、用户输入),JSON 序列化必须确定性(key 顺序固定),只能追加新内容,不能修改前缀。

以 Claude Sonnet 4.5 为例,缓存命中价格是 0.30 USD/MTok,未命中是 3.00 USD/MTok,差距 10 倍。所以 system prompt、工具定义这些不变的内容要放在最前面,变化的内容放后面。

Compress:压缩和总结

50 条对话浓缩成几句话,保留关键信息,丢弃冗余内容。比如“对对对,就是这里”、“可能是这个问题”等等的对话内容完全可以丢掉。已经解决的中间步骤,同样没必要留着。

但有很多关键信息不能丢,包括:

  • 关键决策不能丢,比如“我们选择用 Redis 而不是 Memcached,因为需要持久化”。
  • 错误信息不能丢,比如“在第 45 行发现空指针异常”。
  • 用户偏好也不能丢,比如“用户希望优先考虑性能而不是可读性”。

Anthropic 的研究 Agent 有多个子 Agent,每个完成任务后会生成一个摘要。主 Agent 不需要看 50 页的实验记录,只需要看“实验结论:方法 A 比方法 B 快 30%,但内存占用增加 15%”这样的总结。

过度压缩会丢失关键信息。比如用户说“别用那个库,上次出过安全漏洞”,这种细节很重要,但容易在压缩时被丢掉。所以压缩前要分析重要性,保留关键决策、错误信息、用户偏好。

Retrieve:按需加载

不把所有信息都塞进上下文,而是建立索引,需要时再检索。

编辑器类产品(如 Cursor)通常会做预检式的内容组装。当你要求“优化这个函数的性能”时,它不会把整个代码库都加载进来。它会分析当前函数的调用关系,检索相关的函数定义,查找类似的优化案例,把这些精选内容组装成上下文。

检索通常有三个层次:

  • 语义检索,通过向量相似度找相关内容。
  • 结构化检索,通过 AST、调用图找依赖关系。
  • 混合检索,结合上面两种,加上关键词匹配。

这里有个权衡。召回多了有噪音,召回少了遗漏信息。检索越精细越慢,但质量越高。给的上下文多,AI 推理的空间就小。Windsurf 团队强调,生产环境的 RAG 要求更高,需要多轮迭代优化。他们的经验是,宁愿检索精确一点,也不要为了速度牺牲质量。

我之前在做 RAG 时用纯向量检索时也踩过坑,召回了一堆看起来相似但不相关的内容,AI 被带跑了。后来改用混合检索,再加上重排序模型,效果好了很多。

Isolate:隔离上下文

多个 Agent 各管各的上下文,避免互相干扰。

Anthropic 构建的研究 Agent 系统采用了“Lead agent + 并行 sub-agents”的架构。Lead Agent 负责总体协调,而不同的子 Agent 分别负责研究、分析、撰写等环节。每个 Agent 维护自己的上下文窗口,子 Agent 之间不需要知道彼此的所有细节,只需要完成各自的任务并将结果交给 Lead Agent。

什么时候该隔离?任务可以独立完成,上下文不需要共享全部细节,单个上下文窗口不够用。

什么时候不该隔离?需要频繁协调,上下文高度相关,任务很简单的情况。

Cognition AI 的 Walden Yan 写过一篇文章《Don’t Build Multi-Agents》,警告说多 Agent 系统的协调成本很高。如果任务本身不复杂,不要为了“看起来高级”而强行拆分 Agent。

我曾经把一个简单任务拆成 5 个 Agent,结果光是 Agent 之间传递消息就花了大量时间。

写在最后

在有限的上下文空间内,为大模型提供最合适的信息和工具,是上下文工程需要解决的核心问题。为此,可以采用多种策略,如 Offload、Cache、Compress、Retrieve、Isolate 等。

在实际应用中,通常需要将多种策略结合使用。例如,Offload + Retrieve 适用于长任务,将中间结果 offload 到文件中,需用时通过文件路径检索;Cache + Compress 适用于高频对话,缓存 system prompt 和工具定义,并压缩历史对话内容;Isolate + Cache 适用于复杂流程,让多个 Agent 各自管理上下文,并在每个 Agent 内部使用缓存。

未来如果实现了 AGI,AI 可能会主动理解你的需求,甚至比你更懂你的代码。那时,或许就不再需要上下文工程了。AI 会像人类一样自主管理记忆,记住该记住的,忘掉该忘掉的。但在现阶段,上下文工程仍然是必不可少的。


相关资源:


欢迎长按下面的二维码关注 Feisky 公众号,了解更多云原生和 AI 知识。

comments powered by Disqus