> 原文链接:Credential Pools
title: Credential Pools description: 为每个 Provider 汇聚多个 API 密钥或 OAuth Token,实现自动轮换和速率限制恢复。 sidebar_label: Credential Pools sidebar_position: 9
Credential Pools(凭据池)
凭据池允许你为同一个 Provider 注册多个 API 密钥或 OAuth Token。当一个密钥触及速率限制或账单配额时,Hermes 会自动轮换到下一个健康密钥——保持会话活跃,无需切换 Provider。
这与 Fallback Provider 不同——Fallback Provider 切换到完全不同的 Provider。凭据池是同一 Provider 的轮换;Fallback Provider 是跨 Provider 的故障转移。池优先尝试——如果所有池密钥都耗尽,然后 Fallback Provider 才会激活。
工作原理
你的请求
→ 从池中选择密钥 (round_robin / least_used / fill_first / random)
→ 发送到 Provider
→ 429 速率限制?
→ 同一密钥重试一次(瞬时波动)
→ 第二次 429 → 轮换到下一个池密钥
→ 所有密钥耗尽 → fallback_model(不同 Provider)
→ 402 账单错误?
→ 立即轮换到下一个池密钥(24 小时冷却)
→ 401 认证过期?
→ 尝试刷新 Token(OAuth)
→ 刷新失败 → 轮换到下一个池密钥
→ 成功 → 正常继续
快速开始
如果你已经在 .env 中设置了 API 密钥,Hermes 会自动将其发现为 1 密钥池。要利用池功能,添加更多密钥:
# 添加第二个 OpenRouter 密钥
hermes auth add openrouter --api-key sk-or-...-key
# 添加第二个 Anthropic 密钥
hermes auth add anthropic --type api-key --api-key sk-ant...-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
这会显示完整的池状态并提供菜单:
你想做什么?
1. 添加凭据
2. 移除凭据
3. 重置 Provider 的冷却状态
4. 设置 Provider 的轮换策略
5. 退出
对于同时支持 API 密钥和 OAuth 的 Provider(Anthropic、Nous、Codex),添加流程会询问类型:
anthropic 同时支持 API 密钥和 OAuth 登录。
1. API 密钥(从 Provider 控制台粘贴密钥)
2. OAuth 登录(通过浏览器认证)
类型 [1/2]:
CLI 命令
| 命令 | 描述 |
|---|---|
hermes auth | 交互式池管理向导 |
hermes auth list | 显示所有池和凭据 |
hermes auth list <provider> | 显示特定 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 Token。仅在刷新失败时轮换 | — |
| 所有密钥耗尽 | 回退到 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 credential):
# #1 config key api_key config:Together.ai ←
# 为同一端点添加第二个密钥:
hermes auth add Together.ai --api-key sk-tog...-key
自定义端点池存储在 auth.json 的 credential_pool 中,带有 custom: 前缀:
{
"credential_pool": {
"openrouter": [...],
"custom:together.ai": [...]
}
}
自动发现
Hermes 自动从多个来源发现凭据并在启动时填充池:
| 来源 | 示例 | 自动填充? |
|---|---|---|
| 环境变量 | OPENROUTER_API_KEY、ANTHROPIC_API_KEY | 是 |
| OAuth Token (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 共享:
- 相同 Provider — 子 Agent 接收父 Agent 的完整池,支持速率限制时的密钥轮换
- 不同 Provider — 子 Agent 加载该 Provider 自己的池(如果已配置)
- 未配置池 — 子 Agent 回退到继承的单个 API 密钥
这意味着子 Agent 与父 Agent 拥有相同的速率限制弹性,无需额外配置。每任务凭据租约确保子 Agent 在并发轮换密钥时不会互相冲突。
线程安全
凭据池对所有状态变更(select()、mark_exhausted_and_rotate()、try_refresh_current()、mark_used())使用线程锁。这确保 Gateway 同时处理多个聊天会话时安全的并发访问。
架构
完整数据流图请参见仓库中的 docs/credential-pool-flow.excalidraw。
凭据池集成在 Provider 解析层:
agent/credential_pool.py— 池管理器:存储、选择、轮换、冷却hermes_cli/auth_commands.py— CLI 命令和交互式向导hermes_cli/runtime_provider.py— 感知池的凭据解析run_agent.py— 错误恢复:429/402/401 → 池轮换 → Fallback
存储
池状态存储在 ~/.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": "***",
"last_status": "ok",
"request_count": 142
}
]
},
}
策略存储在 config.yaml(而非 auth.json)中:
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used