Перейти к содержимому

Добавление провайдеров

Hermes уже может взаимодействовать с любым OpenAI-совместимым эндпоинтом через путь пользовательского провайдера. Не добавляйте встроенный провайдер, если вам не нужен первоклассный UX для этого сервиса:

  • аутентификация или обновление токенов, специфичные для провайдера
  • курируемый каталог моделей
  • пункты меню настройки / hermes model
  • алиасы провайдеров для синтаксиса provider:model
  • не-OpenAI-образная форма API, требующая адаптераЕсли провайдер — это просто «ещё один совместимый с OpenAI URL и API ключ», может хватить именованного пользовательского провайдера.

Встроенный провайдер должен быть согласован на нескольких уровнях:1. hermes_cli/auth.py определяет, как находятся учётные данные. 2. hermes_cli/runtime_provider.py преобразует это в данные времени выполнения:

  • provider
    • api_mode
    • base_url
    • api_key
    • source
  1. run_agent.py использует api_mode для определения того, как формируются и отправляются запросы.4. hermes_cli/models.py и hermes_cli/main.py обеспечивают отображение провайдера в CLI. (hermes_cli/setup.py делегирует main.py автоматически — никаких изменений не требуется.)
  2. agent/auxiliary_client.py и agent/model_metadata.py обеспечивают корректную работу побочных задач и управления токен-бюджетом.Важная абстракция — api_mode.
  • Большинство провайдеров используют chat_completions.
  • Codex использует codex_responses.
  • Anthropic использует anthropic_messages.
  • Новый протокол, несовместимый с OpenAI, обычно означает добавление нового адаптера и новой ветки api_mode.

Используйте этот путь, когда провайдер принимает запросы в стандартном формате chat-completions.

Типичная работа:

  • добавить метаданные аутентификации
  • добавить каталог моделей / псевдонимы
  • добавить разрешение во время выполнения
  • добавить подключение меню CLI
  • добавить значения по умолчанию для вспомогательных моделей
  • добавить тесты и документацию для пользователей

Обычно вам не нужен новый адаптер или новый api_mode.

Используйте этот путь, когда провайдер не работает как OpenAI chat completions.

Примеры в текущей кодовой базе:

  • codex_responses
  • anthropic_messages

Этот путь включает всё из пути A плюс:

  • адаптер провайдера в agent/
  • run_agent.py ветки для построения запросов, отправки, извлечения использования, обработки прерываний и нормализации ответов
  • тесты адаптера

Обязательно для каждого встроенного провайдера1. hermes_cli/auth.py

Заголовок раздела «Обязательно для каждого встроенного провайдера1. hermes_cli/auth.py»
  1. hermes_cli/models.py
  2. hermes_cli/runtime_provider.py
  3. hermes_cli/main.py
  4. agent/auxiliary_client.py
  5. agent/model_metadata.py
  6. тесты
  7. пользовательская документация в website/docs/

Дополнительно для нативных / не-OpenAI провайдеров

Заголовок раздела «Дополнительно для нативных / не-OpenAI провайдеров»
  1. agent/<provider>_adapter.py
  2. run_agent.py
  3. pyproject.toml, если для провайдера требуется SDK

Быстрый путь: простые провайдеры с ключом APIЕсли ваш провайдер — это просто конечная точка, совместимая с OpenAI, которая аутентифицируется с помощью одного ключа API, вам не нужно изменять auth.py, runtime_provider.py, main.py или любые другие файлы из полного списка ниже.

Заголовок раздела «Быстрый путь: простые провайдеры с ключом APIЕсли ваш провайдер — это просто конечная точка, совместимая с OpenAI, которая аутентифицируется с помощью одного ключа API, вам не нужно изменять auth.py, runtime_provider.py, main.py или любые другие файлы из полного списка ниже.»

Всё, что вам нужно:1. Директория плагина в plugins/model-providers/<your-provider>/, содержащая:

  • __init__.py — вызывает register_provider(profile) на уровне модуля
    • plugin.yaml — манифест (имя, тип: model-provider, версия, описание)2. Всё. Плагины провайдеров загружаются автоматически при первом вызове get_provider_profile() или list_providers() — как встроенные плагины (из этого репозитория), так и пользовательские плагины из $HERMES_HOME/plugins/model-providers/ обнаруживаются и подключаются.Когда вы добавляете плагин и он вызывает register_provider(), следующее подключается автоматически:1. PROVIDER_REGISTRY запись в auth.py (разрешение учётных данных, поиск переменных окружения)
  1. api_mode установлен в chat_completions
  2. base_url получен из конфигурации или объявленной переменной окружения
  3. env_vars проверяется в порядке приоритета для ключа API
  4. fallback_models список, зарегистрированный для провайдера
  5. --provider CLI флаг принимает идентификатор провайдера
  6. hermes model меню включает провайдера
  7. hermes setup мастер делегирует управление main.py автоматически9. provider:model синтаксис псевдонима работает
  8. Резолвер времени выполнения возвращает правильные base_url и api_key
  9. HERMES_INFERENCE_PROVIDER переопределение переменной окружения принимает идентификатор провайдера
  10. Активация резервной модели может корректно переключиться на провайдераПользовательские плагины в $HERMES_HOME/plugins/model-providers/<name>/ переопределяют встроенные плагины с тем же именем (побеждает последний записавший в register_provider()) — таким образом сторонние разработчики могут модифицировать или заменить любой встроенный профиль без редактирования репозитория.См. plugins/model-providers/nvidia/ или plugins/model-providers/gmi/ в качестве шаблона, а также полное руководство по плагинам провайдеров моделей для справки по полям, идиомам хуков и сквозным примерам.

Используйте полный чек-лист ниже, если вашему провайдеру требуется что-либо из следующего:

  • OAuth или обновление токена (Nous Portal, Codex, Google Gemini, Qwen Portal, Copilot)
  • Формат сообщений, отличный от OpenAI API, требующий нового адаптера (Anthropic Messages, Codex Responses)
  • Обнаружение пользовательских эндпоинтов или мультирегиональное зондирование (z.ai, Kimi)
  • Курируемый статический каталог моделей или динамическая загрузка /models
  • Специфичные для провайдера пункты меню hermes model с индивидуальными потоками аутентификации

Шаг 1: Выберите один канонический идентификатор провайдераВыберите единый идентификатор провайдера и используйте его везде.

Заголовок раздела «Шаг 1: Выберите один канонический идентификатор провайдераВыберите единый идентификатор провайдера и используйте его везде.»

Примеры из репозитория:

  • openai-codex
  • kimi-coding
  • minimax-cn

Этот же идентификатор должен использоваться в:

  • PROVIDER_REGISTRY в hermes_cli/auth.py
  • _PROVIDER_LABELS в hermes_cli/models.py
  • _PROVIDER_ALIASES и в hermes_cli/auth.py, и в hermes_cli/models.py
  • CLI вариантах --provider в hermes_cli/main.py
  • ветках настройки / выбора модели
  • значениях по умолчанию вспомогательных моделей
  • тестахЕсли идентификатор отличается между этими файлами, провайдер будет работать частично: аутентификация может функционировать, в то время как /model, настройка или разрешение во время выполнения молча его пропустят.

Шаг 2: Добавьте метаданные аутентификации в hermes_cli/auth.py

Заголовок раздела «Шаг 2: Добавьте метаданные аутентификации в hermes_cli/auth.py»

Для провайдеров с API-ключом добавьте запись ProviderConfig в PROVIDER_REGISTRY с:

  • id
  • name
  • auth_type="api_key"
  • inference_base_url
  • api_key_env_vars
  • необязательный base_url_env_var

Также добавьте псевдонимы в _PROVIDER_ALIASES.Используйте существующих провайдеров в качестве шаблонов:

  • простой путь с API-ключом: Z.AI, MiniMax
  • путь с API-ключом и определением конечной точки: Kimi, Z.AI
  • нативное разрешение токенов: Anthropic
  • путь OAuth / auth-store: Nous, OpenAI Codex

Вопросы, на которые нужно ответить здесь:

  • Какие переменные окружения должен проверять Hermes и в каком порядке приоритета?
  • Нужны ли провайдеру переопределения base-URL?
  • Требуется ли проверка конечных точек или обновление токенов?
  • Что должно содержать сообщение об ошибке аутентификации при отсутствии учётных данных?

Если провайдеру требуется что-то большее, чем «найти ключ API», добавьте выделенный резолвер учётных данных вместо того, чтобы засорять логикой несвязанные ветки.

Шаг 3: Добавьте каталог моделей и псевдонимы в hermes_cli/models.pyОбновите каталог провайдеров, чтобы провайдер работал в меню и в синтаксисе provider:model.

Заголовок раздела «Шаг 3: Добавьте каталог моделей и псевдонимы в hermes_cli/models.pyОбновите каталог провайдеров, чтобы провайдер работал в меню и в синтаксисе provider:model.»

Типичные правки:

  • _PROVIDER_MODELS
  • _PROVIDER_LABELS
  • _PROVIDER_ALIASES
  • порядок отображения провайдеров внутри list_available_providers()
  • provider_model_ids(), если провайдер поддерживает получение списка моделей /models в реальном времени

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

anthropic:claude-sonnet-4-6
kimi:model-name

Если здесь отсутствуют псевдонимы, провайдер может пройти аутентификацию успешно, но всё равно завершиться ошибкой при парсинге /model.

Шаг 4: Разрешение данных времени выполнения в hermes_cli/runtime_provider.py

Заголовок раздела «Шаг 4: Разрешение данных времени выполнения в hermes_cli/runtime_provider.py»

resolve_runtime_provider() — это общий путь, используемый CLI, gateway, cron, ACP и вспомогательными клиентами.

Добавьте ветку, которая возвращает словарь как минимум с:

{
"provider": "your-provider",
"api_mode": "chat_completions",
# or your native mode
"base_url": "https://...",
"api_key": "...",
"source": "env|portal|auth-store|explicit",
"requested_provider": requested_provider,
}

Если провайдер совместим с OpenAI, api_mode обычно следует оставить chat_completions.Будьте осторожны с приоритетом ключей API. Hermes уже содержит логику для предотвращения утечки ключа OpenRouter к несвязанным конечным точкам. Новый провайдер должен быть столь же явным в отношении того, какой ключ используется для какого базового URL.

Провайдер не будет обнаружен, пока не появится в интерактивном потоке hermes model.

Обновите следующее в hermes_cli/main.py:

  • provider_labels dict
  • providers list в select_provider_and_model()
  • диспетчеризация провайдеров (if selected_provider == ...)
  • --provider варианты аргументов
  • login/logout варианты, если провайдер поддерживает эти потоки
  • функция _model_flow_<provider>(), или повторное использование _model_flow_api_key_provider(), если подходит

Шаг 6: Обеспечьте работоспособность вспомогательных вызовов

Заголовок раздела «Шаг 6: Обеспечьте работоспособность вспомогательных вызовов»

Здесь важны два файла:

Добавьте недорогую / быструю модель по умолчанию для вспомогательных задач в _API_KEY_PROVIDER_AUX_MODELS, если это прямой провайдер с API-ключом.

К вспомогательным задачам относятся, например:

  • резюмирование изображений
  • резюмирование веб-извлечения
  • резюме сжатия контекста
  • резюме поиска по сессиям
  • сбросы памяти

Если у провайдера нет разумного значения по умолчанию для вспомогательных задач, побочные задачи могут работать некорректно или неожиданно использовать дорогую основную модель.

Добавьте длины контекста для моделей провайдера, чтобы бюджет токенов, пороги сжатия и лимиты оставались в разумных пределах.

Шаг 7: Если провайдер является нативным, добавьте адаптер и поддержку run_agent.py

Заголовок раздела «Шаг 7: Если провайдер является нативным, добавьте адаптер и поддержку run_agent.py»

Если провайдер не использует стандартный формат завершения чата, выделите логику, специфичную для провайдера, в agent/<provider>_adapter.py.

Держите run_agent.py сфокусированным на оркестрации. Он должен вызывать вспомогательные функции адаптера, а не формировать полезные нагрузки провайдера вручную по всему файлу.

Нативный провайдер обычно требует доработки в следующих местах:

Типичные обязанности:

  • создать клиент SDK / HTTP
  • разрешить токены
  • преобразовать сообщения разговора в стиле OpenAI в формат запроса провайдера
  • при необходимости преобразовать схемы инструментов
  • нормализовать ответы провайдера обратно в то, что ожидает run_agent.py
  • извлечь данные об использовании и причине завершения

Найдите api_mode и проверьте каждую точку переключения. Как минимум убедитесь в следующем:

  • __init__ выбирает нового api_mode
  • создание клиента работает для провайдера
  • _build_api_kwargs() знает, как форматировать запросы
  • _interruptible_api_call() направляет вызов нужному клиенту
  • пути прерывания / пересборки клиента работают
  • валидация ответа принимает формат провайдера
  • извлечение причины завершения корректно
  • извлечение использования токенов корректно
  • активация резервной модели может чисто переключиться на нового провайдера- пути summary-generation и memory-flush по-прежнему работаютТакже выполните поиск run_agent.py по self.client.. Любой кодовый путь, предполагающий наличие стандартного клиента OpenAI, может сломаться, когда нативный провайдер использует другой объект клиента или self.client = None.

Кэширование prompt и специфичные для провайдера поля запросов

Заголовок раздела «Кэширование prompt и специфичные для провайдера поля запросов»

Кэширование prompt и специфичные для провайдера параметры легко регрессируют.

Примеры уже в кодовой базе:

  • Anthropic имеет собственный путь кэширования prompt-ов
  • OpenRouter получает поля маршрутизации провайдеров
  • не каждый провайдер должен получать все параметры на стороне запроса

При добавлении нативного провайдера убедитесь, что Hermes отправляет только те поля, которые этот провайдер действительно понимает.

Как минимум, затроньте тесты, которые защищают проводку провайдеров.

Типичные места:

  • tests/test_runtime_provider_resolution.py
  • tests/test_cli_provider_resolution.py
  • tests/test_cli_model_command.py
  • tests/test_setup_model_selection.py
  • tests/test_provider_parity.py
  • tests/test_run_agent.py
  • tests/test_<provider>_adapter.py для нативного провайдера

Для примеров, содержащих только документацию, точный набор файлов может отличаться. Суть в том, чтобы охватить:

  • разрешение аутентификации
  • CLI меню / выбор провайдера
  • разрешение провайдера во время выполнения
  • путь выполнения агента
  • парсинг provider:model
  • любое преобразование сообщений, специфичное для адаптера

Запуск тестов с отключённым xdist:

Окно терминала
source venv/bin/activate
python -m pytest tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/test_cli_model_command.py tests/test_setup_model_selection.py -n0 -q
```Для более глубоких изменений запустите полный набор тестов перед отправкой:
```bash
source venv/bin/activate
python -m pytest tests/ -n0 -q

После тестов выполните реальный smoke-тест.

Окно терминала
source venv/bin/activate
python -m hermes_cli.main chat -q "Say hello" --provider your-provider --model your-model

Также протестируйте интерактивные сценарии, если вы изменили меню:

Окно терминала
source venv/bin/activate
python -m hermes_cli.main model
python -m hermes_cli.main setup

Для нативных провайдеров проверьте также хотя бы один вызов инструмента, а не только обычный текстовый ответ.

Шаг 10: Обновите пользовательскую документацию

Заголовок раздела «Шаг 10: Обновите пользовательскую документацию»

Если провайдер должен поставляться как полноценный вариант, обновите также пользовательскую документацию:

  • website/docs/getting-started/quickstart.md
  • website/docs/user-guide/configuration.md
  • website/docs/reference/environment-variables.md

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

Чек-лист для провайдеров, совместимых с OpenAI

Заголовок раздела «Чек-лист для провайдеров, совместимых с OpenAI»

Используйте его, если провайдер поддерживает стандартные chat completions.- [ ] ProviderConfig добавлен в hermes_cli/auth.py

  • псевдонимы добавлены в hermes_cli/auth.py и hermes_cli/models.py
  • каталог моделей добавлен в hermes_cli/models.py
  • ветка среды выполнения добавлена в hermes_cli/runtime_provider.py
  • подключение CLI добавлено в hermes_cli/main.py (setup.py наследуется автоматически)
  • вспомогательная модель добавлена в agent/auxiliary_client.py
  • длины контекста добавлены в agent/model_metadata.py- [ ] runtime / CLI тесты обновлены
  • пользовательская документация обновлена

Используйте этот чек-лист, когда провайдеру требуется новый протокольный путь.

  • всё из чек-листа для совместимых с OpenAI
  • адаптер добавлен в agent/<provider>_adapter.py
  • новый api_mode поддерживается в run_agent.py
  • путь прерывания / перестроения работает
  • извлечение данных об использовании и причине завершения работает
  • путь отката работает
  • добавлены тесты адаптера
  • пройден живой дымовой тест

1. Добавление провайдера в аутентификацию, но не в парсинг моделей

Заголовок раздела «1. Добавление провайдера в аутентификацию, но не в парсинг моделей»

В этом случае учётные данные разрешаются корректно, но вводы /model и provider:model завершаются с ошибкой.

2. Забывчивость того, что config["model"] может быть строкой или словарём

Заголовок раздела «2. Забывчивость того, что config["model"] может быть строкой или словарём»

Много кода выбора провайдера должен нормализовать обе формы.

3. Предположение о необходимости встроенного провайдера

Заголовок раздела «3. Предположение о необходимости встроенного провайдера»

Если сервис просто совместим с OpenAI, пользовательскую задачу может уже решить пользовательский провайдер с меньшими затратами на поддержку.

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

5. Ветки нативных провайдеров, скрытые в run_agent.py

Заголовок раздела «5. Ветки нативных провайдеров, скрытые в run_agent.py»

Выполните поиск по api_mode и self.client.. Не предполагайте, что очевидный путь запроса является единственным.

6. Отправка параметров, специфичных только для OpenRouter, другим провайдерамПоля, такие как маршрутизация провайдеров, должны присутствовать только у тех провайдеров, которые их поддерживают.

Заголовок раздела «6. Отправка параметров, специфичных только для OpenRouter, другим провайдерамПоля, такие как маршрутизация провайдеров, должны присутствовать только у тех провайдеров, которые их поддерживают.»

Оба потока должны знать о провайдере.

Полезные символы для поиска при реализации

Заголовок раздела «Полезные символы для поиска при реализации»

Если вы ищете все места, где задействован провайдер, искать нужно по следующим символам:

  • PROVIDER_REGISTRY
  • _PROVIDER_ALIASES
  • _PROVIDER_MODELS
  • resolve_runtime_provider
  • _model_flow_
  • select_provider_and_model
  • api_mode
  • _API_KEY_PROVIDER_AUX_MODELS
  • self.client.