提供者运行时解析
Hermes 拥有一个共享的提供者运行时解析器,用于以下场景:
- CLI
- gateway(网关)
- cron 作业
- ACP
- 辅助模型调用
主要实现文件:
hermes_cli/runtime_provider.py— 凭据解析,_resolve_custom_runtime()hermes_cli/auth.py— 提供者注册表,resolve_provider()hermes_cli/model_switch.py— 共享的/model切换管道(CLI + gateway)agent/auxiliary_client.py— 辅助模型路由providers/— ABC + 注册表入口点(ProviderProfile、register_provider、get_provider_profile、list_providers)plugins/model-providers/<name>/— 每个提供者的插件(内置),声明api_mode、base_url、env_vars、fallback_models,并在首次访问时自行注册到注册表。用户插件位于$HERMES_HOME/plugins/model-providers/<name>/,会覆盖同名的内置插件。
providers/ 中的 get_provider_profile() 返回给定提供者 ID 的 ProviderProfile。runtime_provider.py 在解析时调用此函数,获取规范的 base_url、env_vars 优先级列表、api_mode 和 fallback_models,无需在多个文件中重复这些数据。在 plugins/model-providers/<your-provider>/(或 $HERMES_HOME/plugins/model-providers/<your-provider>/)下添加一个调用 register_provider() 的新插件,就足以让 runtime_provider.py 识别它——无需在解析器中添加分支。
如果你正尝试添加新的顶级推理提供者,请同时阅读添加提供者和模型提供者插件指南以及本页面。
解析优先级
在高层面上,提供者解析使用:
- 显式的 CLI/运行时请求
config.yaml的模型/提供者配置- 环境变量
- 提供者特定的默认值或自动解析
这个顺序很重要,因为 Hermes 将已保存的模型/提供者选择视为正常运行的真相来源。这可以防止过时的 shell 导出变量静默覆盖用户在 hermes model 中最后选择的端点。
提供者
当前提供者家族包括(完整内置集请参见 plugins/model-providers/):
- AI Gateway (Vercel)
- OpenRouter
- Nous Portal
- OpenAI Codex
- Copilot / Copilot ACP
- Anthropic(原生)
- Google / Gemini(
gemini、google-gemini-cli) - Alibaba / DashScope(
alibaba、alibaba-coding-plan) - DeepSeek
- Z.AI
- Kimi / Moonshot(
kimi-coding、kimi-coding-cn) - MiniMax(
minimax、minimax-cn、minimax-oauth) - Kilo Code
- Hugging Face
- OpenCode Zen / OpenCode Go
- AWS Bedrock
- Azure Foundry
- NVIDIA NIM
- xAI (Grok)
- Arcee
- GMI Cloud
- StepFun
- Qwen OAuth
- Xiaomi
- Ollama Cloud
- LM Studio
- Tencent TokenHub
- Custom(自定义)(
provider: custom)——适用于任何兼容 OpenAI 的端点的顶级提供者 - 命名自定义提供者(config.yaml 中的
custom_providers列表)
运行时解析的输出
运行时解析器返回的数据包括:
provider(提供者)api_mode(API 模式)base_url(基础 URL)api_key(API 密钥)source(来源)- 提供者特定的元数据,如过期/刷新信息
为何重要
这个解析器是 Hermes 能够在以下场景之间共享认证/运行时逻辑的主要原因:
hermes chat- gateway 消息处理
- 在新会话中运行的 cron 作业
- ACP 编辑器会话
- 辅助模型任务
AI Gateway
在 ~/.hermes/.env 中设置 AI_GATEWAY_API_KEY,并使用 --provider ai-gateway 运行。Hermes 从网关的 /models 端点获取可用模型,筛选出支持工具调用(tool-use)的语言模型。
OpenRouter、AI Gateway 和自定义 OpenAI 兼容基础 URL
Hermes 包含逻辑,用于在存在多个提供者密钥时(例如 OPENROUTER_API_KEY、AI_GATEWAY_API_KEY 和 OPENAI_API_KEY),避免将错误的 API 密钥泄露到自定义端点。
每个提供者的 API 密钥限定在其自己的 base URL 范围内:
OPENROUTER_API_KEY仅发送到openrouter.ai端点AI_GATEWAY_API_KEY仅发送到ai-gateway.vercel.sh端点OPENAI_API_KEY用于自定义端点并作为回退
Hermes 还会区分:
- 用户选择的真实自定义端点
- 未配置自定义端点时使用的 OpenRouter 回退路径
这种区分对于以下情况尤为重要:
- 本地模型服务器
- 非 OpenRouter/非 AI Gateway 的 OpenAI 兼容 API
- 无需重新运行设置即可切换提供者
- 即使当前 shell 中未导出
OPENAI_BASE_URL,也应继续工作的配置保存的自定义端点
原生 Anthropic 路径
Anthropic 不再仅仅是”通过 OpenRouter”。
当提供者解析选择 anthropic 时,Hermes 使用:
api_mode = anthropic_messages- 原生 Anthropic Messages API
agent/anthropic_adapter.py进行转换
原生 Anthropic 的凭据解析现在优先使用可刷新的 Claude Code 凭据,而非复制的环境令牌(当两者同时存在时)。实际上这意味着:
- 包含可刷新认证的 Claude Code 凭据文件被视为首选来源
- 手动的
ANTHROPIC_TOKEN/CLAUDE_CODE_OAUTH_TOKEN值仍可作为显式覆盖使用 - Hermes 在原生 Messages API 调用之前会预检 Anthropic 凭据刷新
- Hermes 在重建 Anthropic 客户端后,仍会在 401 错误时重试一次,作为回退路径
OpenAI Codex 路径
Codex 使用独立的 Responses API 路径:
api_mode = codex_responses- 专用的凭据解析和认证存储支持
辅助模型路由
辅助任务如:
- 视觉(vision)
- 网页提取摘要(web extraction summarization)
- 上下文压缩摘要(context compression summaries)
- 技能中心操作(skills hub operations)
- MCP 辅助操作
- 内存刷新(memory flushes)
可以使用自己的提供者/模型路由,而非主要的对话模型。
当辅助任务配置的提供者为 main 时,Hermes 会通过与普通聊天相同的共享运行时路径进行解析。实际上这意味着:
- 环境变量驱动的自定义端点仍然有效
- 通过
hermes model/config.yaml保存的自定义端点也有效 - 辅助路由能够区分真实保存的自定义端点和 OpenRouter 回退
回退模型
Hermes 支持配置的回退提供者链——一个 (provider, model) 条目列表,当主要模型遇到错误时按顺序尝试。传统的单对 fallback_model 字典仍然被接受以保持向后兼容(并在首次写入时迁移)。
内部工作原理
-
存储:
AIAgent.__init__存储fallback_model字典,并设置_fallback_activated = False。 -
触发点:
_try_activate_fallback()在run_agent.py的主重试循环中的三个位置被调用:- 在无效 API 响应达到最大重试次数后(None choices、missing content)
- 在不可重试的客户端错误时(HTTP 401、403、404)
- 在瞬时错误达到最大重试次数后(HTTP 429、500、502、503)
-
激活流程(
_try_activate_fallback):- 如果已激活或未配置,立即返回
False - 调用
auxiliary_client.py中的resolve_provider_client()构建具有正确认证的新客户端 - 确定
api_mode:openai-codex 为codex_responses,anthropic 为anthropic_messages,其他均为chat_completions - 原地替换:
self.model、self.provider、self.base_url、self.api_mode、self.client、self._client_kwargs - 对于 anthropic 回退:构建原生 Anthropic 客户端而非 OpenAI 兼容客户端
- 重新评估提示缓存(prompt caching)(对 OpenRouter 上的 Claude 模型启用)
- 设置
_fallback_activated = True——防止再次触发 - 将重试计数重置为 0 并继续循环
- 如果已激活或未配置,立即返回
-
配置流程:
- CLI:
cli.py读取CLI_CONFIG["fallback_model"]→ 传递给AIAgent(fallback_model=...) - Gateway:
gateway/run.py._load_fallback_model()读取config.yaml→ 传递给AIAgent - 验证:
provider和model键都必须非空,否则禁用回退
- CLI:
不支持回退的情况
- 子代理委派(
tools/delegate_tool.py):子代理继承父级的提供者,但不继承回退配置 - 辅助任务:使用自己独立的提供者自动检测链(参见上文的辅助模型路由)
Cron 作业支持回退:run_job() 从 config.yaml 读取 fallback_providers(或传统的 fallback_model)并传递给 AIAgent(fallback_model=...),与 gateway 的 _load_fallback_model() 模式匹配。参见 Cron 内部机制。
测试覆盖
参见 tests/test_fallback_model.py,包含对所有支持的提供者、一次性语义和边界情况的全面测试。