Пулы учётных данных

Пулы учётных данных позволяют регистрировать несколько 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, пул учётных данных родителя автоматически передаётся дочерним агентам:

Это означает, что подагенты получают такую же устойчивость к лимитам запросов, как и родитель, без необходимости дополнительной настройки. Аренда учётных данных на уровне задачи гарантирует, что дочерние агенты не конфликтуют друг с другом при одновременной ротации ключей.

Потокобезопасность

Пул учётных данных использует блокировку потоков для всех изменений состояния (select(), mark_exhausted_and_rotate(), try_refresh_current(), mark_used()). Это обеспечивает безопасный конкурентный доступ, когда gateway обрабатывает несколько чат-сессий одновременно.

Архитектура

Полную диаграмму потока данных см. в docs/credential-pool-flow.excalidraw в репозитории.

Пул учётных данных встроен в уровень разрешения провайдера:

  1. agent/credential_pool.py — Менеджер пула: хранение, выбор, ротация, cooldown'ы

  2. hermes_cli/auth_commands.py — Команды CLI и интерактивный мастер

  3. hermes_cli/runtime_provider.py — Разрешение учётных данных с учётом пула

  4. 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