Пулы учётных данных
Пулы учётных данных позволяют регистрировать несколько 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
Быстрый старт
Если у вас уже есть API-ключ, заданный в .env, Hermes автоматически обнаружит его как пул из одного ключа. Чтобы использовать преимущества пула, добавьте больше ключей:
# Add a second OpenRouter key
hermes auth add openrouter --api-key sk-or-...-key
# Add a second Anthropic key
hermes auth add anthropic --type api-key --api-key sk-ant...-key
# Add an Anthropic OAuth credential (requires Claude Max plan + extra usage credits)
hermes auth add anthropic --type oauth
# Opens browser for OAuth login
Проверьте свои пулы:
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> |
Сбросить все статусы cooldown/истощения |
Стратегии ротации
Настройка через hermes auth → "Set rotation strategy" или в config.yaml:
credential_pool_strategies:
openrouter: round_robin
anthropic: least_used
| Стратегия | Поведение |
|---|---|
fill_first (по умолчанию) |
Использовать первый рабочий ключ, пока он не исчерпан, затем перейти к следующему |
round_robin |
Равномерно перебирать ключи, ротируя после каждого выбора |
least_used |
Всегда выбирать ключ с наименьшим количеством запросов |
random |
Случайный выбор среди рабочих ключей |
Обработка ошибок
Пул обрабатывает разные ошибки по-разному:
| Ошибка | Поведение | Cooldown |
|---|---|---|
| 429 Rate Limit | Повторная попытка на том же ключе один раз (кратковременный сбой). Второй подряд 429 переключает на следующий ключ | 1 час |
| 402 Billing/Quota | Немедленная ротация на следующий ключ | 24 часа |
| 401 Auth Expired | Сначала попытаться обновить OAuth-токен. Ротация только в случае неудачи обновления | — |
| Все ключи исчерпаны | Переход к fallback_model, если настроен |
— |
Флаг has_retried_429 сбрасывается при каждом успешном API-вызове, поэтому единичный кратковременный 429 не вызывает ротацию.
Пулы пользовательских endpoint'ов
Пользовательские endpoint'ы, совместимые с OpenAI (Together.ai, RunPod, локальные серверы), получают собственные пулы, ключом которых является имя endpoint'а из custom_providers в config.yaml.
Когда вы настраиваете пользовательский endpoint через hermes model, автоматически генерируется имя, например "Together.ai" или "Local (localhost:8080)". Это имя становится ключом пула.
# 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-tog...-key
Пулы пользовательских endpoint'ов хранятся в auth.json в разделе credential_pool с префиксом custom::
{
"credential_pool": {
"openrouter": [...],
"custom:together.ai": [...]
}
}
Автоматическое обнаружение
Hermes автоматически обнаруживает учётные данные из нескольких источников и заполняет пул при запуске:
| Источник | Пример | Автозаполнение? |
|---|---|---|
| Переменные окружения | OPENROUTER_API_KEY, ANTHROPIC_API_KEY |
Да |
| OAuth-токены (auth.json) | Codex device code, Nous device code | Да |
| Учётные данные Claude Code | ~/.claude/.credentials.json |
Да (Anthropic) |
| Hermes PKCE OAuth | ~/.hermes/auth.json |
Да (Anthropic) |
| Конфигурация пользовательских endpoint'ов | model.api_key в config.yaml |
Да (пользовательские endpoint'ы) |
| Ручные записи | Добавлены через hermes auth add |
Сохраняются в auth.json |
Автозаполненные записи обновляются при каждой загрузке пула — если вы удалите переменную окружения, соответствующая запись в пуле будет автоматически удалена. Ручные записи (добавленные через hermes auth add) никогда не удаляются автоматически.
Делегирование и совместное использование
Когда агент порождает подагентов через delegate_task, пул учётных данных родителя автоматически передаётся дочерним агентам:
-
Тот же провайдер — дочерний агент получает полный пул родителя, обеспечивая ротацию ключей при лимитах запросов
-
Другой провайдер — дочерний агент загружает собственный пул этого провайдера (если настроен)
-
Пул не настроен — дочерний агент использует унаследованный одиночный API-ключ
Это означает, что подагенты получают такую же устойчивость к лимитам запросов, как и родитель, без необходимости дополнительной настройки. Аренда учётных данных на уровне задачи гарантирует, что дочерние агенты не конфликтуют друг с другом при одновременной ротации ключей.
Потокобезопасность
Пул учётных данных использует блокировку потоков для всех изменений состояния (select(), mark_exhausted_and_rotate(), try_refresh_current(), mark_used()). Это обеспечивает безопасный конкурентный доступ, когда gateway обрабатывает несколько чат-сессий одновременно.
Архитектура
Полную диаграмму потока данных см. в docs/credential-pool-flow.excalidraw в репозитории.
Пул учётных данных встроен в уровень разрешения провайдера:
-
agent/credential_pool.py— Менеджер пула: хранение, выбор, ротация, cooldown'ы -
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