🤖HermesBlog
Hermes 功能详解 · 第28篇2026/8/9· Easy Understand Hermes Agent

第28篇:提供商路由——智能分发模型请求

Hermes 功能详解第28篇:Provider Routing。按规则自动选择模型提供商。

提供商路由:智能调度员

第28篇:提供商路由——智能分发模型请求

上一篇我们聊了模型路由的“大脑”,今天这篇咱们来聊聊提供商路由——也就是 Hermes 怎么帮你把不同的“活儿”分发给不同的模型去干,让每个任务都找到最合适的“打工人”。

两类模型槽位:主力军和辅助队

Hermes 把模型分成两大类:

  • 主模型(Main model):负责“思考”的。你发的每条消息、工具调用循环、流式响应,全走它。
  • 辅助模型(Auxiliary models):干杂活的。比如上下文压缩、图像分析、网页摘要、审批评分、MCP 工具路由、会话标题生成、技能搜索……一共 11 个槽位,每个都能单独指定模型。

默认情况下,辅助任务都是 auto——也就是跟着主模型走。但如果你想省钱或提速,完全可以给某个辅助任务单独指定一个便宜的小模型。

仪表盘里怎么配?

打开 Dashboard,点侧边栏的 Models,你会看到两个区域:

  1. Model Settings:顶部面板,给各个槽位分配模型。
  2. Usage analytics:使用统计卡片,显示每个模型跑了多少 token、花了多少钱。

主模型那一行点 Change 就能打开选择器。左边是已认证的提供商,右边是精选模型列表——注意,这不是原始 /models 接口的全量 dump(OpenRouter 上那可是 400+ 模型,包括 TTS、画图、reranker 啥的),而是 Hermes 针对该提供商推荐的智能体模型。

选好模型点 Switch,配置就写进 ~/.hermes/config.yaml 了。注意:这只对新会话生效,已经打开的聊天标签页不会变。想热切换当前对话?用 /model 斜杠命令。

订阅速度档位与扩展上下文

速度(Speed)和推理强度(reasoning effort)是两码事。在支持的订阅模型上,Fast 会请求 Priority 通道,Ultrafast 则请求 Ultrafast 档位——两者互斥,选一个就会清掉另一个。你选的档位会按模型记住,并带进新会话。

配置默认值的位置在 Settings → Model → Main model → Speed,对应配置项 agent.service_tier,可选 normal、fast、ultrafast。注意 Ultrafast 只对支持它的模型显示,而且在订阅下,只有你账户的 Codex 目录为该模型列出它时才会出现。想清掉旧的遗留设置,点 Use standard speed 就行。另外提醒一句:请求被接受,不代表 OpenAI 真的按你要求的档位服务了。

Hermes 会把 GPT-6.1 Sol-900k 这个选项从一个符合条件的、被发现的 GPT-6.1 Sol 模型上本地生成。-900k 后缀只是本地的上下文选择,真正发给 OpenAI 的模型 ID 里会去掉它。Hermes 会把预算限制在账户目录允许的最大值内,而 Codex 自己还会预留一部分,所以它报告的可用上下文可能更小。如果新模型没出现,点 Refresh models 刷新一下。还有一点:如果模型发现失败了,Hermes 会改用短时有效的兼容性提示,而不会把它当成成功的账户目录缓存下来。

顺带说下 GPT-6.1 Sol-900k 这个选项:它是 Hermes 从一个符合条件的、被发现的 GPT-6.1 Sol 模型上本地生成的。-900k 后缀只是本地的上下文选择,真正发给 OpenAI 的模型 ID 里会去掉它。Hermes 会把预算限制在账户目录允许的最大值内,而 Codex 自己还会预留一部分,所以它报告的可用上下文可能更小。如果新模型没出现,点 Refresh models 刷新一下。还有一点:如果模型发现失败了,Hermes 会改用短时有效的兼容性提示,而不会把它当成成功的账户目录缓存下来。

提供商路由:只在 OpenRouter 下生效

提供商路由(provider routing) 是 OpenRouter 专属的能力:OpenRouter 背后对接了很多底层提供商(Anthropic、Google、AWS Bedrock、Together AI 等),提供商路由让你可以精细控制这些请求交给谁、按什么优先级排。你可以用它来优化成本、速度、质量,或者强制指定某些提供商。

在 ~/.hermes/config.yaml 里加一段 provider_routing 就能配置:

provider_routing:
  sort: "price"           # How to rank providers
  only: []                # Whitelist: only use these providers
  ignore: []              # Blacklist: never use these providers
  order: []               # Explicit provider priority order
  require_parameters: false  # Only use providers that support all parameters
  data_collection: null   # Control data collection ("allow" or "deny")

几个常用选项:

  • sort:排序方式,可选 "price"(最便宜优先)、"throughput"(每秒 token 数最快优先)、"latency"(首 token 延迟最低优先)。
  • only:白名单,只允许列表里的提供商。
  • ignore:黑名单,永不使用列表里的提供商。
  • order:显式优先级顺序,靠前的优先,没列出的作为兜底。
  • require_parameters:设为 true 时,只路由到支持你请求里全部参数(如 temperature、top_p、tools 等)的提供商,避免参数被悄悄丢掉。
  • data_collection:控制提供商能否拿你的提示词去训练,可选 "allow" 或 "deny"。

注意:提供商路由只在用 OpenRouter 时生效。对 Nous Portal 和直连提供商(比如直接连 Anthropic API)都没有效果——Nous Portal 是按模型在中心侧统一决定路由的,不接受调用方传入的提供商偏好,Hermes 根本不会把 provider 对象发给 Portal,所以 provider_routing 在那里会被直接忽略。

按模型单独覆盖(models)

如果你想让不同模型走不同的提供商策略,可以用 models 子键做按模型覆盖。models 下的键是模型 id,每一项都接受和上面一样的 sort / only / ignore / order / require_parameters / data_collection,只对该模型生效;没写的项就沿用顶层的默认值。

provider_routing:
  sort: "price"                      # applies to every model
  models:
    "openai/gpt-6-astra":
      only: ["openai"]               # never let a reseller serve this one
    "anthropic/claude-fable-5.1":
      only: ["anthropic"]
    "moonshotai/kimi-k2.6":
      order: ["moonshotai", "together"]
      sort: "throughput"

匹配是拼写宽容的(和 agent.reasoning_overrides 一样):claude-fable-5.1 / claude-fable-5-1 都行,带不带 openrouter/ 前缀也都行。覆盖跟随的是智能体当前所用的模型,所以 /model 切换、fallback 激活、cron 任务、委派给别的模型的子智能体,各自都会用自己那一份 pin。这些键建议直接编辑 config.yaml:模型 id 里带点号,hermes config set 会把点号当成路径分隔符来解析。

中途切换的坑:缓存重置警告

在会话中途切换模型(比如 Herm TUI 里选模型、CLI 里切、Telegram/Discord 里发 /model),Hermes 会预估你的下一条消息是否需要对新模型做“预检上下文压缩”。如果会话已经接近或超过新模型的压缩阈值,切换时会附带警告。

更坑的是:中途切换会重置提示缓存。因为缓存是按模型 key 的,换模型意味着下一条消息要按全价重新读一遍整个对话,而不是享受 75-90% 的缓存折扣。另外,显式 /model 切换还会改写系统提示里的 Model:(以及 Provider:)行,让智能体知道自己跑在什么模型上——这是一次性、有意的改动:切换后的第一个请求会错过一次缓存前缀,系统提示之后的内容保持逐字节一致。自动 fallback 只在内存里改写同一行,存储的会话仍保留主模型的标签,所以主模型恢复后重放的提示是逐字节一致的。长会话里,这一下重读可能比两个模型之间的单价差还贵。所以——要切换就趁早,最好在对话刚开始或刚开新会话时切。

正因为有这笔一次性重读成本,当当前会话已经攒了很大的上下文时(默认 100,000 token,按最近一次提供商计费的 prompt 大小算),Hermes 会在应用中途切换前要求你明确确认。这个确认走的是和昂贵模型、数据训练警告同一套选择守卫提示,出现在 CLI 和 TUI 的 /model 命令与选择器里,以及聊天中带活跃智能体时手打的网关 /model。想调整或关掉,改 config.yaml:

model:
  # Ask before mid-session switches when the session exceeds this many
  # context tokens (the next reply re-reads them uncached). 0 disables.
  switch_context_confirm_tokens: 100000

重新选你当前已经在用的模型不会弹确认(缓存还是热的),没有测到上下文的会话(全新会话、非实时界面)也豁免。

无人值守任务的数据训练等级

有些模型(比如 muse-spark-1.2-contributor)因为厂商可能拿你的数据训练,所以价格打折。交互式选择时会有确认弹窗,但无人值守任务(Kanban workers、cron agents)没法弹窗问,所以默认拒绝。

如果你接受,可以持久化确认:

hermes config set security.allow_data_training_tiers_noninteractive true

Hermes 每次无人值守启动时仍会打印完整的数据政策警告和确认键,保证日志里有审计痕迹。撤销就用:

hermes config unset security.allow_data_training_tiers_noninteractive

快速上手:Nous Portal

如果你是全新安装,最快的路径是:

hermes setup --portal

一条命令登录 Nous Portal,300+ 模型一个订阅全搞定。查看配置情况用 hermes portal info。Portal 订阅者还能享受token 计费提供商 10% 折扣。

小提醒:model: 配置的两种形态

全新安装的默认配置里,model 是一个空字符串(表示“还没配置”)。你第一次跑 hermes setup 或 hermes model 时,它会自动升级成包含 provider、default、base_url、api_mode 子键的映射结构。如果你在 config.yaml 里看到空字符串,跑一下 hermes model 或在 Dashboard 里点 Change,Hermes 就会帮你写回字典形式。

给提供商加请求头的小技巧

如果你用的是自建网关或代理,providers.<name> 里还能加几个小开关:

  • extra_headers:给发往该提供商的每个 LLM 请求附加额外 HTTP 头,常用于 Cloudflare Access 服务令牌、代理鉴权或自定义 bearer 方案。它作用于 OpenAI 兼容路由和 anthropic_messages 路由(主客户端、/model 切换、重建和辅助客户端都算),但 bedrock_converse 不用它。头里经常带凭证,Hermes 从不记录它们。典型场景是网关躲在 WAF 后面,拒绝了 SDK 默认的 User-Agent(返回 403 “Your request was blocked” 或浏览器挑战页)——这时 Hermes 会把这种 403 报成防火墙/CDN 拦截,而不是 API key 被拒。
  • session_affinity_header:填一个头的名字,Hermes 会在发往该提供商的每个请求上带上会话 id(主回合的 chat_completions、anthropic_messages、codex_responses,以及压缩、标题等辅助调用)。不设就不发——Hermes 绝不会往没要求的端点塞会话标识。会话感知的代理(比如 LiteLLM 的 x-litellm-session-id、自建 Claude/OpenAI 网关)背后是有状态后端,没有这个头就没法把一轮智能体循环关联起来,会把几乎每个请求都当成新对话,每回合都把整段历史重发一遍。这个值是不透明的,在一次对话的各回合间保持稳定(包括压缩后),不同对话各不相同。
providers:
  my-proxy:
    api: http://127.0.0.1:4000/v1
    api_key: sk-...
    session_affinity_header: x-litellm-session-id

答案跑进 reasoning 字段怎么办?

有些 OpenAI 兼容的服务器会把整段回答塞进 reasoning 字段,而 content 是空的。默认情况下 Hermes 不会把 reasoning 当成回复显示——因为大多数提供商把私有的思维链放在那儿,它宁可重试一次。但如果你那个服务器的解析器确实就是把最终答案写进 reasoning,可以给这个模型单独开 answer_in_reasoning:

providers:
  local-vllm:
    api: http://127.0.0.1:8000/v1
    models:
      my-reasoner:
        answer_in_reasoning: true

想给某个提供商下的所有模型都开,就把这个标志放进提供商级的 capabilities: 块里(capabilities: {answer_in_reasoning: true})。Hermes 会在每一回合重新读取当前路由上的这个开关,CLI、TUI、网关都一样,所以哪怕用 /model 切到同一提供商下的另一个模型,它也照样生效。但 fallback 或别的提供商不会继承它,OpenRouter 的路由更是永远不信任——就算你设了标志也没用。

📖 官方文档

本文根据 Hermes Agent 官方文档编写,原文见:官方文档 › user-guide/configuring-models