去年夏天,我一个月里开了五家 LLM 服务商的账号。OpenAI、Anthropic、OpenRouter、Fireworks、Together。到十月份,我已经分不清哪张信用卡在给谁家扣钱了。到十二月,其中一家悄悄改了价格,我三个礼拜后收到账单才发现。
说白了,2026 年在 LLM 上做事的现实就是:服务商动物园是个长期现象。每个礼拜都有新模型出来,价格随时会动,免费额度说重排就重排。三月还是最强模型的东西,五月就变成脚注了。如果你的 agent 框架在装的时候就替你把服务商定死了,那你等于签了一份每隔几个月重搭一次的合同。
Hermes Agent 从第一天起就往相反方向押注:服务商是一个 config 值,而不是架构替你做的选择。三层特性叠在一起,才真正让这件事跑得通。
中央路由器(v0.2.0)
底层是一个唯一的调用入口。v0.2.0 上线时,项目引入了一个集中式服务商路由器——一个 call_llm() / async_call_llm() 函数,agent 里每一处调用 LLM 的地方都从这里走。视觉、总结、压缩、轨迹存档、主聊天循环,全部走同一条代码路径。
听起来像个重构层面的小细节,直到你在一个没做过这件事的 agent 里试着换服务商,你才会明白差别。大多数框架里,真正调用 LLM 的地方散在十一个位置,每处读凭据的方式都略有不同。你改了一个,忘了另一个,出问题的方式还隐蔽到不容易被察觉。Hermes 的做法是让所有调用只有一个地方,这类问题就从根上消失了。
回退链(v0.6.0)
两周后,v0.6.0 叠上第二层:有序的回退服务商链。你在 config.yaml 里按顺序列出服务商,主用的那家一遇到错误——429 限流、短暂的 500、连不通的端点——Hermes 会自动切到链上的下一家。
重点是:它是有序的,不是轮询。你自己决定首选和备胎。常见的配法是把 OpenRouter 当作便宜的默认档,Anthropic 直连当作稳的备份,Nous Portal 的免费额度当作最后的保命档。链顶的那家今天不舒服,你这边是感觉不到的。v0.6.0 顺手修了一个隐蔽的 bug:之前用 hermes model 切服务商时会把 api_mode 写死成 chat_completions,现在改成在切换时清掉旧值,所以 Anthropic 兼容端点在切完之后不会再莫名其妙地返回 404 了。
凭据池(v0.7.0)
v0.7.0 那一版的主题是韧性,它又叠上了第三层:同一家服务商内部的凭据池。关键认知是:"我用的主服务商" 和 "我在那家服务商下具体用的那把 API key" 是两件不同的事。你可能手里有三把 Anthropic 的 key——个人的、团队的,外加另一个账号上备的一把——你希望 Hermes 永远用当下最闲的那把。
你通过配置向导或一个 credential_pool 块来声明它们,Hermes 默认按 least_used 策略挑 key。如果某把 key 返回 401,池会自动轮到下一把,并把那把死的挂上一段冷却时间。整套实现是线程安全的,意思是你可以同时跑 CLI、一个 Telegram 网关、一个 cron 任务,它们共用同一个池互不打架。v0.7.0 还确保了池的状态能扛住回退切换——主用那家遇上 429,不会把池里 "哪把 key 已经累了" 的记忆一起抹掉。
为什么要叠成三层
三层里每一层单独拿出来都只解决一个窄问题。它们合起来之所以让人觉得有力,是因为三层之间完全不重叠:
- •路由器 让你在一个地方改 用哪家服务商。
- •回退链 让你不用重启就能处理 服务商层面的失败。
- •凭据池 让你在同一家服务商内部处理 key 层面的失败和负载。
而在命令行里,hermes model 让你把以上任何一层都重配一遍,不用手改配置文件。最终效果是:有新模型出来时——不管是谁发的、叫什么、怎么定价——你要迁移的成本是 "改一行配置",而不是 "把我的助手重写一遍"。对一个要陪你跨过很多代模型的项目来说,这大概是唯一一个真正重要的架构决策。