Skip to main content

提供商运行时解析

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 — 辅助模型路由

如果你正在尝试添加一个新的第一方推理提供商,请结合本页阅读 添加提供商

解析优先级

从整体上看,提供商解析遵循以下顺序:

  1. 显式 CLI/运行时请求
  2. config.yaml 模型/提供商配置
  3. 环境变量
  4. 提供商特定的默认值或自动解析

这一顺序至关重要,因为 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 中列出)

运行时解析输出

运行时解析器返回如下数据:

  • provider
  • api_mode
  • base_url
  • api_key
  • source
  • 提供商特定的元数据(如过期/刷新信息)

为何如此重要

该解析器是 Hermes 能够在以下组件间共享认证与运行时逻辑的主要原因:

  • hermes chat
  • 网关消息处理
  • 在全新会话中运行的定时任务
  • ACP 编辑器会话
  • 辅助模型任务

AI 网关

AI_GATEWAY_API_KEY 中设置 ~/.hermes/.env,并使用 --provider ai-gateway 运行。Hermes 会从网关的 /models 接口获取可用模型列表,并筛选出支持工具调用的语言模型。

OpenRouter、AI 网关及自定义 OpenAI 兼容基础 URL

Hermes 包含逻辑以避免在存在多个提供商密钥时(例如 OPENROUTER_API_KEYAI_GATEWAY_API_KEYOPENAI_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 支持配置的回退模型/提供商对,允许在主模型遇到错误时进行运行时故障转移。

内部工作原理

  1. 存储AIAgent.__init__ 存储 fallback_model 字典,并设置 _fallback_activated = False

  2. 触发点_try_activate_fallback()run_agent.py 的主重试循环中被调用三次:

    • 在最大重试次数后遇到无效 API 响应(无 choices,缺少内容)
    • 遇到不可重试的客户端错误(HTTP 401、403、404)
    • 在最大重试次数后遇到临时错误(HTTP 429、500、502、503)
  3. 激活流程_try_activate_fallback):

    • 如果已激活或未配置,则立即返回 False
    • resolve_provider_client() 调用 auxiliary_client.py 构建新客户端并正确认证
    • 确定 api_modecodex_responses 用于 openai-codex,anthropic_messages 用于 anthropic,chat_completions 用于其他所有情况
    • 就地替换:self.modelself.providerself.base_urlself.api_modeself.clientself._client_kwargs
    • 对 Anthropic 回退:构建原生 Anthropic 客户端,而非 OpenAI 兼容客户端
    • 重新评估提示缓存(OpenRouter 上的 Claude 模型启用缓存)
    • 设置 _fallback_activated = True — 防止再次触发
    • 重置重试计数为 0 并继续循环
  4. 配置流程

    • CLI:cli.py 读取 CLI_CONFIG["fallback_model"] → 传递给 AIAgent(fallback_model=...)
    • 网关:gateway/run.py._load_fallback_model() 读取 config.yaml → 传递给 AIAgent
    • 验证:providermodel 键都必须非空,否则回退功能禁用

不支持回退的场景

  • 子代理委派tools/delegate_tool.py):子代理继承父级的提供商,但不继承回退配置
  • 定时任务cron/):以固定提供商运行,无回退机制
  • 辅助任务:使用其自身独立的提供商自动检测链(参见上文“辅助模型路由”)

测试覆盖

详见 tests/test_fallback_model.py,涵盖所有支持的提供商、单次调用语义及边缘情况的全面测试。

相关文档