跳到正文
北京时间
原文
OpenRouter:Announcements(RSS)· Kenny Rogers·· 2026-06-15精选AI 评分62

OpenRouter Presets:当模型下线时保持 AI 智能体运行

Keep Your Agent Running When Models Disappear

AI 导读

Anthropic 在 Claude Fable 5 发布仅数天后便对其进行了限制。如果代码硬编码模型 slug,该限制也会导致服务中断。OpenRouter 的 Presets 功能将模型选择移至服务器端,使用户无需重新部署即可切换模型、设置回退策略并强制执行数据策略。

推荐理由

给 Agent 开发者的实用提醒,硬编码模型名会在供应商限制时塌方,用 Presets 换模型、设降级方案比现改代码省心。

正文 · AI 翻译

Keep Your Agent Running When Models Disappear

服务商下线和限制模型是家常便饭。过去几年里,已有 70 多个模型被服务商撤下或弃用。Anthropic 的 Fable 最近被撤下,或许是我们见过的此类事件中最受关注、影响最大的一个例子,但这种现象并不新鲜,也不会消失。

OpenRouter 已经为你处理了其中一层问题。当一个模型运行在多个服务商上,而其中一个出现故障或触发速率限制时,这个市场平台会自动改道到另一个服务商,无需任何配置。我们在另一篇文章中介绍了这种故障转移是如何工作的。

这能让单个模型在服务商出问题时依然可达,但一旦模型本身消失,它就无能为力了。为此,你需要的是模型故障转移——当你的首选模型消失时,请求会转移到另一个模型。预设(Presets)就是用来设置这一机制的方式。

把模型 slug 硬编码,会把你的选择钉死在每一个使用它的服务里。当那个模型消失时,唯一的解决办法就是修改代码并重新部署每个服务,而在你这么做之前,请求会一直失败。

预设把这一选择从你的代码中抽离出来。它是一个具名的服务端配置(模型、备用模型、服务商规则、参数以及系统提示词),你通过 slug 来引用它。模型存在于预设中,而不是代码中,所以你只需在一个地方修改它,所有调用该预设的服务都会自动采用,无需重新部署。

下面是一个简单的预设定义。复制它并调整其中的模型:

{
  "models": [
    "anthropic/claude-fable-5",
    "anthropic/claude-opus-4.8",
    "openai/gpt-5.5"
  ],
  "provider": { "allow_fallbacks": true }
}

models 数组就是你的回退链,按优先级排序。如果第一个模型不可用,OpenRouter 会尝试下一个。

硬编码 slug 与预设引用

问题硬编码模型字符串预设引用
某个提供商限制了该模型在你编辑并重新部署之前,所有服务都会中断只需编辑一次预设;调用方继续运行
谁来发布修复每个代码库各自的负责人预设的负责人
变更的影响范围每个仓库、每个服务各改一次改一次,处处生效
数据策略(ZDR、保留)在每个请求中重新声明在预设上设置一次
回滚还原某个提交并重新部署重新指定一个先前的版本

把这个交给你的智能体

想让你的编程智能体把它接好?复制下面的提示词:

I want to stop hard-coding model slugs so one provider change can't take down my app. Set up an OpenRouter preset and route my calls through it.

1. Create a preset named "customer-support" with a fallback chain: a primary model plus 2 backups in priority order, using the models array.
2. Set provider rules on the preset: allow_fallbacks true, and zdr true if my data policy requires Zero Data Retention.
3. Capture it by POSTing a known-good chat/completions body to https://openrouter.ai/api/v1/presets/customer-support/chat/completions with my OpenRouter API key.
4. Replace the model field in my inference calls with "@preset/customer-support".
5. Keep my OpenRouter API key in an environment variable. Never hard-code it.

Use these references for current shapes:
- Presets: https://openrouter.ai/docs/guides/features/presets
- Provider routing and fallbacks: https://openrouter.ai/docs/guides/routing/provider-selection

把一个可用的请求捕获为预设

你可以在控制台中构建一个预设,或者从你已经信任的请求体中捕获一个。

向预设捕获端点发送一个已知可用的 chat/completions 请求体。OpenRouter 会持久化与预设配置重叠的字段(models、provider、temperature 等等),并忽略像 messages 这样的临时字段:

curl https://openrouter.ai/api/v1/presets/customer-support/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "models": [
      "anthropic/claude-fable-5",
      "anthropic/claude-opus-4.8",
      "openai/gpt-5.5"
    ],
    "provider": { "allow_fallbacks": true },
    "messages": [
      { "role": "system", "content": "You are a concise support assistant." },
      { "role": "user", "content": "Summarize this ticket in one sentence." }
    ]
  }'

如果该 slug 的预设已存在,这会创建一个新版本并将其指定为活跃版本。如果不存在,则会创建该预设。请选择一个尚未被使用的 slug,因为向已存在的 slug 捕获会用一个新的活跃版本覆盖其正在使用的配置。响应会返回该预设及其被指定的版本(此处已裁剪):

{
  "data": {
    "name": "customer-support",
    "slug": "customer-support",
    "status": "active",
    "designated_version": {
      "version": 1,
      "system_prompt": "You are a concise support assistant.",
      "config": {
        "models": [
          "anthropic/claude-fable-5",
          "anthropic/claude-opus-4.8",
          "openai/gpt-5.5"
        ],
        "provider": { "allow_fallbacks": true }
      }
    }
  }
}

在你的代码中引用该预设

现在将你的推理调用指向 @preset/customer-support。模型选择存在于预设中,因此当底层模型发生变化时,这一行保持不变。

先安装一个 SDK:

pip install openrouter        # Python
npm install @openrouter/sdk   # TypeScript
from openrouter import OpenRouter
import os

client = OpenRouter(api_key=os.getenv("OPENROUTER_API_KEY"))

response = client.chat.send(
    model="@preset/customer-support",
    messages=[
        {"role": "user", "content": "Summarize this ticket in one sentence."}
    ],
)
print(response.choices[0].message.content)
import { OpenRouter } from '@openrouter/sdk';

const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });

const response = await client.chat.send({
  chatRequest: {
    model: '@preset/customer-support',
    messages: [
      { role: 'user', content: 'Summarize this ticket in one sentence.' },
    ],
  },
});
console.log(response.choices[0]?.message.content);

默认使用@preset/slug上方所示的表单。当你想要指定一个基础模型并在其上叠加某个预设的配置时,可以改用组合model@preset/slug表单,或者使用一个单独的preset字段与model搭配使用,如果你更愿意将它们保留为不同的请求字段。关于预设的文档涵盖了这 3 种方式。

添加回退模型,让请求持续流转

models 数组是能在弃用后依然存活的部分。按优先级顺序传入模型,当某个模型不可用时,OpenRouter 会依次遍历该列表。

把你最信任的模型放在最后一项,这样你的最终回退就是一个你愿意上线的底线。对于依赖 Fable 5 的编程工作负载,像 anthropic/claude-fable-5、然后 anthropic/claude-opus-4.8、然后 openai/gpt-5.5 这样的链条可以把强模型留作后备。

这就是那个回退被触发的情形。在 Fable 5 受限的情况下,一个指定上述链条的请求依然成功,而响应中的 model 和 provider 字段会指明实际为其服务的是哪个模型:

{
  "model": "anthropic/claude-4.8-opus-20260528",
  "provider": "Anthropic",
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "Customer cannot log in because password reset emails are not being received, despite checking spam and confirming the correct email address."
      }
    }
  ]
}

OpenRouter 跳过了受限的首选模型,改由数组中的下一个模型提供服务。你的代码无需改动。

`model` 字段报告的是实际处理该请求的具体版本,因此它的值与您发送的 slug 不同。在这里,`anthropic/claude-opus-4.8` 在 Anthropic 上解析为带日期的构建版本 `anthropic/claude-4.8-opus-20260528`。

这里有两层恢复机制。提供商层故障转移是自动的:对于由多个提供商服务的同一个模型,OpenRouter 会在遇到 5xx 或速率限制时重试下一个提供商。模型层回退则是 `models` 数组,当整个主模型不可用时,会切换到另一个模型。关于两者的具体机制,请参阅 可靠性与自动故障转移 和 模型路由。

在预设中设置您的数据策略

提供商规则也随同一个预设一起生效,因此路由策略无需修改代码即可应用于每个调用方。

{
  "models": [
    "anthropic/claude-fable-5",
    "anthropic/claude-opus-4.8",
    "openai/gpt-5.5"
  ],
  "provider": {
    "zdr": true,
    "data_collection": "deny",
    "allow_fallbacks": true
  }
}

`zdr: true` 会将请求保持在遵守零数据保留的端点上。`data_collection: "deny"` 会屏蔽那些用提示词进行训练或存储提示词的提供商。您还可以通过 `only`、`ignore` 和 `order` 来固定或排除特定提供商。完整列表请参阅 提供商路由。

Fable 5 的情况在这里就变得具体了。它的模型页面指出,Anthropic 的政策“不允许零数据保留”。当预设上设置了 `zdr: true` 时,路由会跳过 Fable 5,因为它无法满足该规则,并转而使用您数组中下一个能够满足该规则的模型。一个开关,在服务端强制执行,适用于所有指定该预设的请求。

在你的团队中推行和回滚

在组织账户中,每个成员都可以使用组织预设,因此一次做出的路由决策会被共享,而不是复制到每个仓库中。

每次捕获或编辑都会创建一个新版本并将其标记为活跃版本。版本历史会被保留,因此一次糟糕的更改只需重新指定一次即可回滚。通过 API,始终运行的是最新指定的版本。你可以在仪表盘中重新指定版本并删除预设;API 可以捕获和读取预设,但没有删除端点。

你在请求中传入的参数会覆盖预设的值,进行浅合并。请求字段优先,你未发送的预设字段会被保留。这样一次调用就可以提升temperature,而无需分叉预设。

把它们全部串联起来

上面的数据策略配置已经包含了全部 3 层:模型链、提供商策略,以及(一旦你添加了)系统提示词。用 curl 调用捕获一次,在各处引用@preset/customer-support,下次某个提供商限制某个模型时,你只需编辑一个配置,而不必在每个服务中追踪 slug。

如果你根本不想固定一个主模型,可以将模型链指向一个自更新别名,比如~anthropic/claude-opus-latest,它始终解析为该系列中最新的模型。

从一个预设开始

选择你流量最高的调用,在 openrouter.ai/settings/presets 为它创建一个预设,给它配置一条回退链,然后把模型字符串替换为 @preset/your-slug。这一举动就能把一次被迫迁移变成一次配置修改。

预设与治理工作也很契合:那个能在弃用中存活下来的控制点,正是你执行数据处理规则的地方,详见 AI 智能体的人工监督。

注意: 本文介绍的是工程模式,并非法律建议。关于出口管制、数据驻留或留存义务,请就你的具体用例和司法管辖区咨询法律顾问。

常见问题

当某个模型被弃用或受限时,我的应用会发生什么?

如果你的代码硬编码了模型 slug,对该模型的请求就会开始失败,所有使用它的服务都会中断,直到你修改代码并重新部署。而通过预设来路由,你只需修改一处配置;调用方无需重新部署即可获取这一变更。一个 models 回退数组可以让请求在你决定如何处理期间继续由备用模型成功响应。

预设与在代码中传入 models 回退数组有何不同?

一个 models 数组为单个请求设定回退顺序。预设会将该数组,连同提供商规则、参数和系统提示词,以某个 slug 存储在服务器上。你通过 @preset/slug 来引用它,因此配置集中在一处,跨所有服务通用,并且无需修改代码即可变更。

请求参数会覆盖预设值吗?

会。请求参数优先于预设的值,采用浅合并。请求级字段会覆盖匹配的预设字段,而你没有发送的预设字段会被保留。

我可以用预设强制执行零数据保留吗?

可以。将 provider.zdr 设为 true。OpenRouter 只会路由到遵守零数据保留的端点,跳过无法遵守的模型或提供商,并沿着你的 models 数组回退到下一个符合条件的选项。

如何回滚预设的更改?

每次捕获或编辑都会创建一个新版本并将其指定为活动版本。版本历史会被保留,因此你可以重新指定之前的版本。通过 API,始终使用最新指定的版本。

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