智能体越跑越贵?缓存读取降价 75% 之后,我发现真正该改的是负载结构
如果你正在用 Claude 这类模型搭建智能体(Agent),最近一定会被一个新消息刷屏:缓存读取价格下调 75%。很多人的第一反应是“单次调用便宜了嘛,挺好”。但如果你只看到这层,很可能错过一个更重要的信号——这次降价真正改变的是智能体负载的成本结构,而不是单纯把 API 账单打了个折扣。
为什么这么说?
做过 Agent 工程的人都有体会:智能体跑一个多步骤任务,比如“查资料 → 写总结 → 生成报告 → 发通知”,每一步都要带着完整的系统提示词、工具定义、历史消息和中间结果去调用模型。这些内容有相当大比例是重复的,而且会在每一轮请求里反复传给模型。于是,成本大头往往不是“模型生成答案”那部分,而是“重复读取同一批上下文”的那部分。如果缓存读取能便宜 75%,整个智能体的负载成本为什么只降了约 45%?其余的 30% 去哪了?这篇文章就把这个问题拆开讲清楚。
读完这篇文章,你会得到三样东西:一是理解缓存定价背后的运行逻辑,二是学会判断自己的 Agent 项目到底能省多少钱,三是知道下一步调整智能体架构时,应该把精力放在哪些真正影响成本的环节上。
1. 智能体成本为什么总在失控
先说一个很常见的场景。你让一个智能体扮演“市场分析助手”,它需要完成:
- 读取企业上传的十份 PDF 文档;
- 调用搜索工具补充行业趋势;
- 生成一份包含图表建议的市场月报。
从表面看,这只是一个任务。但在底层,模型可能需要完成十几轮甚至是几十轮推理,因为智能体要知道“下一步应该调用哪个工具”“文档里哪一段和当前问题相关”“中间结果是不是已经足够生成报告”。每一轮推理,都要把前面已经积累的上下文重新发送给模型。
这个过程中最典型的浪费是:系统提示词(比如“你是一个严谨的市场分析师,请按照如下格式输出”)、工具说明(比如“你有一个 web_search 工具,参数是 query”)、历史消息(比如前面已经读过的 PDF 文本片段)全部被一遍又一遍地传输和计算。
在没有缓存机制的年代,无论内容是否重复,模型服务端都会按完整输入长度计费。于是,智能体的成本曲线往往不是线性增长,而是“会话越长、工具越多、步骤越多,平均每轮的有效新信息越少,重复成本越高”。
这里先引入一个关键概念:Prompt Caching(提示词缓存)。它的思路是,当同一段前缀内容在短时间内被重复提交时,模型服务商不需要重新计算它的编码表示(token 向量),可以直接复用上次计算好的结果。用户只需要为“缓存命中”支付一小部分读取费用,而不是按完整输入价格重新付费。
这就是为什么这次缓存读取降价,对智能体类项目的影响远大于对普通单次对话的影响。因为普通聊天虽有重复,但并不会像 Agent 一样在同一个会话里反复塞入大量工具定义和历史记录。
2. 缓存读取降价的真正成本含义
要理解“缓存读取降价 75%”的影响,先要把一次 API 调用的费用拆开来看。以典型的对话补全(chat completion)接口为例,账单上的成本主要由三部分构成:
| 成本部分 | 含义 | 典型例子 |
|---|---|---|
| 输入 token 费用 | 你提交给模型的全部内容,包括系统提示词、工具定义、历史消息、用户问题 | 系统提示词 + 多轮对话历史 + 工具 JSON Schema |
| 缓存写入费用 | 内容首次被处理并存入缓存,或者缓存过期后需要重新写入 | 第一次提交一段带有缓存标记的新前缀 |
| 输出 token 费用 | 模型生成答案所产生的 token | 回复内容、思考内容 |
在智能体场景中,输入 token 往往占绝对大头。一次调用里,用户新输入可能只有几十个 token,但完整的上下文前缀可能高达几千甚至几万 token。这些 token 如果每一轮都重新计费,成本立刻就失控。
缓存机制的引入改变了这个局面:同一段前缀如果被重复使用,模型服务商只需要读取已经算好的结果,不再需要重新做全量编码。而“读取缓存”的成本定价往往大幅低于“重新计算输入”的成本。这次降价 75%,意味着缓存读取的边际成本变得更低,相当于给所有重复性上下文开了一条“高复用率专属通道”。
这里要解释一个容易混淆的点:“缓存命中”不等于“免费”。缓存命中仍然要花钱,只是价格远低于原始输入。它更像“买书 vs 借书”的区别——首次购买很贵,之后反复借阅只需要一小笔手续费。如果系统设置不合理,缓存命中率很低,那么降价 75% 对你的账单影响就非常有限。
从材料给出的行业解读来看,Rohan Paul 在分析时做了一个关键拆分:为什么缓存读取降了 75%,整体负载成本只降约 45%?原因是整体负载成本里不仅包含缓存读取,还包含缓存写入、输出 token、以及那些无法命中缓存的新增上下文部分。缓存读取降价只能作用于“命中缓存的那一部分 token”,而不是全部成本。这正好解释了为什么不能简单地把 75% 直接乘到总成本上。
3. 智能体负载的典型特征与成本结构
要读懂这次降价对 Agent 项目的影响,需要先搞清楚智能体负载到底长什么样。
一个典型的智能体请求过程可以抽象成下面这副图景。假设一个 Agent 由三个节点组成:规划器(planner)、工具调用器(tool executor)、总结器(summarizer)。用户提出一个问题后,每个节点都会向模型发送一次请求。每次请求的 payload 通常包含:
{ "model": "claude-model", "messages": [ { "role": "system", "content": "你是一个智能体,负责拆解任务并调用可用工具。" }, { "role": "user", "content": "请分析公司上季度的销售数据。" }, { "role": "assistant", "content": "我将先查询数据库,然后生成分析报告。" }, { "role": "tool_result", "content": "查询结果:销售额 1200 万,环比增长 8%……" }, { "role": "assistant", "content": "基于查询结果,我进一步需要生成报告……" } ], "tools": [ { "type": "function", "function": { "name": "query_database", "description": "查询企业数据库", "parameters": { "type": "object", "properties": { "sql": { "type": "string", "description": "SQL 语句" } } } } } ] }注意观察:messages和tools里的内容,在同一个会话的每一轮调用中几乎完全一样,只有新增加的那一条消息不同。如果这个 Agent 一轮任务需要调用模型 20 次,那么前 19 次都在反复携带同一份前缀。
如果只看单次请求,你很难感受到问题。但如果把 20 次请求合并成一个会话,就会发现:有效的新信息只占全部输入 token 的极小比例,大部分 token 都是重复的上下文。缓存机制恰恰就是为这种“会话内高频重复读取”的场景设计的。
所以,智能体负载的成本结构,通常呈现这样一个特征:
| 组成部分 | 占预算比例(典型情况) | 是否受缓存降价直接影响 |
|---|---|---|
| 缓存命中读取 | 30% - 50% | 是,直降 75% |
| 缓存首次写入 | 15% - 25% | 否,价格不变 |
| 未命中缓存的新输入 | 10% - 20% | 否,价格不变 |
| 输出 token | 20% - 35% | 否,价格不变 |
不同项目比例差异很大,但缓存命中读取普遍占据显著份额。这也就是为什么缓存降价 75% 后,整体成本只下降约 45%:因为不是所有成本都属于“可以打折”的部分,输出 token 和首次写入仍然按原价计费。
4. 多步骤会话与多智能体协作中的成本放大效应
缓存降价的影响还体现在一个容易被忽略的地方:它让多步骤会话和多智能体协作的工程方案变得更加可行。
此前,很多团队在设计 Agent 时,会刻意压缩上下文:比如每轮只保留最近两三条消息,或者每次调用后把历史记录清空。这种做法的初衷是控制成本,但也带来了副作用——模型失去了对完整任务的记忆,经常需要重复解释目标,甚至出现“聊着聊着忘记前面查过什么”的尴尬局面。
缓存降价之后,同样的成本预算可以支撑更长的上下文保留。你不必为了省钱而牺牲 Agent 的记忆能力,因为你保留的上下文越大,缓存命中的比例往往越高,单位成本反而越划算。
对于多智能体(Multi-Agent)系统来说,这个变化更明显。在多个 Agent 分工协作的场景下,每个子 Agent 往往需要共享一份全局上下文,比如项目目标、工作区目录结构、已经产生的中间结论。无缓存时,每个子 Agent 都要从头加载这份全局上下文;有缓存时,第一个 Agent 写入一次,后续所有 Agent 都能以极低价格读取同一份前缀。
这相当于把团队的“会议纪要”从每人复印一份,变成了共享一份在线文档,大家按需快速查看。多智能体协作如果设计得当,缓存命中率甚至可以超过 70%,成本下降会比单 Agent 场景更明显。
5. 从 75% 到 45%:一次完整的成本测算示例
为了把“为什么只降 45%”这件事讲清楚,我们用一个具体测算示例来演示。假设一个智能体任务总共消耗 100 万 token,成本构成如下:
| 项目 | Token 数量 | 单价(相对原始输入的倍率) | 费用 |
|---|---|---|---|
| 缓存写入 | 30 万 | 1.25x | 37.5 万单位 |
| 缓存读取 | 40 万 | 0.10x(降价后) | 4 万单位 |
| 未命中输入 | 10 万 | 1x | 10 万单位 |
| 输出 | 20 万 | 5x | 100 万单位 |
| 合计 | 100 万 | - | 151.5 万单位 |
如果缓存读取不降价,按原来的 0.40x 计算,缓存读取费用是 16 万单位,总费用是 163.5 万单位。降价后变成了 151.5 万单位,降低了约 7.3%。
这个数字离 45% 还很远。问题出在哪?答案是缓存读取在整体负载中的占比还不够高,而且缓存读取单价即使按原来的 0.40x 计算,本来也不贵。
那么 Rohan Paul 分析的 45% 是怎么来的?关键在于:他的测算针对的是典型的“长会话 + 高复用”Agent 负载,也就是缓存读取 token 占比极高(比如 70% 以上)、输出 token 占比被控制得较低的场景。在这种负载模式下:
- 降价前:缓存读取 70 万 token × 0.40x = 28 万单位
- 降价后:缓存读取 70 万 token × 0.10x = 7 万单位
- 其他成本不变:假设为 33 万单位
- 总成本从 61 万单位降到 40 万单位,降幅约 34%
如果再叠加其他优化手段,比如减少未命中输入、压缩输出 token,45% 的整体降幅是可以实现的。这说明一个问题:缓存降价是杠杆,但你的负载结构决定了杠杆能撬动多少收益。
下面的 Python 脚本可以直接复用,用来估算你自己的 Agent 负载能省多少钱:
def estimate_agent_cost_saving( total_tokens: int, cache_read_ratio: float, output_ratio: float, write_ratio: float, old_cache_read_price: float = 0.40, new_cache_read_price: float = 0.10, normal_input_price: float = 1.0, output_price: float = 5.0, write_price: float = 1.25, ): """ 估算缓存读取降价前后,智能体负载成本的变化。 ratio 参数为各类 token 在总 token 中的占比,总和应为 1.0。 返回字典,包含降价前总成本、降价后总成本、节省比例。 """ assert abs(cache_read_ratio + output_ratio + write_ratio) <= 1.0, ( "缓存读取、输出、写入三类占比之和不能超过1" ) miss_ratio = 1.0 - cache_read_ratio - output_ratio - write_ratio cost_before = total_tokens * ( cache_read_ratio * old_cache_read_price + miss_ratio * normal_input_price + output_ratio * output_price + write_ratio * write_price ) cost_after = total_tokens * ( cache_read_ratio * new_cache_read_price + miss_ratio * normal_input_price + output_ratio * output_price + write_ratio * write_price ) saving_ratio = (cost_before - cost_after) / cost_before return { "cost_before": cost_before, "cost_after": cost_after, "saving_ratio": saving_ratio, } # 典型长会话 Agent 负载:缓存读取占 70%,输出占 10%,写入占 15% result = estimate_agent_cost_saving( total_tokens=1_000_000, cache_read_ratio=0.70, output_ratio=0.10, write_ratio=0.15, ) print(f"降价前成本: {result['cost_before']:.2f} 单位") print(f"降价后成本: {result['cost_after']:.2f} 单位") print(f"节省比例: {result['saving_ratio'] * 100:.2f}%")运行这段脚本,你会看到类似这样的输出:
降价前成本: 610000.00 单位 降价后成本: 400000.00 单位 节省比例: 34.43%如果你的缓存命中率更高、输出 token 占比更低,节省比例会更接近 45%。所以,45% 不是固定数字,而是一个“高缓存命中型负载”的参考值。
6. 如何提升缓存命中率:三个可落地的工程建议
既然缓存命中率决定了节省幅度,那么下一个问题就是:如何提升缓存命中率?
第一,控制上下文前缀的稳定性。缓存的命中前提是“前缀完全一致”,哪怕只改了一个标点符号,也可能导致缓存失效。所以系统提示词、工具定义、知识库前缀内容要尽量保持稳定,不要频繁拼接动态内容。不要把当前时间戳直接拼进系统提示词里,而是放到用户的最后一条消息中,或者作为单独的 user message 追加在后面,避免破坏缓存前缀。
第二,把静态内容前置,动态内容后置。模型在处理上下文时,缓存机制通常针对前缀生效。静态内容比如系统角色设定、工具 JSON Schema、知识库固定内容,应该放在 messages 数组最前面,动态内容比如临时查询结果、用户最新输入,应该放在最后面。这样每次调用时,前缀都能命中缓存。
第三,使用显式缓存控制参数。很多模型 API 支持在系统提示词或消息级别设置cache_control标记。比如下面这段示例,就是在 Anthropic API 风格中启用缓存写入的配置:
from anthropic import Anthropic client = Anthropic() response = client.messages.create( model="claude-model", max_tokens=1024, system=[ { "type": "text", "text": "你是一个智能体,负责拆解任务并调用工具。", "cache_control": {"type": "ephemeral", "ttl": "300s"} } ], messages=[ {"role": "user", "content": "分析公司上季度销售数据。"} ], tools=[ { "name": "query_database", "description": "查询企业数据库", "input_schema": { "type": "object", "properties": { "sql": {"type": "string"} } } } ] ) print(response)这段代码的关键点有两个。一是system部分通过cache_control显式声明需要缓存,并且设置了存活时间;二是tools和system内容在会话期间保持稳定,这样后续请求才有机会复用缓存。
如果你的调用工具是 Dify 这类智能体平台,通常可以在模型配置或节点设置里找到缓存开关。建议先阅读平台文档确认默认行为,因为不同平台对缓存的支持程度不一样。
7. 缓存降价后的架构选择:该不该重新设计 Agent
缓存降价不仅影响成本,还影响架构决策。以前很多团队不敢做“长上下文记忆”,现在可以重新评估。
一个明显的变化是:在同等预算下,你可以把更多上下文塞进会话里,让 Agent 看到更多历史步骤和中间结果。这意味着任务拆分的粗粒度可以更细,Agent 可以更频繁地“回头看”之前的内容,而不必担心每多看一次就多付一次全量输入的价格。从架构上看,你可以把一些原本放在外部存储里的上下文(比如向量数据库检索结果)直接保留在会话上下文里,减少额外的数据流转。
但也要注意反向陷阱。缓存降价不意味着“上下文无限增长”。缓存的 TTL 到期后需要重新写入,写入价格并不便宜,而且超长上下文即使命中缓存,读取 token 数量一多,费用依然可观。所以“能塞就塞”不是最佳策略,更合理的做法是:
- 固定部分(系统提示词、工具说明、长期目标)放前面,尽量保持稳定;
- 临时部分(单步工具返回、临时思考)放后面,用完能丢就丢;
- 外部知识优先做检索过滤,只把最相关的段落注入上下文,而不是无脑全量塞入。
从架构角度看,缓存降价让“以缓存为设计目标”成为了一个新的优化方向。设计系统提示词时,可以像设计数据库主键一样,考虑“这段内容会不会被反复读取”“改变它会不会影响后续所有缓存命中”。
8. 多智能体协作的成本新模型
如果你在做多智能体或者工作流编排,缓存降价的收益可能会被进一步放大。
以 Dify 这类智能体平台为例,一个工作流可能包含多个节点,每个节点都会调用模型。如果没有缓存,每个节点都要独立计算公共上下文;有缓存后,只要公共前缀一致,后续节点都能享受缓存读取价格。
有一个工程细节很值得注意:多个节点之间共享上下文时,要保证上下文拼接顺序完全一致。例如,节点 A 的上下文是“系统提示词 + 文档A”,节点 B 的上下文是“系统提示词 + 文档B”,这两个节点的前缀不同(因为文档A和文档B不同),缓存无法跨节点复用。更合理的做法是,把公共前缀统一成“系统提示词 + 公共知识”,然后把文档A、文档B都放到动态追加部分。这样,即使节点 A 和节点 B 处理不同的任务,它们共享的公共前缀仍能命中同一份缓存。
对于多智能体协作框架,比如 A2A(Agent-to-Agent)协作模式,情况类似。每个 Agent 在收到任务时都会附带一份共享的全局上下文,缓存降价后,共享上下文的边际成本大幅降低,这会让“让多个 Agent 共享完整项目背景”成为一个更经济的选择。
9. 常见问题与排查思路
在实际把智能体接入缓存降价接口时,总会遇到几个高频问题。这里整理成表格,方便对照排查。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 账单金额没有明显下降 | 缓存命中率低,缓存读取 token 占比太小 | 查看 API 平台提供的缓存命中统计和用量分析 | 优化上下文前缀稳定性,把静态内容前置,动态内容后置 |
| 缓存从未命中 | 未使用显式缓存控制参数,或每次请求都修改了前缀内容 | 检查 API 请求日志,对比两次请求的 content 是否一致 | 在 system 中加入 cache_control,并统一系统提示词内容 |
| 上下文明明一样,但缓存写入费用增加 | TTL 过期后重新写入是正常现象 | 检查两次请求的时间间隔是否超过 TTL | 根据会话频率调整 TTL;长会话内尽量保持连续请求 |
| 多智能体之间无法共享缓存 | 各 Agent 的上下文前缀不一致,例如拼接了不同的用户身份字段 | 检查各 Agent 发送的 messages 数组头部内容是否一致 | 将公共部分提取到系统提示词,用户信息放到动态消息末尾 |
| 输出 token 费用占比升高 | 智能体生成内容过长,输出 token 不受缓存降价影响 | 查看账单中输出 token 的费用比例 | 控制 max_tokens、精简输出格式、使用结构化输出减少冗余 |
| 长会话中途缓存失效 | 上下文超过窗口上限,触发截断或重置 | 查看请求返回的上下文窗口使用情况 | 定期摘要历史消息,用摘要替换旧消息,减少上下文长度 |
这里需要强调的是,每一个排查步骤都建议先在小流量或者测试环境里验证,再应用到生产环境。成本优化的本质是工程调优,不是一次性配置,更需要持续观测。
10. 成本监控与回归测试的工程实践
缓存降价带来了成本红利,但也对工程团队提出了新的要求:你要能看见自己的缓存命中率,不然降价跟你关系不大。
推荐建立几个核心监控指标:
| 指标名称 | 计算公式 | 作用 |
|---|---|---|
| 缓存读取占比 | 缓存读取 token ÷ 总输入 token | 判断上下文复用程度 |
| 缓存命中率 | 缓存读取 token ÷(缓存写入 token + 缓存读取 token) | 判断缓存是否有效 |
| 单任务成本 | 总费用 ÷ 任务完成数 | 判断业务成本趋势 |
| 平均上下文长度 | 输入 token ÷ 请求次数 | 判断上下文是否过度膨胀 |
在团队协作中,可以建立一个简单的每日扫描任务,用脚本拉取 API 账单数据,计算上述指标。如果发现缓存读取占比低于 30%,说明当前的对话设计里重复内容太少,或者缓存前缀不稳定,需要回顾提示词和工具定义的设计。
以下是一个最小成本监控脚本的示例:
import json import requests def get_cost_metrics(api_base: str, api_key: str, start_date: str, end_date: str): """ 拉取成本与用量数据,计算缓存命中率和单任务成本。 实际接口地址和参数以服务商文档为准,这里仅演示结构。 """ headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } params = { "start_date": start_date, "end_date": end_date, } resp = requests.get(api_base + "/v1/usage", headers=headers, params=params, timeout=10) resp.raise_for_status() data = resp.json() input_tokens = data.get("input_tokens", 0) cache_read_tokens = data.get("cache_read_tokens", 0) cache_write_tokens = data.get("cache_write_tokens", 0) total_cost = data.get("total_cost", 0) tasks = data.get("tasks_completed", 1) metrics = { "cache_read_ratio": cache_read_tokens / max(input_tokens, 1), "cache_hit_rate": cache_read_tokens / max(cache_read_tokens + cache_write_tokens, 1), "cost_per_task": total_cost / max(tasks, 1), } return metrics if __name__ == "__main__": metrics = get_cost_metrics( api_base="https://api.example.com", api_key="your-api-key", start_date="2025-01-01", end_date="2025-01-07", ) print(json.dumps(metrics, indent=2, ensure_ascii=False))运行这段脚本后,你会得到类似这样的输出:
{ "cache_read_ratio": 0.65, "cache_hit_rate": 0.82, "cost_per_task": 0.12 }如果cache_hit_rate长期低于 0.5,就要认真检查上下文前缀的稳定性了。如果cost_per_task没有随着缓存降价而下降,说明你的工作负载本身缓存命中率很低,降价红利没有被吃满。
11. 从成本角度看 Agent 工程的下一步方向
缓存读取降价 75% 这件事,放到更大的时间尺度看,并不是一次孤立的调价,而是模型服务商业化走向成熟的信号。当模型服务商愿意在“读取”这件事上大幅让利,说明他们的缓存基础设施已经足够成熟,也说明智能体负载已经成为重要的付费场景。
对开发者来说,这意味着两件事。
第一,缓存读取的定价策略正在成为 Agent 架构设计的一个新变量。以前选架构是看性能、看开发效率、看模型能力;现在还要看“这个架构能不能产生高比例的可缓存前缀”。一个好的 Agent 设计,不只是逻辑清晰,还要在上下文布局上做到“该稳的稳、该变的变”。
第二,智能体的成本优化正在从“少调模型”转向“聪明地调模型”。以前省成本,常见手段是减少模型调用次数、换更小的模型。现在多了第三个手段:让每次调用尽量命中缓存,把同一份昂贵的上下文编码结果反复利用。
如果你正在搭建 AI 智能体、多智能体系统,或者使用 Dify、Claude Code 这类工具,接下来的优化思路可以按照下面四步推进:
- 先做成本体检,用账单数据和监控脚本摸清缓存命中率、缓存读取占比、单任务成本;
- 再优化上下文布局,把静态内容前置并稳定化,动态内容后置并控制长度;
- 然后调整架构策略,在多节点工作流中统一公共前缀,提升跨节点缓存复用;
- 最后建立成本回归测试,每次修改系统提示词或工具定义后,观察缓存命中率是否变化。
不要一上来就准备重构整个 Agent 架构,也不要因为看到了 45% 的降幅数字就把所有希望寄托在缓存上。缓存降价是一个放大器,它放大的前提是你的 Agent 本身设计了大量重复读取的上下文。如果你的系统每次请求的内容差异很大,缓存能帮你省的钱就非常有限。
从更长远的角度看,随着 Agent 负载成为主流,模型服务商还会继续优化缓存机制、上下文管理和调度策略。对工程团队来说,只有把成本感知内建到系统设计里,才能真正享受每一轮降价红利。这也是这次缓存降价带给我们的最大启示:智能体成本模型正在改变,而你能省多少钱,取决于你多早看清这种改变。