Добавление провайдеров
Hermes уже может взаимодействовать с любым OpenAI-совместимым эндпоинтом через путь пользовательского провайдера. Не добавляйте встроенный провайдер, если вам не нужен первоклассный UX для этого сервиса:
- аутентификация или обновление токенов, специфичные для провайдера
- курируемый каталог моделей
- пункты меню настройки /
hermes model - алиасы провайдеров для синтаксиса
provider:model - не-OpenAI-образная форма API, требующая адаптераЕсли провайдер — это просто «ещё один совместимый с OpenAI URL и API ключ», может хватить именованного пользовательского провайдера.
Ментальная модель
Заголовок раздела «Ментальная модель»Встроенный провайдер должен быть согласован на нескольких уровнях:1. hermes_cli/auth.py определяет, как находятся учётные данные.
2. hermes_cli/runtime_provider.py преобразует это в данные времени выполнения:
providerapi_modebase_urlapi_keysource
run_agent.pyиспользуетapi_modeдля определения того, как формируются и отправляются запросы.4.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
Заголовок раздела «Путь A — провайдер, совместимый с OpenAI»Используйте этот путь, когда провайдер принимает запросы в стандартном формате chat-completions.
Типичная работа:
- добавить метаданные аутентификации
- добавить каталог моделей / псевдонимы
- добавить разрешение во время выполнения
- добавить подключение меню CLI
- добавить значения по умолчанию для вспомогательных моделей
- добавить тесты и документацию для пользователей
Обычно вам не нужен новый адаптер или новый api_mode.
Путь B — Нативный провайдер
Заголовок раздела «Путь B — Нативный провайдер»Используйте этот путь, когда провайдер не работает как OpenAI chat completions.
Примеры в текущей кодовой базе:
codex_responsesanthropic_messages
Этот путь включает всё из пути A плюс:
- адаптер провайдера в
agent/ run_agent.pyветки для построения запросов, отправки, извлечения использования, обработки прерываний и нормализации ответов- тесты адаптера
Чек-лист файлов
Заголовок раздела «Чек-лист файлов»Обязательно для каждого встроенного провайдера1. hermes_cli/auth.py
Заголовок раздела «Обязательно для каждого встроенного провайдера1. hermes_cli/auth.py»hermes_cli/models.pyhermes_cli/runtime_provider.pyhermes_cli/main.pyagent/auxiliary_client.pyagent/model_metadata.py- тесты
- пользовательская документация в
website/docs/
Дополнительно для нативных / не-OpenAI провайдеров
Заголовок раздела «Дополнительно для нативных / не-OpenAI провайдеров»agent/<provider>_adapter.pyrun_agent.pypyproject.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(разрешение учётных данных, поиск переменных окружения)
api_modeустановлен вchat_completionsbase_urlполучен из конфигурации или объявленной переменной окруженияenv_varsпроверяется в порядке приоритета для ключа APIfallback_modelsсписок, зарегистрированный для провайдера--providerCLI флаг принимает идентификатор провайдераhermes modelменю включает провайдераhermes setupмастер делегирует управлениеmain.pyавтоматически9.provider:modelсинтаксис псевдонима работает- Резолвер времени выполнения возвращает правильные
base_urlиapi_key HERMES_INFERENCE_PROVIDERпереопределение переменной окружения принимает идентификатор провайдера- Активация резервной модели может корректно переключиться на провайдераПользовательские плагины в
$HERMES_HOME/plugins/model-providers/<name>/переопределяют встроенные плагины с тем же именем (побеждает последний записавший вregister_provider()) — таким образом сторонние разработчики могут модифицировать или заменить любой встроенный профиль без редактирования репозитория.См.plugins/model-providers/nvidia/илиplugins/model-providers/gmi/в качестве шаблона, а также полное руководство по плагинам провайдеров моделей для справки по полям, идиомам хуков и сквозным примерам.
Полный путь: OAuth и сложные провайдеры
Заголовок раздела «Полный путь: OAuth и сложные провайдеры»Используйте полный чек-лист ниже, если вашему провайдеру требуется что-либо из следующего:
- OAuth или обновление токена (Nous Portal, Codex, Google Gemini, Qwen Portal, Copilot)
- Формат сообщений, отличный от OpenAI API, требующий нового адаптера (Anthropic Messages, Codex Responses)
- Обнаружение пользовательских эндпоинтов или мультирегиональное зондирование (z.ai, Kimi)
- Курируемый статический каталог моделей или динамическая загрузка
/models - Специфичные для провайдера пункты меню
hermes modelс индивидуальными потоками аутентификации
Шаг 1: Выберите один канонический идентификатор провайдераВыберите единый идентификатор провайдера и используйте его везде.
Заголовок раздела «Шаг 1: Выберите один канонический идентификатор провайдераВыберите единый идентификатор провайдера и используйте его везде.»Примеры из репозитория:
openai-codexkimi-codingminimax-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 с:
idnameauth_type="api_key"inference_base_urlapi_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-6kimi: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.
Шаг 5: Подключите CLI в hermes_cli/main.py
Заголовок раздела «Шаг 5: Подключите CLI в hermes_cli/main.py»Провайдер не будет обнаружен, пока не появится в интерактивном потоке hermes model.
Обновите следующее в hermes_cli/main.py:
provider_labelsdictproviderslist вselect_provider_and_model()- диспетчеризация провайдеров (
if selected_provider == ...) --providerварианты аргументов- login/logout варианты, если провайдер поддерживает эти потоки
- функция
_model_flow_<provider>(), или повторное использование_model_flow_api_key_provider(), если подходит
Шаг 6: Обеспечьте работоспособность вспомогательных вызовов
Заголовок раздела «Шаг 6: Обеспечьте работоспособность вспомогательных вызовов»Здесь важны два файла:
agent/auxiliary_client.py
Заголовок раздела «agent/auxiliary_client.py»Добавьте недорогую / быструю модель по умолчанию для вспомогательных задач в _API_KEY_PROVIDER_AUX_MODELS, если это прямой провайдер с API-ключом.
К вспомогательным задачам относятся, например:
- резюмирование изображений
- резюмирование веб-извлечения
- резюме сжатия контекста
- резюме поиска по сессиям
- сбросы памяти
Если у провайдера нет разумного значения по умолчанию для вспомогательных задач, побочные задачи могут работать некорректно или неожиданно использовать дорогую основную модель.
agent/model_metadata.py
Заголовок раздела «agent/model_metadata.py»Добавьте длины контекста для моделей провайдера, чтобы бюджет токенов, пороги сжатия и лимиты оставались в разумных пределах.
Шаг 7: Если провайдер является нативным, добавьте адаптер и поддержку run_agent.py
Заголовок раздела «Шаг 7: Если провайдер является нативным, добавьте адаптер и поддержку run_agent.py»Если провайдер не использует стандартный формат завершения чата, выделите логику, специфичную для провайдера, в agent/<provider>_adapter.py.
Держите run_agent.py сфокусированным на оркестрации. Он должен вызывать вспомогательные функции адаптера, а не формировать полезные нагрузки провайдера вручную по всему файлу.
Нативный провайдер обычно требует доработки в следующих местах:
Новый файл адаптера
Заголовок раздела «Новый файл адаптера»Типичные обязанности:
- создать клиент SDK / HTTP
- разрешить токены
- преобразовать сообщения разговора в стиле OpenAI в формат запроса провайдера
- при необходимости преобразовать схемы инструментов
- нормализовать ответы провайдера обратно в то, что ожидает
run_agent.py - извлечь данные об использовании и причине завершения
run_agent.py
Заголовок раздела «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 отправляет только те поля, которые этот провайдер действительно понимает.
Шаг 8: Тесты
Заголовок раздела «Шаг 8: Тесты»Как минимум, затроньте тесты, которые защищают проводку провайдеров.
Типичные места:
tests/test_runtime_provider_resolution.pytests/test_cli_provider_resolution.pytests/test_cli_model_command.pytests/test_setup_model_selection.pytests/test_provider_parity.pytests/test_run_agent.pytests/test_<provider>_adapter.pyдля нативного провайдера
Для примеров, содержащих только документацию, точный набор файлов может отличаться. Суть в том, чтобы охватить:
- разрешение аутентификации
- CLI меню / выбор провайдера
- разрешение провайдера во время выполнения
- путь выполнения агента
- парсинг provider:model
- любое преобразование сообщений, специфичное для адаптера
Запуск тестов с отключённым xdist:
source venv/bin/activatepython -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```Для более глубоких изменений запустите полный набор тестов перед отправкой:
```bashsource venv/bin/activatepython -m pytest tests/ -n0 -qШаг 9: Проверка в реальных условиях
Заголовок раздела «Шаг 9: Проверка в реальных условиях»После тестов выполните реальный smoke-тест.
source venv/bin/activatepython -m hermes_cli.main chat -q "Say hello" --provider your-provider --model your-modelТакже протестируйте интерактивные сценарии, если вы изменили меню:
source venv/bin/activatepython -m hermes_cli.main modelpython -m hermes_cli.main setupДля нативных провайдеров проверьте также хотя бы один вызов инструмента, а не только обычный текстовый ответ.
Шаг 10: Обновите пользовательскую документацию
Заголовок раздела «Шаг 10: Обновите пользовательскую документацию»Если провайдер должен поставляться как полноценный вариант, обновите также пользовательскую документацию:
website/docs/getting-started/quickstart.mdwebsite/docs/user-guide/configuration.mdwebsite/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, пользовательскую задачу может уже решить пользовательский провайдер с меньшими затратами на поддержку.
4. Забывание вспомогательных путей
Заголовок раздела «4. Забывание вспомогательных путей»Основной путь чата может работать, в то время как суммирование, сбросы памяти или вспомогательные модули для работы с изображениями завершаются ошибками, потому что маршрутизация вспомогательных путей никогда не обновлялась.
5. Ветки нативных провайдеров, скрытые в run_agent.py
Заголовок раздела «5. Ветки нативных провайдеров, скрытые в run_agent.py»Выполните поиск по api_mode и self.client.. Не предполагайте, что очевидный путь запроса является единственным.
6. Отправка параметров, специфичных только для OpenRouter, другим провайдерамПоля, такие как маршрутизация провайдеров, должны присутствовать только у тех провайдеров, которые их поддерживают.
Заголовок раздела «6. Отправка параметров, специфичных только для OpenRouter, другим провайдерамПоля, такие как маршрутизация провайдеров, должны присутствовать только у тех провайдеров, которые их поддерживают.»7. Обновление hermes model, но не hermes setup
Заголовок раздела «7. Обновление hermes model, но не hermes setup»Оба потока должны знать о провайдере.
Полезные символы для поиска при реализации
Заголовок раздела «Полезные символы для поиска при реализации»Если вы ищете все места, где задействован провайдер, искать нужно по следующим символам:
PROVIDER_REGISTRY_PROVIDER_ALIASES_PROVIDER_MODELSresolve_runtime_provider_model_flow_select_provider_and_modelapi_mode_API_KEY_PROVIDER_AUX_MODELSself.client.