提供商运行时解析
Hermes 使用一个共享的提供商运行时解析器,适用于以下场景:
- CLI
- 网关
- 定时任务(cron jobs)
- ACP
- 辅助模型调用
核心实现包括:
hermes_cli/runtime_provider.py— 凭证解析,_resolve_custom_runtime()hermes_cli/auth.py— 提供商注册表,resolve_provider()hermes_cli/model_switch.py— 共享的/model切换管道(CLI + 网关)agent/auxiliary_client.py— 辅助模型路由
如果你正在尝试添加一个新的第一方推理提供商,请结合本页阅读 添加提供商。
解析优先级
从整体上看,提供商解析遵循以下顺序:
- 显式 CLI/运行时请求
config.yaml模型/提供商配置- 环境变量
- 提供商特定的默认值或自动解析
这一顺序至关重要,因为 Hermes 将保存的模型/提供商选择视为正常运行时的“事实来源”。这可防止旧的 shell 导出环境变量静默覆盖用户在 hermes model 中最后选定的端点。
提供商
当前支持的提供商类别包括:
- AI 网关(Vercel)
- OpenRouter
- Nous Portal
- OpenAI Codex
- Copilot / Copilot ACP
- Anthropic(原生)
- Google / Gemini
- 阿里巴巴 / DashScope
- DeepSeek
- Z.AI
- Kimi / Moonshot
- MiniMax
- MiniMax 中国版
- Kilo Code
- Hugging Face
- OpenCode Zen / OpenCode Go
- 自定义(
provider: custom)— 用于任何兼容 OpenAI 的端点的第一方提供商 - 命名自定义提供商(
custom_providers在 config.yaml 中列出)
运行时解析输出
运行时解析器返回如下数据:
providerapi_modebase_urlapi_keysource- 提供商特定的元数据(如过期/刷新信息)
为何如此重要
该解析器是 Hermes 能够在以下组件间共享认证与运行时逻辑的主要原因:
hermes chat- 网关消息处理
- 在全新会话中运行的定时任务
- ACP 编辑器会话
- 辅助模型任务
AI 网关
在 AI_GATEWAY_API_KEY 中设置 ~/.hermes/.env,并使用 --provider ai-gateway 运行。Hermes 会从网关的 /models 接口获取可用模型列表,并筛选出支持工具调用的语言模型。
OpenRouter、AI 网关及自定义 OpenAI 兼容基础 URL
Hermes 包含逻辑以避免在存在多个提供商密钥时(例如 OPENROUTER_API_KEY、AI_GATEWAY_API_KEY 和 OPENAI_API_KEY)将错误的 API 密钥泄露给自定义端点。
每个提供商的 API 密钥仅限于其自身的基础 URL:
OPENROUTER_API_KEY仅发送至openrouter.ai端点AI_GATEWAY_API_KEY仅发送至ai-gateway.vercel.sh端点OPENAI_API_KEY用于自定义端点,并作为回退选项
Hermes 还区分:
- 用户明确选择的自定义端点
- 当未配置自定义端点时使用的 OpenRouter 回退路径
这一区别尤其重要于:
- 本地模型服务器
- 非 OpenRouter / 非 AI 网关的 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 凭证刷新
- 若刷新后仍出现 401 错误,Hermes 会再次重试一次,作为后备路径
OpenAI Codex 路径
Codex 使用独立的 Responses API 路径:
api_mode = codex_responses- 专用的凭证解析和认证存储支持
辅助模型路由
辅助任务如:
- 视觉分析
- 网页提取摘要
- 上下文压缩摘要
- 会话搜索摘要
- 技能库操作
- MCP 辅助操作
- 内存清理
可使用独立的提供商/模型路由,而非主对话模型。
当辅助任务配置了提供者 main 时,Hermes 通过与常规聊天相同的共享运行时路径进行解析。实际上意味着:
- 基于环境变量的自定义端点仍然有效
- 通过
hermes model/config.yaml保存的自定义端点也有效 - 辅助路由能够区分真正的已保存自定义端点与 OpenRouter 回退路径
回退模型
Hermes 支持配置的回退模型/提供商对,允许在主模型遇到错误时进行运行时故障转移。
内部工作原理
-
存储:
AIAgent.__init__存储fallback_model字典,并设置_fallback_activated = False。 -
触发点:
_try_activate_fallback()在run_agent.py的主重试循环中被调用三次:- 在最大重试次数后遇到无效 API 响应(无 choices,缺少内容)
- 遇到不可重试的客户端错误(HTTP 401、403、404)
- 在最大重试次数后遇到临时错误(HTTP 429、500、502、503)
-
激活流程(
_try_activate_fallback):- 如果已激活或未配置,则立即返回
False - 从
resolve_provider_client()调用auxiliary_client.py构建新客户端并正确认证 - 确定
api_mode:codex_responses用于 openai-codex,anthropic_messages用于 anthropic,chat_completions用于其他所有情况 - 就地替换:
self.model、self.provider、self.base_url、self.api_mode、self.client、self._client_kwargs - 对 Anthropic 回退:构建原生 Anthropic 客户端,而非 OpenAI 兼容客户端
- 重新评估提示缓存(OpenRouter 上的 Claude 模型启用缓存)
- 设置
_fallback_activated = True— 防止再次触发 - 重置重试计数为 0 并继续循环
- 如果已激活或未配置,则立即返回
-
配置流程:
- CLI:
cli.py读取CLI_CONFIG["fallback_model"]→ 传递给AIAgent(fallback_model=...) - 网关:
gateway/run.py._load_fallback_model()读取config.yaml→ 传递给AIAgent - 验证:
provider和model键都必须非空,否则回退功能禁用
- CLI:
不支持回退的场景
- 子代理委派(
tools/delegate_tool.py):子代理继承父级的提供商,但不继承回退配置 - 定时任务(
cron/):以固定提供商运行,无回退机制 - 辅助任务:使用其自身独立的提供商自动检测链(参见上文“辅助模型路由”)
测试覆盖
详见 tests/test_fallback_model.py,涵盖所有支持的提供商、单次调用语义及边缘情况的全面测试。