凭证池
Credential pool 允许你为同一个大模型提供商(provider)注册多个 API key 或 OAuth token。当某个 key 遇到限流或账单配额问题时,Hermes 会自动切换到下一个健康 key,而无需切换到其他 provider。
这与 fallback providers 不同。fallback 大模型提供商(provider) 是切换到另一个 provider;credential pool 是在同一个 大模型提供商(provider) 内部轮换。Hermes 会先尝试 pool;如果 pool 中所有 key 都耗尽,才会触发 fallback provider。
工作原理
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 key,Hermes 会自动把它识别为一个只含 1 个 key 的 pool。若想真正发挥 pool 价值,请继续添加更多 key:
# Add a second OpenRouter key
hermes auth add openrouter --api-key sk-or-v1-your-second-key
# Add a second Anthropic key
hermes auth add anthropic --type api-key --api-key sk-ant-api03-your-second-key
# Add an Anthropic OAuth credential (Claude Code subscription)
hermes auth add anthropic --type oauth
# Opens browser for OAuth login
查看当前 pool:
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
它会展示完整 pool 状态并提供菜单:
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 key 和 OAuth 的大模型提供商(provider)(如 Anthropic、Nous、Codex),添加流程会进一步询问凭据类型。
CLI 命令
| 命令 | 说明 |
|---|---|
hermes auth | 交互式 pool 管理向导 |
hermes auth list | 显示所有 pools 与凭据 |
hermes auth list <provider> | 显示某个特定 大模型提供商(provider) 的 pool |
hermes auth add <provider> | 添加凭据 |
hermes auth add <provider> --type api-key --api-key <key> | 非交互方式添加 API key |
hermes auth add <provider> --type oauth | 通过浏览器登录添加 OAuth 凭据 |
hermes auth remove <provider> <index> | 按 1-based 索引移除凭据 |
hermes auth reset <provider> | 清空该 大模型提供商(provider) 的 cooldown / exhaustion 状态 |
轮换策略
可通过 hermes auth → “Set rotation strategy” 或直接在 config.yaml 中配置:
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used
| 策略 | 行为 |
|---|---|
fill_first(默认) | 优先使用第一个健康 key,直到其耗尽,再切到下一个 |
round_robin | 均匀轮转,每次选择后切到下一个 |
least_used | 始终选择请求次数最少的 key |
random | 在健康 key 中随机选择 |
错误恢复
pool 会针对不同错误采取不同策略:
| 错误 | 行为 | Cooldown |
|---|---|---|
| 429 Rate Limit | 同一 key 先重试一次;连续第二次 429 才切换到下一个 key | 1 小时 |
| 402 Billing/Quota | 立即切换到下一个 key | 24 小时 |
| 401 Auth Expired | 先尝试刷新 OAuth token;仅在刷新失败时切换 | — |
| All keys exhausted | 若已配置 fallback_model,则回退到其他 大模型提供商(provider) | — |
has_retried_429 标志会在每次成功 API 调用后重置,因此单次偶发 429 不会立即触发轮换。
自定义端点 pools
自定义的 OpenAI 兼容端点(如 Together.ai、RunPod、本地服务)也会拥有自己的 credential pool,其 key 取自 config.yaml 中 custom_providers 的端点名称。
通过 hermes model 设置自定义端点时,Hermes 会自动生成名称,例如 “Together.ai” 或 “Local (localhost:8080)”。这个名称就是 pool 的主键。
# After setting up a custom endpoint via hermes model:
hermes auth list
# Shows:
# Together.ai (1 credential):
# #1 config key api_key config:Together.ai ←
# Add a second key for the same endpoint:
hermes auth add Together.ai --api-key sk-together-second-key
这些自定义端点的 pool 会以 custom: 前缀保存在 auth.json 的 credential_pool 下:
{
"credential_pool": {
"openrouter": [...],
"custom:together.ai": [...]
}
}
自动发现
Hermes 会从多个来源自动发现凭据,并在启动时为 pool 预填充:
| 来源 | 示例 | 自动加入 pool? |
|---|---|---|
| 环境变量 | OPENROUTER_API_KEY, ANTHROPIC_API_KEY | Yes |
| OAuth tokens(auth.json) | Codex device code, Nous device code | Yes |
| Claude Code 凭据 | ~/.claude/.credentials.json | Yes(Anthropic) |
| Hermes PKCE OAuth | ~/.hermes/auth.json | Yes(Anthropic) |
| 自定义端点配置 | model.api_key in config.yaml | Yes(自定义端点) |
| 手工添加项 | 通过 hermes auth add 添加 | 持久保存在 auth.json |
自动发现的条目会在每次加载 pool 时同步更新;如果你删除了某个环境变量,对应 pool 条目也会自动消失。手工添加的条目则不会被自动裁剪。
Delegation 与子智能体共享
当智能体通过 delegate_task 启动子智能体时,父智能体的 credential pool 会自动共享给子智能体:
- 同一 provider — 子智能体继承父智能体的完整 pool,可在限流时轮换 key
- 不同 provider — 子智能体会加载目标 大模型提供商(provider) 自己的 pool(若有配置)
- 未配置 pool — 子智能体会回退到继承下来的单个 API key
这意味着子智能体天然拥有与父智能体相同的限流韧性,无需额外配置。每任务凭据租约机制还能避免多个子智能体并发轮换时相互冲突。
线程安全
credential pool 在所有状态变更操作上都使用线程锁,从而确保 网关 同时处理多个聊天会话时的并发安全。
架构
完整数据流图见仓库中的 docs/credential-pool-flow.excalidraw。
credential pool 集成在 大模型提供商(provider) 解析层:
agent/credential_pool.py— pool 管理器:存储、选择、轮换、cooldownhermes_cli/auth_commands.py— CLI 命令与交互式向导hermes_cli/runtime_provider.py— 感知 pool 的凭据解析run_agent.py— 错误恢复:429 / 402 / 401 → pool 轮换 → fallback
存储
pool 状态保存在 ~/.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 中:
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used