你的智能体在每一轮都会发送相同的系统提示词、工具定义、架构和策略指令。在一个6轮会话中,即使唯一变化的是用户的最新消息或智能体的最新工具结果,你仍可能为同一段开头内容被计费6次。
提示词缓存解决了这个问题。服务提供商会从缓存中读取你提示词中重复的部分,而不是每次都按全价收费。粘性路由通过将会话送回持有热缓存的同一提供商,使这一机制在跨轮次中持续生效。
本文涵盖费用方面:缓存 token 的成本是多少,为什么缓存读取和写入的定价不同,session_id 如何从第一轮开始保持智能体会话的热度,以及如何检查缓存是否实际生效。
太长不看版
- 缓存读取的成本是全新输入 token 的0.1倍到0.5倍,具体取决于提供商。在 Claude Sonnet 4.6 上,缓存读取价格为每百万 token 0.30美元,而输入价格为每百万 token 3.00美元,正好是0.1倍。
- 首次请求需要支付缓存写入费用。Anthropic 的写入成本是输入成本的1.25倍(5分钟 TTL)或2.0倍(1小时 TTL),因此一次未被复用的写入成本比完全不使用缓存更高。
- 热缓存只有在你的下一个请求落在同一提供商端点时才有效。在超过70个提供商中,第二轮可能会命中一个冷端点,此时你需要支付全价。
- 我们的粘性路由将后续请求固定到持有热缓存的提供商,而 session_id 从首次成功请求开始(在任何缓存命中发生之前)就强制实现这一点。
- 缓存未命中由4种原因导致:提示词过短、缓存过期、开头内容不断变化,或者请求转移到了不同的提供商。请检查 usage 响应中的 cached_tokens 字段以确认是否命中。
提示词缓存能降低多少 token 成本?
缓存读取的成本是正常输入定价的0.1倍到0.5倍,具体取决于提供商。正是这个范围使得缓存能够大幅降低智能体循环的成本。
重复的部分通常是成本高昂的部分:一段很长的系统提示词、工具定义、JSON 模式、护栏、检索到的文档,或是保持模型一致性的示例。没有缓存时,每一轮交互都要为所有这些内容支付全价。有了缓存,第一次请求会将其写入缓存,后续请求则以更优惠的价格读取。
以下是各提供商层面的情况:
| 提供商 | 缓存读取 | 缓存写入 | 启用方式 |
|---|---|---|---|
| Anthropic Claude(5 分钟 TTL) | 0.1 倍输入价格 | 1.25 倍输入价格 | 自动或显式 |
| Anthropic Claude(1 小时 TTL) | 0.1 倍输入价格 | 2.0 倍输入价格 | 显式(ttl: "1h") |
| OpenAI(GPT-5.6 之前) | 0.25 倍至 0.50 倍输入价格 | 免费 | 自动 |
| OpenAI(GPT-5.6 及之后) | 0.25 倍至 0.50 倍输入价格 | 1.25 倍输入价格 | 自动或显式 |
| Google Gemini(隐式) | 0.25 倍输入价格 | 免费 | 自动 |
| Grok(xAI) | 0.25 倍输入价格 | 免费 | 自动 |
| 月之暗面(Moonshot AI) | 0.25 倍输入价格 | 免费 | 自动 |
| Groq | 0.5 倍输入价格 | 免费 | 自动(Kimi K2 模型) |
| DeepSeek | 0.1 倍输入价格 | 1.0 倍输入价格 | 自动 |
| 阿里巴巴通义千问(Alibaba Qwen) | 0.1 倍输入价格 | 1.25 倍输入价格 | 显式(cache_control) |
| Z.AI | 约 0.2 倍输入价格 | 免费 | 自动 |
提示词缓存文档中有完整的详细说明。具体的美元金额仍取决于模型和提供商路由;这个倍数告诉你,对于该提供商而言,缓存输入与普通输入相比的价格关系。
对于智能体构建者来说,模式很简单:第一轮交互可能需要付费来建立缓存,但只要相同的开头部分被重复使用,此后的每一轮交互都会便宜得多。
成本花在了哪里:缓存写入还是缓存读取?
提示词缓存有两种成本:写入和读取。
当提供商存储提示词中可重复使用的部分时,会发生写入操作。当后续请求重用该存储内容时,会发生读取操作。一旦相同的内容被读取足够多次,足以覆盖写入成本,你就开始节省成本了。
在某些提供商那里,写入成本高于普通输入。Anthropic 的缓存写入成本,对于默认的 5 分钟 TTL 是输入价格的 1.25 倍,对于 1 小时 TTL 则是输入价格的 2.0 倍。一次从未被重用的 Anthropic 缓存写入,其成本比不使用缓存发送相同的提示词还要高。
对于一次性请求,缓存可能没有帮助。对于多轮智能体,重复是默认情况:智能体在整个会话过程中携带相同的指令、工具、架构和策略上下文。因此,写入操作在几轮交互后就能收回成本。
对于下一轮请求很快到来的短时突发场景,使用 5 分钟缓存生存时间(TTL)。当会话可能暂停足够长的时间导致默认缓存过期,但内容仍值得保留时,则使用 1 小时缓存生存时间。
为什么热缓存在下一次请求时并不总是有效?
热缓存仅在下一个请求落在持有该缓存的提供商端点上时才有帮助。
当请求可能路由到多个提供商时,第一轮可能在一个提供商上写入缓存,而第二轮却落在别处。第二个提供商没有热缓存可读取。请求仍然能工作,但你需要支付全价,且 `cached_tokens` 保持低值或为零。
这就是我们将粘性路由与提示词缓存配对使用的原因。在缓存请求之后,当该提供商的缓存读取价格低于常规输入价格时,我们会将同一模型的后续请求路由回同一个提供商端点。如果该粘性提供商不可用,OpenRouter 会回退到下一个可用提供商,而不是让请求失败。
默认情况下,OpenRouter 通过哈希对话的第一条系统消息或开发者消息以及第一条非系统消息来识别一个对话。当这些开头消息保持不变时,这种方式有效。
智能体常常会打破这一点。有些智能体会在总结状态、重新排序工具上下文或添加新的运行元数据时重写它们的第一条消息。当开头消息发生变化时,哈希值也会改变,对话就可能落到不同的提供商上。解决方案是使用显式的 `session_id`。
使用 `session_id` 从第一轮就强制使用热缓存
对于智能体循环,请设置 `session_id`。当你传递它时,OpenRouter 会直接将其用作粘性路由键,而不是从开头消息中派生一个键。
使用 `session_id` 后,粘性路由会在首次请求成功之后、任何缓存命中发生之前生效。不使用 `session_id` 时,粘性路由只有在检测到缓存命中后才会开始。对于多轮智能体而言,这决定了缓存是从第一轮开始就可靠,还是仅仅有时处于预热状态。
你可以将 `session_id` 作为请求体的顶层字段发送,或者通过 `x-session-id` 请求头发送。请在整个对话或智能体运行期间保持该值稳定,并将其控制在 256 个字符以内。
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.6",
"session_id": "my-agent-session-abc123",
"messages": [{"role": "system", "content": "..."}]
}' from openrouter import OpenRouter
client = OpenRouter()
resp = client.chat.send(
model="anthropic/claude-sonnet-4.6",
session_id="my-agent-session-abc123",
messages=[{"role": "system", "content": "..."}],
) import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const response = await openRouter.chat.send({
model: 'anthropic/claude-sonnet-4.6',
session_id: 'my-agent-session-abc123',
messages: [{ role: 'system', content: '...' }],
}); 使用与工作单元相匹配的值:例如一个聊天线程、工单、工作流运行或智能体任务。不要为每一轮都创建新的 `session_id`,否则请求将无法落在持有缓存的提供商上。
如果你使用自动路由或帕累托路由等路由模型,会话粘性不仅会固定提供商,还会固定路由模型所选择的模型。这可以防止对话在会话中途切换模型,从而保持行为一致性并维持缓存预热状态。
如何确认提示词缓存是否真的在生效?
最快的检查方式是查看用量数据。
在响应中,`usage.prompt_tokens_details.cached_tokens` 字段显示从缓存中读取了多少个 token。如果该值大于零,则说明该请求命中了缓存。`cache_write_tokens` 字段则显示在缓存写入请求期间写入了多少个 token。
{
"usage": {
"prompt_tokens": 10339,
"completion_tokens": 60,
"total_tokens": 10399,
"prompt_tokens_details": {
"cached_tokens": 10318,
"cache_write_tokens": 0
}
}
} 在这个例子中,大部分提示词 token 来自缓存,并且本轮没有写入新的缓存条目。
你可以在三个地方检查缓存行为:活动页面的详情视图、`/api/v1/generation` API,以及 API 响应返回的 `usage.prompt_tokens_details` 对象。
使用 `cache_discount` 可以查看一次生成节省了多少成本。在提供付费写入服务的提供商上,你可能会在写入轮次看到负折扣,因为缓存写入的成本高于普通输入。在后续的缓存读取轮次中,折扣应变为正值。
为什么你的缓存会未命中,以及如何避免?
当缓存看起来失效时,通常可归结为以下四种原因之一:提示词太短、缓存已过期、开头内容发生变化,或者请求被路由到了不同的提供商。
提示词低于提供商的最低要求。
每个提供商都有最低提示词大小,低于该大小则不会缓存任何内容。在 Anthropic 上,Claude Opus 4.5 到 4.8 以及 Claude Haiku 4.5 需要 4,096 个模型 token;Claude Haiku 3.5 需要 2,048 个;Claude Sonnet 4、4.5 和 4.6(以及 Opus 4 / 4.1)需要 1,024 个。OpenAI 需要 1,024 个。Gemini 2.5 Pro 需要 4,096 个;Gemini 2.5 Flash 需要 1,024 个。
如果你的可复用内容低于该最低值,缓存将不会启动。不要为了强制触发缓存而用填充文本填充请求。在你已经拥有大量可复用内容的地方使用缓存:工具、模式、检索到的文档、示例或策略文本。
缓存已在轮次之间过期
缓存存活时间不长。Anthropic 的默认值是 5 分钟,对于更长的会话可提供 1 小时选项。Gemini 的隐式缓存大约持续 3-5 分钟,并且在你读取时不会重置。一旦缓存过期,下一次请求就必须写入一个新的缓存。
如果你的用户经常在轮次之间暂停,请在支持的地方使用更长的 TTL,或者构建智能体使其在空闲期后接受新的写入。
提示词的开头不断变化
当提示词的开头保持不变时,自动和隐式缓存的效果最佳。将稳定的内容放在前面:系统指令、工具、模式以及固定的参考资料。将变化的内容放在后面:用户问题、时间戳、临时状态、工具输出以及短期的元数据。
这里的小细节很重要。第一条系统消息中的时间戳会让提示词在每一轮看起来都是新的。如果时间戳不需要成为缓存内容的一部分,请将其移到后面的用户或工具消息中。
请求被路由到了不同的提供商
缓存存在于其写入的位置。如果后续请求被路由到不同的提供商端点,该端点无法读取之前的缓存。
对于智能体工作流,请设置 session_id,并让粘性路由将会话保持在已预热(缓存)的提供商上。有一个注意事项:如果你自己设置了 provider.order,你的排序会覆盖粘性路由。如果你需要特定的提供商顺序,请使用提供商路由控制。
为智能体循环结合使用缓存和粘性路由
如果你的智能体在每一轮都发送相同的内容,请参考以下检查清单:
- 将稳定内容放在前面:系统提示词、工具定义、模式、策略以及长期存在的上下文。
- 将变化的内容放在后面:用户消息、工具结果、时间戳以及每次运行特有的状态。
- 为需要显式 cache_control 的提供商启用提示词缓存。
- 为对话或工作流运行设置一个稳定的 session_id。
- 检查 cached_tokens 和 cache_discount 以确认缓存读取正在发生。
粗略来说,可以想象一个智能体在 6 轮交互中重复使用相同的 10,000 个 token。
| 场景 | 第 1 轮 | 第 2-6 轮 | 总成本(对比 1 轮无缓存) |
|---|---|---|---|
| 无缓存 | 完整输入 | 每轮完整输入 | 6.0 倍 |
| Anthropic 5 分钟缓存 + 粘性路由 | 1.25 倍写入 | 0.1 倍读取 | 1.75 倍 |
| 免费写入提供商 + 0.25 倍读取 | 1.0 倍输入/写入 | 0.25 倍读取 | 2.25 倍 |
| 免费写入提供商 + 0.5 倍读取 | 1.0 倍输入/写入 | 0.5 倍读取 | 3.5 倍 |
此示例仅涵盖重复内容。它忽略了较小的变化消息和模型的输出 token。节省的成本会随着轮次增加而增长。
何时使用何种方式:
- 对于多轮对话,当重复使用的内容随对话增长时,使用自动缓存。
- 当你确切知道哪些大块内容应被缓存时,使用显式缓存断点:检索到的文档、长参考文件、角色卡、CSV 数据或策略文本。
- 对于智能体会话、支持工单、聊天线程、工作流运行,以及任何开场消息可能在轮次间变化的对话,使用 session_id。
- 对于较长的 Anthropic 会话,当默认的 5 分钟缓存可能在轮次间过期时,使用 1 小时缓存。对于简短、密集的来回对话,使用默认缓存。
当你的智能体反复发送相同的高成本内容时,缓存读取和粘性路由可以防止它成为循环中最昂贵的部分。
常见问题解答
OpenRouter 是否支持提示词缓存?
是的。OpenRouter 在支持的提供商和模型上支持提示词缓存。大多数提供商自动启用它,而 Anthropic 和阿里巴巴通义千问使用 cache_control 进行显式缓存。缓存读取的成本是正常输入定价的 0.1 倍到 0.5 倍,具体取决于提供商,因此重复使用的前缀在首次请求后会便宜很多。
在 OpenRouter 上,缓存的 token 费用是多少?
缓存读取成本为正常输入定价的 0.1 倍至 0.5 倍,具体取决于提供商。Anthropic、DeepSeek 和阿里通义千问(Qwen)可提供 0.1 倍的读取价格。OpenAI 的读取价格为 0.25 倍至 0.50 倍。Gemini、Grok 和月之暗面(Moonshot)的读取价格为 0.25 倍。Groq 的读取价格为 0.5 倍。
为什么通过 OpenRouter 使用提示词缓存没有生效?
常见原因包括:提示词长度低于提供商的 token 最低要求、缓存已过期、提示词前缀不稳定,或者多轮对话间提供商发生漂移。对于智能体工作流,请先设置一个稳定的 session_id,然后检查 usage 响应中的 cached_tokens 字段,任何大于零的值都确认发生了缓存命中。
如何在智能体的多轮对话中保持缓存处于活跃状态?
为对话、工单或工作流运行传入一个稳定的 session_id。OpenRouter 会将其用作粘性路由键,因此后续请求会路由回同一个持有活跃缓存的提供商端点。设置了 session_id 后,粘性会在首次成功请求后激活,此时尚未观察到任何缓存命中。
如何检查缓存是否节省了费用?
检查 usage.prompt_tokens_details.cached_tokens 以查看缓存读取情况,检查 cache_write_tokens 以查看缓存写入情况;cached_tokens 值大于零即确认发生了命中。您还可以查看响应中的 cache_discount 字段,了解每次生成的成本影响,或者打开 Activity 页面或 /api/v1/generation API 的详情视图。
缓存功能在自动路由(Auto Router)下是否有效?
是的。设置了 session_id 后,Auto Router 和 Pareto Router 等路由模型会将已解析的模型和提供商固定在该对话中,因此后续轮次会持续命中同一个活跃缓存。