Runtime
На этой странице
Hermes имеет общий резолвер провайдера времени выполнения, используемый в:
- CLI
- gateway
- cron-задачах
- ACP
- вспомогательных вызовах моделей
Основная реализация:
hermes_cli/runtime_provider.py— разрешение учётных данных,_resolve_custom_runtime()hermes_cli/auth.py— реестр провайдеров,resolve_provider()hermes_cli/model_switch.py— общий конвейер переключения/model(CLI + gateway)agent/auxiliary_client.py— маршрутизация вспомогательных моделейproviders/— ABC + точки входа в реестр (ProviderProfile,register_provider,get_provider_profile,list_providers)plugins/model-providers/<name>/— плагины для каждого провайдера (встроенные), которые объявляютapi_mode,base_url,env_vars,fallback_modelsи регистрируют себя в реестре при первом обращении. Пользовательские плагины в$HERMES_HOME/plugins/model-providers/<name>/переопределяют встроенные с тем же именем.
get_provider_profile() в providers/ возвращает ProviderProfile для заданного идентификатора провайдера. runtime_provider.py вызывает его во время разрешения, чтобы получить канонические base_url, список приоритетов env_vars, api_mode и fallback_models без необходимости дублировать эти данные в нескольких файлах. Добавление нового плагина в plugins/model-providers/<your-provider>/ (или $HERMES_HOME/plugins/model-providers/<your-provider>/), который вызывает register_provider(), достаточно для того, чтобы runtime_provider.py его подхватил — никаких ветвлений в самом резолвере не требуется.
Если вы пытаетесь добавить нового провайдера первого класса для инференса, прочитайте Добавление провайдеров и Руководство по плагинам провайдеров моделей вместе с этой страницей.
Приоритет разрешения¶
На высоком уровне разрешение провайдера использует:
- явный запрос CLI/времени выполнения
- конфигурацию модели/провайдера в
config.yaml - переменные окружения
- значения по умолчанию или автоматическое разрешение, специфичные для провайдера
Этот порядок важен, потому что Hermes рассматривает сохранённый выбор модели/провайдера как источник истины для обычных запусков. Это предотвращает бесшумное переопределение конечной точки, которую пользователь последний раз выбрал в hermes model, устаревшей переменной окружения из shell.
Провайдеры¶
Текущие семейства провайдеров включают:
- AI Gateway (Vercel)
- OpenRouter
- Nous Portal
- OpenAI Codex
- Copilot / Copilot ACP
- Anthropic (нативный)
- Google / Gemini
- Alibaba / DashScope
- DeepSeek
- Z.AI
- Kimi / Moonshot
- MiniMax
- MiniMax China
- Kilo Code
- Hugging Face
- OpenCode Zen / OpenCode Go
- Custom (
provider: custom) — провайдер первого класса для любой OpenAI-совместимой конечной точки - Именованные пользовательские провайдеры (список
custom_providersв config.yaml)
Результат разрешения времени выполнения¶
Резолвер времени выполнения возвращает такие данные, как:
providerapi_modebase_urlapi_keysource- метаданные, специфичные для провайдера, такие как информация об истечении срока/обновлении
Почему это важно¶
Этот резолвер — основная причина, по которой Hermes может разделять логику аутентификации/времени выполнения между:
hermes chat- обработкой сообщений gateway
- cron-задачами, запускаемыми в новых сессиях
- сессиями редактора ACP
- задачами вспомогательных моделей
AI Gateway¶
Установите AI_GATEWAY_API_KEY в ~/.hermes/.env и запускайте с --provider ai-gateway. Hermes получает доступные модели из эндпоинта /models шлюза, фильтруя языковые модели с поддержкой использования инструментов.
OpenRouter, AI Gateway и пользовательские OpenAI-совместимые базовые URL¶
Hermes содержит логику для предотвращения утечки неверного API-ключа на пользовательскую конечную точку, когда существует несколько ключей провайдеров (например, OPENROUTER_API_KEY, AI_GATEWAY_API_KEY и OPENAI_API_KEY).
API-ключ каждого провайдера привязан к своему базовому URL:
OPENROUTER_API_KEYотправляется только на эндпоинтыopenrouter.aiAI_GATEWAY_API_KEYотправляется только на эндпоинтыai-gateway.vercel.shOPENAI_API_KEYиспользуется для пользовательских конечных точек и как запасной вариант
Hermes также различает:
- реальную пользовательскую конечную точку, выбранную пользователем
- запасной путь OpenRouter, используемый, когда пользовательская конечная точка не настроена
Это различие особенно важно для:
- локальных серверов моделей
- OpenAI-совместимых API, не являющихся OpenRouter или AI Gateway
- переключения провайдеров без повторного запуска настройки
- сохранённых в конфигурации пользовательских конечных точек, которые должны продолжать работать, даже если
OPENAI_BASE_URLне экспортирован в текущем shell
Нативный путь Anthropic¶
Anthropic теперь не только «через OpenRouter».
Когда разрешение провайдера выбирает anthropic, Hermes использует:
api_mode = anthropic_messages- нативный Anthropic Messages API
agent/anthropic_adapter.pyдля трансляции
Разрешение учётных данных для нативного Anthropic теперь предпочитает обновляемые учётные данные Claude Code скопированным токенам окружения, когда присутствуют оба. На практике это означает:
- файлы учётных данных Claude Code рассматриваются как предпочтительный источник, когда они содержат обновляемую аутентификацию
- ручные значения
ANTHROPIC_TOKEN/CLAUDE_CODE_OAUTH_TOKENпо-прежнему работают как явные переопределения - Hermes предварительно проверяет обновление учётных данных Anthropic перед нативными вызовами Messages API
- Hermes по-прежнему повторяет запрос один раз при получении 401 после пересоздания клиента Anthropic, как запасной путь
Путь OpenAI Codex¶
Codex использует отдельный путь Responses API:
api_mode = codex_responses- выделенное разрешение учётных данных и поддержка хранилища аутентификации
Маршрутизация вспомогательных моделей¶
Вспомогательные задачи, такие как:
- vision
- суммаризация извлечённых веб-данных
- суммаризация сжатия контекста
- суммаризация поиска по сессиям
- операции skills hub
- операции MCP helper
- сброс памяти (memory flushes)
могут использовать собственную маршрутизацию провайдера/модели, а не основную разговорную модель.
Когда вспомогательная задача настроена с провайдером main, Hermes разрешает её через тот же общий путь времени выполнения, что и обычный чат. На практике это означает:
- управляемые через окружение пользовательские конечные точки по-прежнему работают
- пользовательские конечные точки, сохранённые через
hermes model/config.yaml, также работают - вспомогательная маршрутизация может отличить реальную сохранённую пользовательскую конечную точку от запасного пути OpenRouter
Резервные модели¶
Hermes поддерживает настроенную пару резервной модели/провайдера, обеспечивая автоматическое переключение при возникновении ошибок основной модели.
Как это работает внутри¶
- Хранение:
AIAgent.__init__сохраняет словарьfallback_modelи устанавливает_fallback_activated = False. - Точки срабатывания:
_try_activate_fallback()вызывается из трёх мест в основном цикле повторных попыток вrun_agent.py: - После исчерпания попыток при невалидных ответах API (None choices, отсутствующий контент)
- При неисправимых ошибках клиента (HTTP 401, 403, 404)
- После исчерпания попыток при временных ошибках (HTTP 429, 500, 502, 503)
- Процесс активации (
_try_activate_fallback): - Возвращает
Falseнемедленно, если уже активировано или не настроено - Вызывает
resolve_provider_client()изauxiliary_client.pyдля создания нового клиента с правильной аутентификацией - Определяет
api_mode:codex_responsesдля openai-codex,anthropic_messagesдля anthropic,chat_completionsдля всего остального - Заменяет на месте:
self.model,self.provider,self.base_url,self.api_mode,self.client,self._client_kwargs - Для резервного варианта anthropic: создаёт нативный клиент Anthropic вместо OpenAI-совместимого
- Переоценивает кэширование промптов (включено для моделей Claude на OpenRouter)
- Устанавливает
_fallback_activated = True— предотвращает повторное срабатывание - Сбрасывает счётчик попыток в 0 и продолжает цикл
- Поток конфигурации:
- CLI:
cli.pyчитаетCLI_CONFIG["fallback_model"]→ передаёт вAIAgent(fallback_model=...) - Gateway:
gateway/run.py._load_fallback_model()читаетconfig.yaml→ передаёт вAIAgent - Валидация: оба ключа
providerиmodelдолжны быть непустыми, иначе резервный режим отключён
Что НЕ поддерживает резервный режим¶
- Делегирование сабагентам (
tools/delegate_tool.py): сабагенты наследуют провайдера родителя, но не конфигурацию резервного режима - Вспомогательные задачи: используют собственную независимую цепочку автоопределения провайдера (см. Маршрутизация вспомогательных моделей выше)
Cron-задачи поддерживают резервный режим: run_job() читает fallback_providers (или устаревший fallback_model) из config.yaml и передаёт его в AIAgent(fallback_model=...), повторяя шаблон _load_fallback_model() из gateway. См. Внутреннее устройство Cron.
Тестовое покрытие¶
См. tests/test_fallback_model.py для всесторонних тестов, охватывающих всех поддерживаемых провайдеров, семантику одноразовых запросов и граничные случаи.
Связанная документация¶
- Внутреннее устройство цикла агента
- Внутреннее устройство ACP
- Провайдеры
- Результат разрешения времени выполнения
- Почему это важно
- AI Gateway
- OpenRouter, AI Gateway и пользовательские OpenAI-совместимые базовые URL
- Нативный путь Anthropic
- Путь OpenAI Codex
- Маршрутизация вспомогательных моделей
- Резервные модели
- Как это работает внутри
- Что НЕ поддерживает резервный режим
- Тестовое покрытие
- Связанная документация