Добавление провайдеров
Hermes может общаться с любым OpenAI-совместимым endpoint через путь пользовательского провайдера. Не добавляйте встроенный провайдер, если вы не хотите обеспечить первоклассный UX для этого сервиса:
-
специфичная для провайдера аутентификация или обновление токенов
-
курируемый каталог моделей
-
пункты меню установки /
hermes model -
алиасы провайдера для синтаксиса
provider:model -
форма API, отличная от OpenAI, требующая адаптер
Если провайдер — это просто «ещё один OpenAI-совместимый base URL и API key», именованного пользовательского провайдера может быть достаточно.
Ментальная модель
Встроенный провайдер должен быть согласован на нескольких уровнях:
-
hermes_cli/auth.pyопределяет, как находятся учётные данные. -
hermes_cli/runtime_provider.pyпреобразует их в данные времени выполнения: providerapi_modebase_urlapi_key-
source -
run_agent.pyиспользуетapi_modeдля того, чтобы решить, как формировать и отправлять запросы. -
hermes_cli/models.pyиhermes_cli/main.pyобеспечивают отображение провайдера в CLI. (hermes_cli/setup.pyделегирует вызовыmain.pyавтоматически — изменений там не требуется.) -
agent/auxiliary_client.pyиagent/model_metadata.pyподдерживают работу второстепенных задач и учёта токенов.
Ключевая абстракция — api_mode.
-
Большинство провайдеров используют
chat_completions. -
Codex использует
codex_responses. -
Anthropic использует
anthropic_messages. -
Новый протокол, отличный от OpenAI, обычно означает добавление нового адаптера и новой ветки
api_mode.
Сначала выберите путь реализации
Путь A — OpenAI-совместимый провайдер
Используйте этот путь, когда провайдер принимает стандартные запросы в стиле chat completions.
Типичная работа:
-
добавить метаданные аутентификации
-
добавить каталог моделей / алиасы
-
добавить разрешение времени выполнения
-
добавить интеграцию в меню CLI
-
добавить значения по умолчанию для вспомогательных моделей
-
добавить тесты и пользовательскую документацию
Обычно вам не нужен новый адаптер или новый api_mode.
Путь B — Нативный провайдер
Используйте этот путь, когда провайдер не ведёт себя как OpenAI chat completions.
Примеры, уже существующие в дереве:
-
codex_responses -
anthropic_messages
Этот путь включает всё из пути A, а также:
-
адаптер провайдера в
agent/ -
ветки в
run_agent.pyдля построения запросов, отправки, извлечения использования, обработки прерываний и нормализации ответов -
тесты адаптера
Контрольный список файлов
Требуется для каждого встроенного провайдера
-
hermes_cli/auth.py -
hermes_cli/models.py -
hermes_cli/runtime_provider.py -
hermes_cli/main.py -
agent/auxiliary_client.py -
agent/model_metadata.py -
тесты
-
пользовательская документация в
website/docs/
hermes_cli/setup.py **не** требует изменений. Мастер установки делегирует выбор провайдера/модели в select_provider_and_model() из main.py — любой провайдер, добавленный туда, автоматически доступен в hermes setup.
Дополнительно для нативных / не-OpenAI провайдеров
-
agent/<provider>_adapter.py -
run_agent.py -
pyproject.tomlесли требуется SDK провайдера
Быстрый путь: Простые провайдеры с API-ключом
Если ваш провайдер — это просто OpenAI-совместимый endpoint, аутентифицирующийся одним API-ключом, вам не нужно трогать auth.py, runtime_provider.py, main.py или любые другие файлы из полного списка ниже.
Всё, что нужно:
- Директория плагина в
plugins/model-providers/<ваш-провайдер>/, содержащая: __init__.py— вызываетregister_provider(profile)на уровне модуля-
plugin.yaml— манифест (name, kind: model-provider, version, description) -
Вот и всё. Плагины провайдера автоматически загружаются при первом вызове
get_provider_profile()илиlist_providers()— как встроенные плагины (из этого репозитория), так и пользовательские плагины из$HERMES_HOME/plugins/model-providers/подхватываются автоматически.
Когда вы добавляете плагин и он вызывает register_provider(), следующие вещи настраиваются автоматически:
-
Запись
PROVIDER_REGISTRYвauth.py(разрешение учётных данных, поиск переменных окружения) -
api_modeустанавливается вchat_completions -
base_urlберётся из конфига или указанной переменной окружения -
env_varsпроверяются в порядке приоритета для API-ключа -
Список
fallback_modelsрегистрируется для провайдера -
Флаг CLI
--providerпринимает id провайдера -
Меню
hermes modelвключает провайдера -
Мастер
hermes setupавтоматически делегирует вызовы вmain.py -
Синтаксис алиаса
provider:modelработает -
Разрешитель времени выполнения возвращает корректные
base_urlиapi_key -
Переопределение через переменную окружения
HERMES_INFERENCE_PROVIDERпринимает id провайдера -
Активация fallback-модели может чисто переключиться на провайдера
Пользовательские плагины в $HERMES_HOME/plugins/model-providers/<имя>/ переопределяют встроенные плагины с тем же именем (последний записавший побеждает в register_provider()) — поэтому сторонние разработчики могут модифицировать или заменять любой встроенный профиль без редактирования репозитория.
Смотрите plugins/model-providers/nvidia/ или plugins/model-providers/gmi/ в качестве шаблона, а также полное руководство по Model Provider Plugin для справки по полям, идиомам хуков и сквозным примерам.
Полный путь: OAuth и сложные провайдеры
Используйте полный контрольный список ниже, когда вашему провайдеру требуется что-либо из следующего:
-
OAuth или обновление токенов (Nous Portal, Codex, Google Gemini, Qwen Portal, Copilot)
-
Форма API, отличная от OpenAI, требующая нового адаптера (Anthropic Messages, Codex Responses)
-
Пользовательское обнаружение endpoint или многорегиональное зондирование (Z.AI, Kimi)
-
Курируемый статический каталог моделей или динамическая загрузка
/models -
Специфичные для провайдера пункты меню
hermes modelс собственными потоками аутентификации
Шаг 1: Выберите один канонический id провайдера
Выберите один id провайдера и используйте его везде.
Примеры из репозитория:
-
openai-codex -
kimi-coding -
minimax-cn
Этот же id должен присутствовать в:
-
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 -
Ветки установки / выбора модели
-
Значения по умолчанию для вспомогательных моделей
-
Тесты
Если id различается между этими файлами, провайдер будет казаться наполовину подключённым: аутентификация может работать, в то время как /model, установка или разрешение времени выполнения будут молча его пропускать.
Шаг 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-ключом и обнаружением endpoint: Kimi, Z.AI
-
нативное разрешение токенов: Anthropic
-
путь OAuth / auth-store: Nous, OpenAI Codex
Вопросы, на которые нужно ответить здесь:
-
Какие переменные окружения должен проверять Hermes и в каком порядке приоритета?
-
Нужны ли провайдеру переопределения base URL?
-
Требуется ли зондирование endpoint или обновление токенов?
-
Что должно говориться в сообщении об ошибке аутентификации при отсутствии учётных данных?
Если провайдеру требуется нечто большее, чем «найти API-ключ», добавьте выделенный разрешитель учётных данных вместо того, чтобы встраивать логику в несвязанные ветки.
Шаг 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
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:
-
словарь
provider_labels -
список
providersвselect_provider_and_model() -
диспетчеризацию провайдера (
if selected_provider == ...) -
варианты аргумента
--provider -
варианты входа/выхода, если провайдер поддерживает эти потоки
-
функцию
_model_flow_<provider>(), или переиспользуйте_model_flow_api_key_provider(), если она подходит
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 сфокусированным на оркестрации. Он должен вызывать вспомогательные функции адаптера, а не встраивать полезные нагрузки провайдера вручную по всему файлу.
Нативный провайдер обычно требует работы в следующих местах:
Новый файл адаптера
Типичные обязанности:
-
создание SDK / HTTP-клиента
-
разрешение токенов
-
преобразование сообщений разговора в стиле OpenAI в формат запроса провайдера
-
преобразование схем инструментов при необходимости
-
нормализация ответов провайдера обратно в то, что ожидает
run_agent.py -
извлечение данных об использовании и причине завершения
run_agent.py
Найдите все вхождения api_mode и проверьте каждую точку ветвления. Как минимум, проверьте:
-
__init__выбирает новыйapi_mode -
конструкция клиента работает для провайдера
-
_build_api_kwargs()умеет форматировать запросы -
_interruptible_api_call()направляет вызов к правильному клиенту -
пути прерывания / пересоздания клиента работают
-
валидация ответа принимает формат провайдера
-
извлечение причины завершения корректно
-
извлечение использования токенов корректно
-
активация fallback-модели может чисто переключиться на новый провайдер
-
пути генерации суммаризаций и сброса памяти всё ещё работают
Также найдите в run_agent.py все вхождения self.client.. Любой код, предполагающий существование стандартного клиента OpenAI, может сломаться, когда нативный провайдер использует другой объект клиента или self.client = None.
Кэширование промптов и специфичные для провайдера поля запросов
Кэширование промптов и специфичные для провайдера настройки легко сломать.
Примеры, уже существующие в дереве:
-
Anthropic имеет нативный путь кэширования промптов
-
OpenRouter получает поля маршрутизации провайдеров
-
не каждый провайдер должен получать все опции на стороне запроса
Когда вы добавляете нативный провайдер, перепроверьте, что Hermes отправляет только те поля, которые этот провайдер действительно понимает.
Шаг 8: Тесты
Как минимум, затроньте тесты, которые проверяют подключение провайдера.
Обычные места:
-
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
Для более глубоких изменений запустите полный набор перед отправкой:
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: Обновите пользовательскую документацию
Если провайдер предназначен для поставки как первоклассный вариант, обновите также пользовательскую документацию:
-
website/docs/getting-started/quickstart.md -
website/docs/user-guide/configuration.md -
website/docs/reference/environment-variables.md
Разработчик может идеально подключить провайдера и всё равно оставить пользователей неспособными найти необходимые переменные окружения или процесс установки.
Контрольный список для 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 -
[ ] тесты времени выполнения / CLI обновлены
-
[ ] пользовательская документация обновлена
Контрольный список для нативного провайдера
Используйте этот список, когда провайдеру требуется новый путь протокола.
-
[ ] всё из контрольного списка для OpenAI-совместимого провайдера
-
[ ] адаптер добавлен в
agent/<provider>_adapter.py -
[ ] новый
api_modeподдерживается вrun_agent.py -
[ ] путь прерывания / пересоздания работает
-
[ ] извлечение использования и причины завершения работает
-
[ ] путь fallback работает
-
[ ] тесты адаптера добавлены
-
[ ] live smoke-тест проходит
Распространённые ошибки
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
Оба потока должны знать о провайдере.
Хорошие цели для поиска при реализации
Если вы ищете все места, которых касается провайдер, ищите эти символы:
-
PROVIDER_REGISTRY -
_PROVIDER_ALIASES -
_PROVIDER_MODELS -
resolve_runtime_provider -
_model_flow_ -
select_provider_and_model -
api_mode -
_API_KEY_PROVIDER_AUX_MODELS -
self.client.