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

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

Если провайдер — это просто «ещё один OpenAI-совместимый base URL и API key», именованного пользовательского провайдера может быть достаточно.

Ментальная модель

Встроенный провайдер должен быть согласован на нескольких уровнях:

  1. hermes_cli/auth.py определяет, как находятся учётные данные.

  2. hermes_cli/runtime_provider.py преобразует их в данные времени выполнения:

  3. provider
  4. api_mode
  5. base_url
  6. api_key
  7. source

  8. run_agent.py использует api_mode для того, чтобы решить, как формировать и отправлять запросы.

  9. hermes_cli/models.py и hermes_cli/main.py обеспечивают отображение провайдера в CLI. (hermes_cli/setup.py делегирует вызовы main.py автоматически — изменений там не требуется.)

  10. agent/auxiliary_client.py и agent/model_metadata.py поддерживают работу второстепенных задач и учёта токенов.

Ключевая абстракция — api_mode.

Сначала выберите путь реализации

Путь A — OpenAI-совместимый провайдер

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

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

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

Путь B — Нативный провайдер

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

Примеры, уже существующие в дереве:

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

Контрольный список файлов

Требуется для каждого встроенного провайдера

  1. hermes_cli/auth.py

  2. hermes_cli/models.py

  3. hermes_cli/runtime_provider.py

  4. hermes_cli/main.py

  5. agent/auxiliary_client.py

  6. agent/model_metadata.py

  7. тесты

  8. пользовательская документация в website/docs/

hermes_cli/setup.py **не** требует изменений. Мастер установки делегирует выбор провайдера/модели в select_provider_and_model() из main.py — любой провайдер, добавленный туда, автоматически доступен в hermes setup.

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

  1. agent/<provider>_adapter.py

  2. run_agent.py

  3. pyproject.toml если требуется SDK провайдера

Быстрый путь: Простые провайдеры с API-ключом

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

Всё, что нужно:

  1. Директория плагина в plugins/model-providers/<ваш-провайдер>/, содержащая:
  2. __init__.py — вызывает register_provider(profile) на уровне модуля
  3. plugin.yaml — манифест (name, kind: model-provider, version, description)

  4. Вот и всё. Плагины провайдера автоматически загружаются при первом вызове get_provider_profile() или list_providers() — как встроенные плагины (из этого репозитория), так и пользовательские плагины из $HERMES_HOME/plugins/model-providers/ подхватываются автоматически.

Когда вы добавляете плагин и он вызывает register_provider(), следующие вещи настраиваются автоматически:

  1. Запись PROVIDER_REGISTRY в auth.py (разрешение учётных данных, поиск переменных окружения)

  2. api_mode устанавливается в chat_completions

  3. base_url берётся из конфига или указанной переменной окружения

  4. env_vars проверяются в порядке приоритета для API-ключа

  5. Список fallback_models регистрируется для провайдера

  6. Флаг CLI --provider принимает id провайдера

  7. Меню hermes model включает провайдера

  8. Мастер hermes setup автоматически делегирует вызовы в main.py

  9. Синтаксис алиаса provider:model работает

  10. Разрешитель времени выполнения возвращает корректные base_url и api_key

  11. Переопределение через переменную окружения HERMES_INFERENCE_PROVIDER принимает id провайдера

  12. Активация fallback-модели может чисто переключиться на провайдера

Пользовательские плагины в $HERMES_HOME/plugins/model-providers/<имя>/ переопределяют встроенные плагины с тем же именем (последний записавший побеждает в register_provider()) — поэтому сторонние разработчики могут модифицировать или заменять любой встроенный профиль без редактирования репозитория.

Смотрите plugins/model-providers/nvidia/ или plugins/model-providers/gmi/ в качестве шаблона, а также полное руководство по Model Provider Plugin для справки по полям, идиомам хуков и сквозным примерам.

Полный путь: OAuth и сложные провайдеры

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

Шаг 1: Выберите один канонический id провайдера

Выберите один id провайдера и используйте его везде.

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

Этот же id должен присутствовать в:

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

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

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

Также добавьте алиасы в _PROVIDER_ALIASES.

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

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

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

Шаг 3: Добавьте каталог моделей и алиасы в hermes_cli/models.py

Обновите каталог провайдера, чтобы провайдер работал в меню и в синтаксисе provider:model.

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

Если провайдер предоставляет динамический список моделей, предпочитайте его, а _PROVIDER_MODELS оставляйте как статический запасной вариант.

Этот файл также отвечает за то, чтобы такие вводы работали:

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

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

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

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

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

{
    "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 к несвязанным endpoint. Новый провайдер должен быть столь же явным в том, какой ключ к какому base URL относится.

Шаг 5: Подключите CLI в hermes_cli/main.py

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

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

hermes_cli/setup.py не требует изменений — он вызывает select_provider_and_model() из main.py, поэтому ваш новый провайдер автоматически появляется как в hermes model, так и в hermes setup.

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

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

agent/auxiliary_client.py

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

Вспомогательные задачи включают:

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

agent/model_metadata.py

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

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

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

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

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

Новый файл адаптера

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

run_agent.py

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

Также найдите в run_agent.py все вхождения self.client.. Любой код, предполагающий существование стандартного клиента OpenAI, может сломаться, когда нативный провайдер использует другой объект клиента или self.client = None.

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

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

Примеры, уже существующие в дереве:

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

Шаг 8: Тесты

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

Обычные места:

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

Запускайте тесты с отключённым 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

Для более глубоких изменений запустите полный набор перед отправкой:

source venv/bin/activate
python -m pytest tests/ -n0 -q

Шаг 9: Проверка вживую

После тестов выполните реальную 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: Обновите пользовательскую документацию

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

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

Контрольный список для OpenAI-совместимого провайдера

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

Контрольный список для нативного провайдера

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

Распространённые ошибки

1. Добавление провайдера в auth, но не в разбор модели

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

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

Большая часть кода выбора провайдера должна нормализовывать обе формы.

3. Предположение, что встроенный провайдер обязателен

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

4. Забывание вспомогательных путей

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

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

Ищите api_mode и self.client.. Не предполагайте, что очевидный путь запроса — единственный.

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

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

7. Обновление hermes model, но не hermes setup

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

Хорошие цели для поиска при реализации

Если вы ищете все места, которых касается провайдер, ищите эти символы: