跳到正文
北京时间
原文
OpenRouter:Announcements(RSS)· OpenRouter·· 2026-07-21精选AI 评分69

OpenRouter 推出 Prompt Caching + Sticky Routing,降低多轮 Agent 调用成本

The Cheapest Token Is a Cached One: Prompt Caching + Sticky Routing

AI 导读

OpenRouter 通过 Prompt Caching 与 Sticky Routing 降低多轮 Agent 的 token 成本。缓存读取价格仅为正常输入的 0.1x-0.5x,其中 Claude Sonnet 4.6 缓存读取为 $0.30/M(正常 $3.00/M)。

推荐理由

Prompt caching 不是新概念,但 OpenRouter 把成本算得明明白白,sticky routing 配合 session_id 解决了缓存漂移的痛点,做 agent 的人该抄作业。

正文 · AI 翻译

The Cheapest Token Is a Cached One: Prompt Caching + Sticky Routing

你的智能体每一轮都会发送相同的系统提示词、工具定义、schema 和策略指令。在一个 6 轮的会话中,你可能会为同一个开场内容块被计费 6 次,尽管唯一变化的东西只是用户最新的消息或智能体最新的工具结果。

提示词缓存解决了这个问题。提供商从缓存中读取你提示词中重复的部分,而不是每次都按全价向你收费。粘性路由通过将会话发回持有热缓存的同一提供商,使这一机制在多个轮次间持续生效。

这篇文章讲的是钱的那一面:缓存 token 的成本是多少,为什么缓存读取和缓存写入的定价不同,session_id 如何让智能体的会话从第一轮起就保持热缓存,以及如何检查缓存是否真的在生效。

太长不看

  • 缓存读取的成本是全新输入 token 的 0.1x 到 0.5x,具体取决于提供商。在 Claude Sonnet 4.6 上,缓存读取为 $0.30/M,而输入为 $3.00/M,正好是 0.1x。
  • 第一个请求需要支付缓存写入费用。Anthropic 的写入成本是输入的 1.25x(5 分钟 TTL)或 2.0x(1 小时 TTL),因此一次未被复用的写入,其成本比完全不缓存还要高。
  • 热缓存只有在你的下一个请求落到同一个提供商端点时才有用。在 70+ 个提供商之间,第二轮可能会命中一个冷端点,于是你就得付全价。
  • 我们的粘性路由会将后续请求固定到持有热缓存的提供商,而 session_id 会从第一次成功请求起就强制执行这一点,此时尚未发生任何缓存命中。
  • 缓存未命中来自 4 种原因:提示词太短、缓存已过期、开头块不断变化,或请求被转移到了不同的提供商。请检查用量响应中的 cached_tokens 以确认命中。

提示词缓存能将你的 token 成本降低多少?

缓存读取的费用为正常输入定价的 0.1x 到 0.5x,具体取决于提供商。正是这一区间使得缓存能让智能体循环变得便宜得多。

重复的部分通常就是昂贵的部分:一段很长的系统提示词、工具定义、JSON schema、护栏、检索到的文档,或用于保持模型一致性的示例。没有缓存时,每一轮都要为所有这些内容再次支付全价。有了缓存后,第一次请求会将其写入缓存,后续请求则以更便宜的价格读回。

以下是提供商层面的视图:

提供商缓存读取缓存写入如何启用
Anthropic Claude(5 分钟 TTL)0.1x 输入1.25x 输入自动或显式
Anthropic Claude(1 小时 TTL)0.1x 输入2.0x 输入显式(ttl: "1h")
OpenAI(GPT-5.6 之前)0.25x-0.50x 输入免费自动
OpenAI(GPT-5.6 及之后)0.25x-0.50x 输入1.25x 输入自动或显式
Google Gemini(隐式)0.25x 输入免费自动
Grok(xAI)0.25x 输入免费自动
Moonshot AI0.25x 输入免费自动
Groq0.5x 输入免费自动(Kimi K2 模型)
DeepSeek0.1x 输入1.0x 输入自动
Alibaba Qwen0.1x 输入1.25x 输入显式(cache_control)
Z.AI约 0.2 倍输入免费自动

提示词缓存文档中有完整的明细。具体金额仍取决于模型和提供商路由;这个倍数告诉你的是,对于该提供商,缓存输入与普通输入相比如何。

对于智能体开发者来说,模式很简单:第一轮可能要付出建立缓存的成本,但只要复用相同的开头内容块,之后每一轮都会便宜得多。

成本花在哪里:缓存写入还是缓存读取?

提示词缓存有两种成本:写入和读取。

写入发生在提供商存储提示词中可复用部分的时候。读取发生在后续请求复用该已存储内容的时候。一旦同一内容被读取足够多次以覆盖写入成本,你就开始划算了。

在某些提供商那里,写入的成本高于普通输入。Anthropic 的缓存写入在默认 5 分钟 TTL 下成本为输入的 1.25 倍,在 1 小时 TTL 下为输入的 2.0 倍。一次从未被复用的 Anthropic 缓存写入,其成本高于在不使用缓存的情况下发送同样的提示词。

对于一次性请求,缓存可能没什么帮助。但对于多轮智能体,重复才是常态:智能体在整个会话过程中会携带相同的指令、工具、schema 和策略上下文。因此,写入缓存的成本在几轮之后就能收回。

对于下一轮很快到来的短时突发场景,使用 5 分钟的缓存生存时间(TTL)。当会话可能暂停足够久、以至于默认缓存会过期,但内容仍然值得保留时,则使用 1 小时的 TTL。

为什么热缓存并不总能在下一次请求时帮上忙?

热缓存只有在下一个请求落到持有该缓存的提供商端点上时才能帮上忙。

当请求可以路由到多个提供商时,第一轮可能在一个提供商上写入缓存,而第二轮却落到了别处。第二个提供商没有热缓存可供读取。请求仍然能正常工作,但你要支付全价,而且 cached_tokens 会保持低位或为零。

这就是我们把粘性路由与提示词缓存搭配使用的原因。在一次已缓存的请求之后,对于同一模型的后续请求,当该提供商的缓存读取定价比普通输入更便宜时,我们会将其路由回同一个提供商端点。如果该粘性提供商变得不可用,OpenRouter 会回退到下一个可用的提供商,而不是让请求失败。

默认情况下,OpenRouter 通过对其第一条 system 或 developer 消息以及第一条非 system 消息进行哈希来识别一段对话。当这些开头的消息保持不变时,这种方式就能奏效。

智能体常常会打破这一点。有些会在总结状态时重写自己的首条消息、重新排列工具上下文,或添加新的运行元数据。当开头消息发生变化时,哈希值就会改变,对话就可能落到不同的提供商上。解决办法是显式设置 session_id。

Diagram of an agent session where session_id keeps turns 1 through N on the same provider for cache writes and cheap cache reads, with automatic failover to a new provider if the sticky one fails

用 session_id 从第一轮起强制使用热缓存

对于智能体循环,设置 session_id。当你传入它时,OpenRouter 会直接将其用作粘性路由键,而不是从开头消息中派生出一个键。

借助 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,否则请求将不再落到持有缓存的那个提供商上。

如果你使用 Auto Router 或 Pareto Router 这类路由模型,会话粘性不仅会固定提供商,还会固定路由所选择的模型。这样可以避免对话在会话中途切换模型,从而保持行为一致,并让缓存保持温热。

我该如何确认提示词缓存确实在起作用?

最快的检查方式是检查用量。

在响应中,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 都来自缓存,而这一轮没有写入新的缓存条目。

你可以在三个地方检查缓存行为:Activity 页面上的详情视图、/api/v1/generation API,以及随 API 响应返回的 usage.prompt_tokens_details 对象。

使用 cache_discount 查看某次生成节省了多少。在写入需要付费的提供商上,写入那一轮可能会看到负的折扣,因为缓存写入的成本高于普通输入。在后续的缓存读取轮次中,折扣应转为正值。

Annotated usage object showing cached_tokens, cache_write_tokens, and cache_discount fields and what each one confirms about caching

为什么你的缓存会未命中,又该如何避免?

当缓存看起来失效时,通常归结为以下 4 种情况之一:提示词太短、缓存已过期、开头内容发生了变化,或者请求被转移到了不同的提供商。

提示词低于提供商的最低要求

每个提供商都有最低提示词长度要求,低于该长度就不会有任何内容被缓存。在 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 个。

如果你的可复用内容低于该最低要求,缓存就不会启动。不要为了强行触发缓存而用填充文本把请求撑大。在你已经有大量可复用内容的地方使用缓存:工具、schema、检索到的文档、示例或策略文本。

缓存在轮次之间过期了

缓存的存活时间不长。Anthropic 的默认值是 5 分钟,对于较长的会话可选择 1 小时。Gemini 的隐式缓存持续约 3-5 分钟,且在你读取它时不会重置。一旦缓存过期,下一次请求就必须写入一个新的缓存。

如果你的用户在轮次之间经常暂停,请在支持的情况下使用更长的 TTL,或者将智能体设计为在空闲期之后接受新的写入。

提示词的开头不断变化

当提示词的开头保持不变时,自动缓存和隐式缓存的效果最好。把稳定的内容放在前面:系统指令、工具、schema 和固定的参考资料。把变化的内容放在后面:用户问题、时间戳、临时状态、工具输出和短期元数据。

这里的细节很重要。第一条系统消息里带一个时间戳,会让提示词在每一轮看起来都是新的。如果它不需要成为缓存内容的一部分,就把它移到后面的用户消息或工具消息里。

请求漂移到了另一个提供商

缓存存在于它被写入的地方。如果后续请求路由到了另一个提供商端点,那个端点无法读取先前的缓存。

对于智能体工作流,设置 session_id,让粘性路由把会话保持在已预热的提供商上。有一个需要注意的地方:如果你自己设置了 provider.order,你的顺序会优先于粘性路由。如果你需要指定特定的提供商顺序,请使用 提供商路由控制。

将缓存和粘性路由结合用于智能体循环

如果你的智能体每一轮都发送相同的内容,以下是检查清单:

  1. 把稳定的内容放在前面:系统提示词、工具定义、schema、策略和长期存活的上下文。
  2. 把变化的内容放在后面:用户消息、工具结果、时间戳和特定于本次运行的状态。
  3. 为需要显式 cache_control 的提供商启用提示词缓存。
  4. 为对话或工作流运行设置一个稳定的 session_id。
  5. 检查 cached_tokens 和 cache_discount,以确认读取正在发生。

粗略地想象一下:一个智能体在 6 轮对话中重复相同的 10,000 个 token。

场景第 1 轮第 2-6 轮总成本(对比 1 轮未缓存)
无缓存完整输入每轮完整输入6.0x
Anthropic 5 分钟缓存 + 粘性路由1.25x 写入0.1x 读取1.75x
免费写入提供商 + 0.25x 读取1.0x 输入/写入0.25x 读取2.25x
免费写入提供商 + 0.5x 读取1.0x 输入/写入0.5x 读取3.5x

此示例仅涵盖重复的内容。它忽略了较小的变化消息以及模型的输出 token。节省量随轮次增加而增长。

Worked example table comparing 10 turns without caching at full price against caching plus sticky routing, ending at roughly 75-90% fewer input tokens billed

何时使用哪种方式:

  • 对于多轮对话,如果复用内容随对话增长,请使用自动缓存。
  • 当你确切知道哪些大块内容应被缓存时,请使用显式缓存断点:检索到的文档、长参考文件、角色卡、CSV 数据或策略文本。
  • 对于智能体会话、支持工单、聊天线程、工作流运行,以及任何开场消息可能在不同轮次之间发生变化的对话,请使用 session_id。
  • 对于较长的 Anthropic 会话,如果默认的 5 分钟缓存在轮次之间可能过期,请使用 1 小时缓存。对于简短、密集的来回对话,请使用默认缓存。

当你的智能体一遍又一遍地发送同样昂贵的内容时,缓存读取和粘性路由可以防止它成为整个循环中最昂贵的部分。

常见问题

OpenRouter 支持提示词缓存吗?

支持。OpenRouter 在受支持的提供商和模型上支持提示词缓存。大多数提供商会自动启用它,而 Anthropic 和阿里通义千问(Qwen)使用 cache_control 进行显式缓存。缓存读取的费用为正常输入定价的 0.1x 到 0.5x,具体取决于提供商,因此被复用的前缀在首次请求之后会便宜得多。

在 OpenRouter 上,缓存 token 的费用是多少?

缓存读取的费用为正常输入定价的 0.1x 到 0.5x,具体取决于提供商。Anthropic、DeepSeek 和阿里通义千问(Qwen)可以按 0.1x 读取。OpenAI 按 0.25x 到 0.50x 读取。Gemini、Grok 和 Moonshot 按 0.25x 读取。Groq 按 0.5x 读取。

为什么通过 OpenRouter 使用提示词缓存不起作用?

常见原因包括:提示词低于提供商的 token 最低要求、缓存已过期、提示词前缀不稳定,或轮次之间发生了提供商漂移。对于智能体工作流,首先设置一个稳定的 session_id,然后检查使用量响应中的 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 等路由模型会为对话固定解析后的模型和提供商,因此后续轮次会持续命中同一热缓存。

来源:OpenRouter:Announcements(RSS) · openrouter.ai