憑據池
憑據池允許你為同一提供商註冊多個 API 密鑰或 OAuth 令牌。當某個密鑰達到速率限制或賬單配額時,Hermes 會自動切換到下一個健康的密鑰——在不切換提供商的情況下保持會話持續運行。
這與 備用提供商 不同,後者會完全切換到 另一個 提供商。憑據池是同一提供商內的輪換;而備用提供商則是跨提供商的故障轉移。系統會優先嚐試池中的密鑰——只有當池中所有密鑰都耗盡後,才會激活備用提供商。
工作原理
Your request
→ Pick key from pool (round_robin / least_used / fill_first / random)
→ Send to provider
→ 429 rate limit?
→ Retry same key once (transient blip)
→ Second 429 → rotate to next pool key
→ All keys exhausted → fallback_model (different provider)
→ 402 billing error?
→ Immediately rotate to next pool key (24h cooldown)
→ 401 auth expired?
→ Try refreshing the token (OAuth)
→ Refresh failed → rotate to next pool key
→ Success → continue normally
快速入門
如果你已經在 .env 文件中設置了 API 密鑰,Hermes 會自動將其識別為一個單密鑰池。要享受池化帶來的優勢,請添加更多密鑰:
# 添加第二個 OpenRouter 密鑰
hermes auth add openrouter --api-key sk-or-v1-your-second-key
# 添加第二個 Anthropic 密鑰
hermes auth add anthropic --type api-key --api-key sk-ant-api03-your-second-key
# 添加 Anthropic OAuth 憑證(Claude Code 訂閱)
hermes auth add anthropic --type oauth
# 打開瀏覽器進行 OAuth 登錄
檢查你的池狀態:
hermes auth list
輸出:
openrouter (2 credentials):
#1 OPENROUTER_API_KEY api_key env:OPENROUTER_API_KEY ←
#2 backup-key api_key manual
anthropic (3 credentials):
#1 hermes_pkce oauth hermes_pkce ←
#2 claude_code oauth claude_code
#3 ANTHROPIC_API_KEY api_key env:ANTHROPIC_API_KEY
← 標記了當前選中的憑據。
交互式管理
運行 hermes auth(不帶子命令)可啟動交互式嚮導:
hermes auth
這將顯示你完整的池狀態,並提供一個菜單:
What would you like to do?
1. Add a credential
2. Remove a credential
3. Reset cooldowns for a provider
4. Set rotation strategy for a provider
5. Exit
對於同時支持 API 密鑰和 OAuth 的提供商(如 Anthropic、Nous、Codex),添加流程會詢問你選擇哪種類型:
anthropic supports both API keys and OAuth login.
1. API key (paste a key from the provider dashboard)
2. OAuth login (authenticate via browser)
Type [1/2]:
CLI 命令
| 命令 | 描述 |
|---|---|
hermes auth | 交互式池管理嚮導 |
hermes auth list | 顯示所有池和憑據 |
hermes auth list <provider> | 顯示特定提供商的池 |
hermes auth add <provider> | 添加憑據(會提示選擇類型和密鑰) |
hermes auth add <provider> --type api-key --api-key <key> | 非交互式添加 API 密鑰 |
hermes auth add <provider> --type oauth | 通過瀏覽器登錄添加 OAuth 憑據 |
hermes auth remove <provider> <index> | 根據 1 開始的索引移除憑據 |
hermes auth reset <provider> | 清除所有冷卻/耗盡狀態 |
輪換策略
可通過 hermes auth → “設置輪換策略” 或在 config.yaml 中配置:
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used
| 策略 | 行為 |
|---|---|
fill_first(默認) | 使用第一個健康的密鑰,直到耗盡,然後切換到下一個 |
round_robin | 均勻循環使用密鑰,每次選擇後輪換 |
least_used | 始終選擇請求次數最少的密鑰 |
random | 在健康的密鑰中隨機選擇 |
錯誤恢復
池會根據不同的錯誤採取不同行為:
| 錯誤 | 行為 | 冷卻時間 |
|---|---|---|
| 429 速率限制 | 同一密鑰重試一次(瞬態)。連續兩次 429 則切換到下一個密鑰 | 1 小時 |
| 402 賬單/配額限制 | 立即切換到下一個密鑰 | 24 小時 |
| 401 認證過期 | 首先嚐試刷新 OAuth 令牌。僅在刷新失敗時才輪換 | — |
| 所有密鑰耗盡 | 如果已配置,將切換到 fallback_model | — |
has_retried_429 標誌在每次成功 API 調用後重置,因此單次瞬態 429 不會觸發輪換。
自定義端點池
自定義 OpenAI 兼容端點(如 Together.ai、RunPod、本地服務器)擁有獨立的池,其鍵名為 config.yaml 中 custom_providers 的端點名稱。
當你通過 hermes model 設置自定義端點時,會自動生成一個名稱,如 "Together.ai" 或 "Local (localhost:8080)"。該名稱將成為池的鍵。
# 通過 hermes model 設置自定義端點後:
hermes auth list
# 顯示:
# Together.ai(1 個證書):
# #1 配置鍵 api_key config:Together.ai ←
# 為同一端點添加第二個密鑰:
hermes auth add Together.ai --api-key sk-together-second-key
自定義端點池存儲在 auth.json 的 credential_pool 下,帶有 custom: 前綴:
{
"credential_pool": {
"openrouter": [...],
"custom:together.ai": [...]
}
}
自動發現
Hermes 會自動從多個來源發現憑據,並在啟動時自動填充池:
| 來源 | 示例 | 是否自動填充 |
|---|---|---|
| 環境變量 | OPENROUTER_API_KEY、ANTHROPIC_API_KEY | 是 |
| OAuth 令牌(auth.json) | Codex 設備碼、Nous 設備碼 | 是 |
| Claude Code 憑據 | ~/.claude/.credentials.json | 是(Anthropic) |
| Hermes PKCE OAuth | ~/.hermes/auth.json | 是(Anthropic) |
| 自定義端點配置 | config.yaml 中的 model.api_key | 是(自定義端點) |
| 手動添加項 | 通過 hermes auth add 添加 | 持久化於 auth.json |
自動填充的條目會在每次池加載時更新——如果你移除了一個環境變量,其池條目會自動清理。手動添加的條目(通過 hermes auth add 添加)不會被自動清理。
委託與子 Agent 共享
當 Agent 通過 delegate_task 派生子 Agent 時,父 Agent 的憑據池會自動共享給子 Agent:
- 同一提供商 —— 子 Agent 接收父 Agent 的完整憑據池,支持在速率限制下進行密鑰輪換
- 不同提供商 —— 子 Agent 加載該提供商自己的憑據池(如果已配置)
- 未配置憑據池 —— 子 Agent 回退到繼承的單個 API 密鑰
這意味著子 Agent 可以像父 Agent 一樣受益於速率限制的容錯能力,無需額外配置。每任務憑據租賃機制確保子 Agent 在併發輪換密鑰時不會相互衝突。
線程安全
憑據池對所有狀態變更操作(select()、mark_exhausted_and_rotate()、try_refresh_current()、mark_used())使用線程鎖,確保網關在同時處理多個聊天會話時能夠安全地併發訪問。
架構
完整的數據流圖請參見倉庫中的 docs/credential-pool-flow.excalidraw。
憑據池集成在提供者解析層:
agent/credential_pool.py— 池管理器:存儲、選擇、輪換、冷卻期hermes_cli/auth_commands.py— CLI 命令和交互式嚮導hermes_cli/runtime_provider.py— 支持池的憑據解析run_agent.py— 錯誤恢復:429/402/401 → 池輪換 → 備用方案
存儲
池狀態存儲在 ~/.hermes/auth.json 文件的 credential_pool 鍵下:
{
"version": 1,
"credential_pool": {
"openrouter": [
{
"id": "abc123",
"label": "OPENROUTER_API_KEY",
"auth_type": "api_key",
"priority": 0,
"source": "env:OPENROUTER_API_KEY",
"access_token": "sk-or-v1-...",
"last_status": "ok",
"request_count": 142
}
]
},
}
策略存儲在 config.yaml 中(不在 auth.json 中):
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used