Hermes 擁有共用的供應商執行時解析器,跨以下場景使用:
- CLI
- 閘道器
- 排程任務
- 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— 輔助模型路由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/):
- 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列表)
執行時解析的輸出
執行時解析器回傳的資料例如:
providerapi_modebase_urlapi_keysource- 供應商特定的中繼資料如到期/刷新資訊
為什麼這很重要
此解析器是 Hermes 能在以下場景之間共用認證/執行時邏輯的主要原因:
hermes chat- 閘道器訊息處理
- 在新會話中運行的排程任務
- ACP 編輯器會話
- 輔助模型任務
OpenRouter 和自訂 OpenAI 相容基礎 URL
Hermes 包含邏輯以避免在存在多個供應商金鑰時(例如 OPENROUTER_API_KEY 和 OPENAI_API_KEY)將錯誤的 API 金鑰洩漏到自訂端點。
每個供應商的 API 金鑰限定在其自己的基礎 URL 範圍:
OPENROUTER_API_KEY只發送到openrouter.ai端點OPENAI_API_KEY用於自訂端點並作為回退
Hermes 也區分:
- 使用者選擇的真實自訂端點
- 未設定自訂端點時使用的 OpenRouter 回退路徑
此區別對以下場景特別重要:
- 本地模型伺服器
- 非 OpenRouter 的 OpenAI 相容 API
- 無需重新執行設定即可切換供應商
- 應在
OPENAI_BASE_URL未在當前 shell 中匯出時仍可運作的設定儲存自訂端點
原生 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- 專用的憑證解析和認證儲存支援
輔助模型路由
輔助任務例如:
- 視覺
- 網頁擷取摘要
- 上下文壓縮摘要
- 技能 hub 操作
- MCP 輔助操作
- 記憶刷新
可以使用自己的供應商/模型路由,而非主對話模型。
當輔助任務以供應商 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、缺少 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 相容
- 重新評估提示快取(在 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):子代理繼承父代的供應商但不繼承降級設定 - 輔助任務:使用自己獨立的供應商自動偵測鏈(見上方輔助模型路由)
排程任務支援降級:run_job() 從 config.yaml 讀取 fallback_providers(或舊版 fallback_model)並傳遞給 AIAgent(fallback_model=...),與閘道器的 _load_fallback_model() 模式一致。參見排程任務內部。
測試覆蓋率
降級行為在多個測試套件中有覆蓋:
tests/run_agent/test_fallback_credential_isolation.py— 主模型和降級之間的憑證隔離tests/hermes_cli/test_fallback_cmd.py—/fallbackCLI 命令tests/gateway/test_fallback_eviction.py— 閘道器對失敗供應商的淘汰