客户在线等着,Agent 报了 prompt_too_long,会话中断。

这不是极端场景。一个中等复杂度的客服 Agent,加上工具调用、RAG 召回、用户上传的截图 OCR,跑 25 轮上下文就能从 8K token 涨到 118K——再多两轮,直接撞墙。

这不是模型的问题,也不是上下文窗口不够大的问题。是你送进去的 token 里,有太多是废的。

Anthropic 在 2025 年 9 月专门发了一篇工程文章定义这件事——Context Engineering(上下文工程)。不是怎么写 prompt,而是每一轮 LLM 调用时,进入上下文的每个 token 是否都值得它的成本

这是 Prompt Engineering 解决不了的问题。它发生在更底层,影响也更大。


一个真实的生产事故

先把问题的规模感建立起来。

这是一个电商客服 Agent 的单次会话 token 增长曲线:

轮次累积 Token主要构成
18Ksystem prompt + 用户首问 + 工具列表
518K+ 5 次工具调用结果(订单详情、物流轨迹)
1035K+ RAG 召回的退款政策(每轮都在召回)
1562K+ 用户上传 3 张订单截图的 OCR 结果
2095K+ 工具调用累积、Memory 召回累积
25118K⚠️ 接近 Claude 128K 上限
27prompt_too_long,会话中断,客户在线等着

这是生产事故,不是演示 Bug。

然后工程师开始修:

修法结果
加滑动窗口(只保留最近 10 轮)答非所问——用户在第 1 轮说的订单号,第 15 轮被丢了
改全量摘要压缩成本翻了 4 倍——KV Cache 命中率从 92% 骤降到 3%
工具返回 200KB 数据直接塞进上下文单条工具结果直接撑爆
摘要 prompt 写得太简单LLM 失忆——把用户名记错了

每一个"修法"都制造了新的问题。

这 4 个坑,是绝大多数做过长对话 Agent 的开发者都踩过的。本文接下来讲的,是把这 4 个坑填上之后的完整方案。


为什么上下文越长越贵、越长越蠢

Token 对 Agent 有两种成本,大多数人只在意了第一种。

财务成本是显性的——按百万输入 Token 计费,多步 Agent 循环里快速累积。30 轮对话下来,单次调用的 token 量是第 1 轮的十几倍。

认知成本是隐性的,也更危险。Transformer 的注意力机制要计算 n² 对的关系,n 是 token 数量。上下文越长,每个 token 分到的"注意力配额"越少。你塞进去的信息越多,模型对每一条的记忆越差。

Anthropic 把这个现象命名为 Context Rot(上下文腐化):随着 token 数增长,模型准确召回上下文信息的能力持续下降。不是到上限才突然崩,而是从第一轮就开始的缓慢劣化曲线。

所以把上下文窗口从 128K 扩到 200K,解决不了根本问题——只是把撞墙推后几轮,Context Rot 照样在发生。

Anthropic Applied AI 团队给出的核心结论:

“Find the smallest possible set of high-signal tokens that maximize the likelihood of the desired outcome.”

不是让模型看更多,而是让模型少看、看对的


上下文不是一段 Prompt,是 6 个组件的工程视图

把上下文理解成"一段越来越长的 prompt"——这个认知直接决定你会优化错方向。

上下文是每次 LLM 调用时即时组装的工程视图,由 6 个来源、生命周期完全不同的组件构成:

本次 LLM 请求的 Context├── System Prompt(系统指令 + 工具列表)← 静态,KV Cache 友好├── Memory 召回(历史记忆检索结果)   ← 动态,每轮可能不同├── RAG 召回(知识库检索结果)         ← 动态,每轮不同├── 历史消息(对话记录序列)           ← 累积增长,主要压力来源├── 工具返回值(本轮工具调用结果)     ← 体积不可预测,可能很大└── 当前用户输入(本轮)               ← 最新,绝对不能压缩

6 个组件,各有各的生命周期,各有各的压缩策略。把它们当成一整段文本统一处理——这是大多数 Agent "莫名变贵、莫名变蠢"的根源。

维度把上下文当 prompt把上下文当工程视图
优化对象整段文本一刀切每个组件独立优化
压缩策略统一处理各组件不同策略
KV Cache不在意静态前缀必须保住
故障隔离出错时整锅倒每个组件独立可调试
成本归因只知道总 token知道每个组件占多少

更关键的一点:四类失败(召回不准、上下文膨胀、摘要丢信息、缓存失效)在外部表现完全一样——LLM 回答变差了。混在一个黑盒里,你永远找不到根因。分层,才能分层调试。


技术一:Token 预算四象限

控制成本的第一步,是主动分配预算,而不是被动等着溢出。

以 Claude 128K 为例,留出 28K 安全余量,工作预算是 100K:

高静态性                    低静态性           ┌──────────────────┬─────────────────────────┐ 高优先级  │ System Prompt     │ 当前用户输入 + 工具返回   │           │ 约 10K            │ 约 25K                  │           │ 工具列表 + 角色设定 │ 本轮新增内容,不可压缩    │           ├──────────────────┼─────────────────────────┤ 低优先级  │ 历史消息           │ RAG / Memory 召回        │           │ 约 40K            │ 约 25K                  │           │ 累积最快,压缩收益最大 │ 控制 top_k,限制单条长度 │           └──────────────────┴─────────────────────────┘

四个象限对应四种处理策略:

  • 高静态 + 高优先级(System Prompt):绝对不压缩,保住 KV Cache 命中基石
  • 低静态 + 高优先级(当前输入 + 工具返回):不压缩,用预算硬保
  • 高静态 + 低优先级(历史消息):累积最快,压缩收益最大,走压缩管线
  • 低静态 + 低优先级(RAG/Memory 召回):从源头控制,限制检索 top_k 和单条长度

超预算时的让步顺序(写进代码,不是约定)

历史消息 → RAG 召回 → System Prompt → 永不压缩当前用户输入和工具返回值

每次组装上下文时,输出一份预算报告——出问题时一眼看出哪个象限失控了:

{    "session_id": "sess_001",    "turn": 27,    "budget_total": 100_000,    "budget_used": 87_500,    "breakdown": {        "system": 9_800,        "history": 38_200,        "rag": 18_500,        "current_input": 350,        "tool_results": 20_650,    },    "compactions_applied": ["snip", "microcompact"],    "cache_anchor_intact": True,}

💡 这部分建议收藏——预算四象限是上下文管理的思维框架,比任何单项技术都重要。


技术二:七步压缩管线

这是整篇文章的核心。

绝大多数开发者在上下文超预算时,会选两种方案之一:滑动窗口(丢信息)或全量摘要(成本爆炸)。这两种都是极端。真实工程需要的是从轻到重的代价梯度

核心原则:能截断就不摘要,能轻量压缩就不全量摘要。

AgentLoop 调用 LLM 之前          ↓步骤 1:工具结果预算检查  单条工具返回值超阈值(如 8K token)  → 替换为 Reference ID + 本地摘要(不调 LLM,成本 0)          ↓(还超预算?)步骤 2:Snip(截断,成本 0)  历史消息中过长的工具返回值就地截断  保留头尾,中间用 [... truncated ...] 替代          ↓(还超预算?)步骤 3:Microcompact(缓存友好压缩)  只压缩缓存锚点之外的部分,锚点之前一字不动  → KV Cache 命中率保持不变,这是关键          ↓(还超预算?)步骤 4:Context Collapse(折叠)  把"用户问→助手调工具→工具返回→助手答"4条消息折叠为1条          ↓(还超预算?)步骤 5:System Prompt 重组          ↓(还超预算?)步骤 6:Autocompact(全量摘要,最后手段)⚠️  把 N 轮历史摘要成一段文字  → KV Cache 全废,成本倒灌          ↓(仍超预算?)步骤 7:ContextOverflow 阻断  抛异常,交给业务层处理

七步代价对比:

步骤信息损失额外 LLM 成本缓存破坏延迟
1 工具结果预算0<10ms
2 Snip中(截断中间)0<10ms
3 Microcompact1 次小调用否(关键)~500ms
4 Context Collapse中高1 次中调用部分~1s
6 Autocompact1 次大调用是(核心代价)~3s

七步管线的全部价值,就是尽可能不走到第 6 步。 Autocompact 一旦触发,KV Cache 全废,下一轮 API 调用费用直接倒灌。很多开发者不明白为什么"摘要完成本反而涨了"——原因就在这里。

Context Collapse(步骤 4)的折叠效果大概是这样:

折叠前(约 780 token):  user: 帮我查订单 2026052001  assistant: [调用 query_order 工具]  tool: {status: "运输中", logistics: "顺丰", eta: "今晚20:00", ...}  assistant: 您的订单正在运输中,预计今晚 20:00 到达折叠后(约 80 token):  [已处理交互] 用户查询订单 2026052001;结论:运输中,顺丰,今晚20:00到

单次折叠节省约 90% 的 token,且信息完整保留。


技术三:Reference ID 模式

工具返回值是上下文膨胀速度最快、最容易被忽视的来源。

一次数据库查询可能返回 500 条记录,一个文件读取可能返回 200KB 文本,一个搜索工具可能带内容地返回 20 条结果。这些数据全塞进上下文,3 轮就能把 100K 的预算打满——而且其中 95% 的内容,在那一轮之后再也不会被用到。

做法:超过阈值的工具返回值,不进上下文,改存 Redis,只留一个 Reference ID 和本地摘要。

# 工具返回值处理逻辑(伪代码)TOOL_RESULT_THRESHOLD = 8_000# token 数阈值defhandle_tool_result(result, session_id):    if estimate_tokens(result) > TOOL_RESULT_THRESHOLD:        # 超过阈值:存外部,上下文里只放摘要 + 引用 ID        ref_id = store_to_redis(result, session_id, ttl=1800)        return {            "content": (                f"[大结果已外挂. ref_id={ref_id}]\n"                f"摘要: {local_summary(result)}\n"                f"如需完整内容: fetch_full_result(ref_id='{ref_id}')"            )        }    else:        # 未超阈值:正常注入        return {"content": result}

配套需要给 Agent 一个 fetch_full_result 工具,让它在需要完整数据时自行拉取。但工具描述里要显式劝退

【使用场景】摘要信息不足以回答用户问题时使用。【不适用】摘要已经够用时请勿调用,避免浪费 token。

这个"劝退"不是摆设——大部分情况下,摘要已经包含了模型做决策所需的信息,全量数据是不必要的。显式劝退能有效减少模型的"习惯性"全量拉取。


技术四:KV Cache 边界维护(最容易被忽视的成本杠杆)

这一节是本文含金量最高的部分,但也是大多数 Agent 工程教程完全不讲的内容。

KV Cache 是什么: OpenAI、Anthropic、DeepSeek 都有 Prompt Cache 机制——前缀字节级完全一致的请求,KV 计算结果会被缓存,后续请求直接复用,不重新计算。

各家 cache 命中的折扣:

模型未命中命中
Claude1.0×0.1×(省 90%)
GPT-4o1.0×0.5×(省 50%)
DeepSeek1.0×0.25×(省 75%)

对于一个 system prompt 有 1 万 token 的 Agent,KV Cache 命中与否,意味着这 1 万 token 的成本差了 10 倍。

什么动作会破坏 KV Cache:

  • • system prompt 改了任何一个字
  • • 工具列表顺序变了(一定要排序稳定)
  • • 历史消息中间插入或修改了内容
  • 用摘要替换了历史消息——这是 Autocompact(第 6 步)的主要代价

最后这条就是为什么"全量摘要把成本砍了"这个说法是错的——摘要确实缩短了上下文,但它同时破坏了 KV Cache,下一轮的 system prompt 要重新全量计算,实际成本反而可能翻倍。

Microcompact 的设计精妙之处:

Microcompact(七步管线第 3 步)的核心思想,就是保住缓存边界:

缓存状态(前缀完全一致,可命中 KV Cache):[system][m1][m2][m3][m4] | [m5][m6][m7][m8][m9][m10]  ↑                      ↑                          ↑已缓存的前缀           缓存锚点               当前末尾Microcompact 只压缩:[m5][m6][m7][m8][m9][m10]                    保持:[system][m1][m2][m3][m4] 一字不动→ 下次请求:[system][m1][m2][m3][m4] 前缀完全一致 → 继续命中 KV Cache

实测效果:从粗暴全量摘要(Autocompact)切换到 Microcompact 后,KV Cache 命中率从 3% 拉回 89%,单次 token 成本降到原来的 1/3

RAG 注入的一个常见错误:

很多开发者会把 RAG 召回的文档拼进 system prompt——理由是"系统知识,应该放系统里"。这是错的。

每轮 RAG 召回的内容不同,只要 system prompt 发生变化,整个缓存前缀就失效了,后面无论历史消息多长都无法命中缓存。

正确做法:system prompt 保持完全稳定,RAG 召回结果作为每轮独立的附加消息注入。


技术五:不要用简单 Prompt 做摘要

当不得不走到 Autocompact(全量摘要)时,摘要的质量决定了 Agent 会不会"失忆"。

最常见的反例 prompt:

请将以下对话历史摘要为 200 字以内的总结。{history}

这个 prompt 的输出大概是:

用户咨询了订单问题,客服提供了帮助,处理了退款申请。

——关键订单号、金额、用户名、reference_id 全部丢失。第 30 轮,Agent 开始用错误的名字称呼用户。

生产级摘要 prompt 需要做三件事:

1. 显式白名单(必须保留的实体):

必须保留的实体,原文照抄:- 所有订单号(纯数字格式)- 所有金额(含币种)- 所有时间日期- 用户提到的姓名、地址、电话- 所有 reference_id(toolres_ 开头)

2. 显式黑名单(允许省略的内容):

可以省略:- 客套话、寒暄- 重复出现的相同信息- 已被后续操作覆盖的旧状态(如旧地址被新地址覆盖)

3. 强制结构化输出:

输出格式(必须严格遵守):[关键事实]:逐条列出所有必须保留的实体[处理过程]:用户做了什么、助手做了什么(顺序叙述)[当前状态]:还在等什么、下一步是什么

加入这三条约束后,"失忆型幻觉"率从 12% 降到 1.5%


技术六:检索是预算决策,不是自动管道

大多数 RAG 实现是这样的:用户输入 → 触发检索 → 召回 top-10 → 注入上下文。这里有两个隐性浪费,加在一起往往占了 RAG 成本的一半以上。

浪费一:每轮都检索,不管有没有必要。 用户追问"刚才那个订单号多少来着",上下文里明明有答案,RAG 还是跑了一趟,召回 10 条文档,全部注入——这一轮的检索 token 完全是净浪费。

浪费二:召回 top-10,真正有用的只有 1-2 条。 那 8 条不相关的文档在上下文里占着位置,既烧 token,又稀释了注意力权重,让模型对真正有用的那两条更不专注。

我自己在一个知识问答 Agent 上测过:把 RAG 从 top-10 改成"召回后评分过滤、只保留相似度 > 0.7 的块",平均每轮注入从 4,200 token 降到 680 token,回答准确率反而提高了——因为去掉了那些相关度不高但会干扰模型的块。

两个具体改进:

Post-retrieval Filtering(召回后过滤):注入上下文之前对每个召回块打相关性分,设一个阈值,低于阈值的直接丢弃。是成本优化里单位实施成本最低、收益最大的操作之一。

Agent-Controlled Retrieval(按需检索):不要每轮自动触发检索,改成让 Agent 自己决定什么时候需要查知识库。只有推理链真正遇到知识空白时才触发,召回精准度大幅提升,无效注入基本消失。代价是要求模型的 tool-use 能力足够稳定,不会忘记在应该检索的时候检索。


技术七:把预算意识注入 Agent 自身

前六个技术都是外部工程控制。最后一个,是让 Agent 自己有预算意识。

Anthropic 在官方工程文章中专门提到了一个被大量忽视的技术:在 Agent 的上下文里告诉它自己还剩多少预算

# 在每轮组装上下文时,把预算状态告诉 Agentbudget_message = {    "role": "system",    "content": f"[当前会话状态] 已用 {used_tokens:,} / {budget_total:,} token,"               f"剩余 {remaining:,} token。"               f"{'请开始精简回答,优先完成关键步骤。' if remaining < 20_000 else ''}"}

当 Agent 知道自己的预算状态时,它会自然地开始更精简地使用工具、更早做出决策、在快耗尽时主动报告进度而不是继续探索。这个技术几乎不增加任何工程成本,但能让 Agent 的行为更像一个有成本意识的工程师。


综合效果:月度账单能降多少

把 7 个技术叠加,成本能降到什么量级?

以下是一个参考 ROI 计算(月处理量 100 万 tokens,Claude Sonnet 定价,数据来源:生产案例综合统计,实际结果因业务场景差异较大):

优化项月度节省说明
优化前基准$9,000/月50万输入 + 50万输出,无任何优化
语义缓存(70% 命中率)−$4,530相似请求复用,是单项最大贡献
Prefix Caching(80% 重复率)−$1,800system prompt 前缀命中 KV Cache
上下文压缩(七步管线,50% 压缩率)−$1,350历史消息 + 工具结果压缩
优化后≈$1,320/月节省约 85%

这些数字来自真实部署中多个 Agent 的叠加效果,但不是保证值。不同业务的 token 分布差异很大——对话密集型 Agent(客服、导购)的优化空间通常比任务执行型(代码生成、数据分析)更大。

两件事是确定的:长对话支持能力从 25 轮 → 200+ 轮;KV Cache 命中率从 3% 到 89%,成本差距是实打实的 3 倍。


Anthropic 对长任务的三个建议

最后补充 Anthropic 工程团队在官方文章里,专门针对长任务(跑几十分钟甚至几小时的任务)给出的三个策略,和七步管线互补:

Compaction(滚动压缩):接近上下文上限时,把历史摘要后开一个新的干净窗口继续跑。适合需要大量来回对话的任务。这就是七步管线里 Autocompact 的宏观版本。

Structured Note-Taking(结构化笔记):让 Agent 主动把关键信息写入外部文件(比如 NOTES.md),按需调回。好处是持久化成本极低,召回灵活。Anthropic 用这个技术让 Claude 在 Claude Plays Pokémon 里跨越数千步和多次上下文重置,自主追踪地图和战略状态。

Sub-Agent 分工:专业子 Agent 处理专注任务,完成后只返回 1,000-2,000 token 的摘要给主 Agent。子 Agent 可能消耗数万 token 做深度工作,但主 Agent 始终保持干净的上下文。Anthropic 自家的多 Agent 研究系统用的就是这个方案,在复杂研究任务上"远优于单 Agent 系统"。

三种技术适用不同场景,选型参考:

场景推荐策略
需要大量来回对话的任务Compaction(滚动压缩)
有明确阶段里程碑的开发任务Structured Note-Taking
需要并行探索的复杂研究/分析Sub-Agent 分工
以上都有组合使用

行动清单

如果你的 Agent 现在还没做上下文工程,按优先级来:

第一周(立竿见影):

  • • 给 system prompt 加 Prefix Cache 标记(Claude: cache_control,OpenAI: 自动)
  • • 把 RAG 召回从 system prompt 里移出来,改为每轮独立消息
  • • 给工具列表排序固定化,避免顺序变化破坏缓存

第二周(核心防护):

  • • 实现工具返回值阈值检测,超过 8K token 走 Reference ID 模式
  • • 实现 Token 预算监控报告,每轮打印各组件占比
  • • 实现 Snip(步骤 2)——最小成本,第一道防线

第三周(工程级):

  • • 实现 Microcompact(步骤 3)——保住 KV Cache 命中率的关键
  • • 写生产级 Autocompact Prompt(白名单 + 黑名单 + 结构化输出)
  • • 给 Agent 注入预算状态消息

把这三周做完,你的 Agent 大概率不会再在第 27 轮崩掉了。


写在最后:名字之前,问题就在

Context Engineering 这个词,Anthropic 在 2025 年 9 月才给它命名。但这个问题本身,从第一个人做 Agent 就存在了——只是之前叫"上下文管理"或"token 优化",没有一套系统的框架。

有了名字和框架的价值不在于概念本身,而在于它让你能把分散的技术手段归拢到同一个问题维度下讨论。知道"这是 KV Cache 边界问题"和"这是压缩管线没有做分层",才能对症下药,而不是在无数可能的原因里瞎猜。

我的判断是:2026 年做生产级 Agent 的工程师,Context Engineering 会是像数据库索引一样的基础能力——不是加分项,而是不做就一定出问题。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

在这里插入图片描述

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐