Плагины

В Hermes есть система плагинов: она добавляет собственные инструменты, хуки и интеграции, не вынуждая лезть в код ядра.

Нужен свой инструмент — для себя, команды или одного проекта? Скорее всего, плагин и есть то, что вам нужно. А вот страница Добавление инструментов из руководства разработчика — про встроенные инструменты ядра Hermes, которые живут в tools/ и toolsets.py.

Соберите плагин для Hermes — пошаговое руководство с готовым рабочим примером.

Коротко о главном

Положите каталог в ~/.hermes/plugins/, добавьте туда plugin.yaml и код на Python:

~/.hermes/plugins/my-plugin/
├── plugin.yaml      # манифест
├── __init__.py      # register() — связывает схемы с обработчиками
├── schemas.py       # схемы инструментов (то, что видит LLM)
└── tools.py         # обработчики инструментов (что выполняется при вызове)

Запустите Hermes — ваши инструменты встанут рядом со встроенными. Модель сможет вызывать их сразу же.

Минимальный рабочий пример

Перед вами законченный плагин: он добавляет инструмент hello_world и пишет в лог каждый вызов инструмента через хук.

~/.hermes/plugins/hello-world/plugin.yaml

name: hello-world
version: "1.0"
description: A minimal example plugin

~/.hermes/plugins/hello-world/__init__.py

"""Minimal Hermes plugin — registers a tool and a hook."""

import json


def register(ctx):
    # --- Инструмент: hello_world ---
    schema = {
        "name": "hello_world",
        "description": "Returns a friendly greeting for the given name.",
        "parameters": {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Name to greet",
                }
            },
            "required": ["name"],
        },
    }

    def handle_hello(params, **kwargs):
        del kwargs
        name = params.get("name", "World")
        return json.dumps({"success": True, "greeting": f"Hello, {name}!"})

    ctx.register_tool(
        name="hello_world",
        toolset="hello_world",
        schema=schema,
        handler=handle_hello,
        description="Return a friendly greeting for the given name.",
    )

    # --- Хук: логируем каждый вызов инструмента ---
    def on_tool_call(tool_name, params, result):
        print(f"[hello-world] tool called: {tool_name}")

    ctx.register_hook("post_tool_call", on_tool_call)

Закиньте оба файла в ~/.hermes/plugins/hello-world/, перезапустите Hermes — и модель сразу сможет вызвать hello_world. Хук печатает строку лога после каждого срабатывания инструмента.

Локальные плагины проекта в ./.hermes/plugins/ по умолчанию выключены. Включайте их только для репозиториев, которым доверяете: задайте HERMES_ENABLE_PROJECT_PLUGINS=true перед запуском Hermes.

Что умеют плагины

Любой API из таблицы ниже (ctx.*) доступен внутри функции register(ctx) вашего плагина.

ВозможностьКак
Добавить инструментыctx.register_tool(name=..., toolset=..., schema=..., handler=...)
Добавить хукиctx.register_hook("post_tool_call", callback)
Добавить слэш-командыctx.register_command(name, handler, description) — добавляет /name в CLI и сессиях шлюза
Вызывать инструменты из командctx.dispatch_tool(name, args) — запускает зарегистрированный инструмент с автоматически подключённым контекстом родительского агента
Добавить команды CLIctx.register_cli_command(name, help, setup_fn, handler_fn) — добавляет hermes <plugin> <subcommand>
Внедрять сообщенияctx.inject_message(content, role="user") — см. Внедрение сообщений
Поставлять файлы данныхPath(__file__).parent / "data" / "file.yaml"
Поставлять навыкиctx.register_skill(name, path) — попадает в пространство имён как plugin:skill, загружается через skill_view("plugin:skill")
Требовать переменные окруженияrequires_env: [API_KEY] в plugin.yaml — запрашивается во время hermes plugins install
Распространять через pip[project.entry-points."hermes_agent.plugins"]
Зарегистрировать платформу шлюза (Discord, Telegram, IRC, …)ctx.register_platform(name, label, adapter_factory, check_fn, ...) — см. Добавление адаптеров платформ
Зарегистрировать бэкенд генерации изображенийctx.register_image_gen_provider(provider) — см. Плагины провайдеров генерации изображений
Зарегистрировать бэкенд генерации видеоctx.register_video_gen_provider(provider) — см. Плагины провайдеров генерации видео
Зарегистрировать движок сжатия контекстаctx.register_context_engine(engine) — см. Плагины движка контекста
Зарегистрировать бэкенд памятиНаследник MemoryProvider в plugins/memory/<name>/__init__.py — см. Плагины провайдеров памяти (использует отдельную систему обнаружения)
Выполнить вызов LLM от имени хостаctx.llm.complete(...) / ctx.llm.complete_structured(...) — заимствует активную модель пользователя и его авторизацию для одиночного запроса с опциональной проверкой по JSON-схеме. См. Доступ плагина к LLM
Зарегистрировать бэкенд инференса (провайдер LLM)register_provider(ProviderProfile(...)) в plugins/model-providers/<name>/__init__.py — см. Плагины провайдеров моделей (использует отдельную систему обнаружения)

Обнаружение плагинов

ИсточникПутьКогда используется
Встроенные<repo>/plugins/Поставляются вместе с Hermes — см. Встроенные плагины
Пользовательские~/.hermes/plugins/Личные плагины
Проектные.hermes/plugins/Плагины конкретного проекта (нужен HERMES_ENABLE_PROJECT_PLUGINS=true)
pipentry_points hermes_agent.pluginsРаспространяемые пакеты
Nixservices.hermes-agent.extraPlugins / extraPythonPackagesДекларативная установка в NixOS — см. Настройка Nix

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

Подкатегории плагинов

Внутри каждого источника Hermes распознаёт ещё и каталоги-подкатегории — они направляют плагины в специализированные системы обнаружения:

ПодкаталогЧто в нём лежитСистема обнаружения
plugins/ (корень)Обычные плагины — инструменты, хуки, слэш-команды, команды CLI, встроенные навыкиPluginManager (kind: standalone или backend)
plugins/platforms/<name>/Адаптеры каналов шлюза (ctx.register_platform())PluginManager (kind: platform, на уровень глубже)
plugins/image_gen/<name>/Бэкенды генерации изображений (ctx.register_image_gen_provider())PluginManager (kind: backend, на уровень глубже)
plugins/memory/<name>/Провайдеры памяти (наследники MemoryProvider)Собственный загрузчик в plugins/memory/__init__.py (kind: exclusive — активен один за раз)
plugins/context_engine/<name>/Движки сжатия контекста (ctx.register_context_engine())Собственный загрузчик в plugins/context_engine/__init__.py (активен один за раз)
plugins/model-providers/<name>/Профили провайдеров LLM (register_provider(ProviderProfile(...)))Собственный загрузчик в providers/__init__.py (лениво сканируется при первом вызове get_provider_profile())

Пользовательские плагины в ~/.hermes/plugins/model-providers/<name>/ и ~/.hermes/plugins/memory/<name>/ перекрывают одноимённые встроенные — побеждает тот, кто записал последним, в register_provider() / register_memory_provider(). Бросаете каталог на место — и он заменяет встроенный без единой правки в репозитории.

Плагины подключаются по выбору (за парой исключений)

Обычные плагины и бэкенды, установленные пользователем, по умолчанию выключены — обнаружение их находит (поэтому они видны в hermes plugins и /plugins), но ничего с хуками или инструментами не загрузится, пока вы не добавите имя плагина в plugins.enabled внутри ~/.hermes/config.yaml. Так сторонний код не запустится без вашего явного согласия.

plugins:
  enabled:
    - my-tool-plugin
    - disk-cleanup
  disabled:       # необязательный чёрный список — всегда побеждает, если имя есть в обоих
    - noisy-plugin

Переключить состояние можно тремя способами:

hermes plugins                    # интерактивный переключатель (пробел — отметить/снять)
hermes plugins enable <name>      # добавить в список разрешений
hermes plugins disable <name>     # убрать из списка разрешений + добавить в disabled

После hermes plugins install owner/repo вас спросят Enable 'name' now? [y/N] — по умолчанию «нет». Для установок из скриптов запрос пропускается флагами --enable или --no-enable.

Что список разрешений НЕ контролирует

Несколько категорий плагинов обходят plugins.enabled — они входят во встроенный набор Hermes и сломали бы базовую работу, будь они выключены по умолчанию:

Тип плагинаЧем активируется вместо этого
Встроенные плагины платформ (IRC, Teams и прочее в plugins/platforms/)Загружаются автоматически, чтобы был доступен любой поставляемый канал шлюза. Сам канал включается через gateway.platforms.<name>.enabled в config.yaml.
Встроенные бэкенды (провайдеры генерации изображений в plugins/image_gen/ и т. д.)Загружаются автоматически, чтобы бэкенд по умолчанию «просто работал». Выбор делается через <category>.provider в config.yaml (например, image_gen.provider: openai).
Провайдеры памяти (plugins/memory/)Обнаруживаются все; активен ровно один, выбранный через memory.provider в config.yaml.
Движки контекста (plugins/context_engine/)Обнаруживаются все; активен один, выбранный через context.engine в config.yaml.
Провайдеры моделей (plugins/model-providers/)Все встроенные провайдеры из plugins/model-providers/ обнаруживаются и регистрируются при первом вызове get_provider_profile(). Пользователь выбирает один за раз через --provider или config.yaml.
Плагины backend, установленные через pipПодключаются по выбору через plugins.enabled (как и обычные плагины).
Платформы, установленные пользователем~/.hermes/plugins/platforms/)Подключаются по выбору через plugins.enabled — сторонним адаптерам шлюза нужно явное согласие.

Если коротко: встроенная инфраструктура «всё-уже-работает» загружается сама; сторонние обычные плагины подключаются по выбору. Список разрешений plugins.enabled — это барьер именно для произвольного кода, который пользователь бросает в ~/.hermes/plugins/.

Миграция для тех, кто уже пользуется Hermes

Когда вы обновитесь до версии Hermes с подключаемыми по выбору плагинами (схема конфига v21+), все пользовательские плагины, уже установленные в ~/.hermes/plugins/ и не попавшие в plugins.disabled, автоматически переносятся в plugins.enabled. Привычная вам конфигурация продолжит работать. Встроенные standalone-плагины не переносятся — даже старым пользователям придётся подключить их явно. (Встроенным плагинам платформ и бэкендов перенос не требовался — их никогда не запирали барьером.)

Доступные хуки

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

ХукКогда срабатывает
pre_tool_callПеред выполнением любого инструмента
post_tool_callПосле того как любой инструмент вернул результат
pre_llm_callОдин раз за ход, перед циклом LLM — может вернуть {"context": "..."}, чтобы внедрить контекст в сообщение пользователя
post_llm_callОдин раз за ход, после цикла LLM (только при успешных ходах)
on_session_startСоздана новая сессия (только на первом ходе)
on_session_endКонец каждого вызова run_conversation + обработчик выхода из CLI
on_session_finalizeCLI или шлюз сворачивает активную сессию (/new, сборка мусора, выход из CLI)
on_session_resetШлюз подставляет новый ключ сессии (/new, /reset, /clear, ротация по простою)
subagent_stopОдин раз на каждого потомка после завершения delegate_task
pre_gateway_dispatchШлюз получил сообщение пользователя, до авторизации и диспетчеризации. Верните {"action": "skip" | "rewrite" | "allow", ...}, чтобы повлиять на ход обработки.

Виды плагинов

В Hermes четыре вида плагинов:

ТипЧто делаетВыборРасположение
Обычные плагиныДобавляют инструменты, хуки, слэш-команды, команды CLIМножественный выбор (включить/выключить)~/.hermes/plugins/
Провайдеры памятиЗаменяют или дополняют встроенную памятьЕдинственный выбор (активен один)plugins/memory/
Движки контекстаЗаменяют встроенный компрессор контекстаЕдинственный выбор (активен один)plugins/context_engine/
Провайдеры моделейОбъявляют бэкенд инференса (OpenRouter, Anthropic, …)Регистрируются во множестве, выбор через --provider / config.yamlplugins/model-providers/

Провайдеры памяти и движки контекста — это плагины-провайдеры: активен может быть только один экземпляр каждого типа. Провайдеры моделей тоже плагины, но их загружается сразу много; пользователь выбирает один за раз через --provider или config.yaml. Обычные плагины включаются в любом сочетании.

Подключаемые интерфейсы — куда идти за каждым

Таблица выше показывает четыре категории плагинов, но внутри «обычных плагинов» PluginContext открывает сразу несколько точек расширения — а ещё Hermes принимает расширения за пределами Python-системы плагинов (бэкенды на конфигах, команды через shell-хуки, внешние серверы и т. д.). По этой таблице найдёте нужную документацию под то, что хотите собрать:

Хочу добавить…КакРуководство по разработке
Инструмент, который сможет вызвать LLMPython-плагин — ctx.register_tool()Соберите плагин для Hermes · Добавление инструментов
Хук жизненного цикла (до/после LLM, начало/конец сессии, фильтр инструментов)Python-плагин — ctx.register_hook()Справочник по хукам · Соберите плагин для Hermes
Слэш-команду для CLI / шлюзаPython-плагин — ctx.register_command()Соберите плагин для Hermes · Расширение CLI
Подкоманду для hermes <thing>Python-плагин — ctx.register_cli_command()Расширение CLI
Встроенный навык, который поставляется с плагиномPython-плагин — ctx.register_skill()Создание навыков
Бэкенд инференса (провайдер LLM: OpenAI-compat, Codex, Anthropic-Messages, Bedrock)Плагин-провайдер — register_provider(ProviderProfile(...)) в plugins/model-providers/<name>/Плагины провайдеров моделей · Добавление провайдеров
Канал шлюза (Discord / Telegram / IRC / Teams / и т. д.)Плагин платформы — ctx.register_platform() в plugins/platforms/<name>/Добавление адаптеров платформ
Бэкенд памяти (Honcho, Mem0, Supermemory, …)Плагин памяти — наследник MemoryProvider в plugins/memory/<name>/Плагины провайдеров памяти
Стратегию сжатия контекстаПлагин движка контекста — ctx.register_context_engine()Плагины движка контекста
Бэкенд генерации изображений (DALL·E, SDXL, …)Плагин-бэкенд — ctx.register_image_gen_provider()Плагины провайдеров генерации изображений
Бэкенд генерации видео (Veo, Kling, Pixverse, Grok-Imagine, Runway, …)Плагин-бэкенд — ctx.register_video_gen_provider()Плагины провайдеров генерации видео
Бэкенд TTS (любой CLI — Piper, VoxCPM, Kokoro, xtts, скрипты клонирования голоса, …)На конфиге (рекомендуется) — объявите под tts.providers.<name> с type: command в config.yaml. ЛИБО Python-плагин-бэкенд — ctx.register_tts_provider() для движков на Python-SDK или потоковых, которым мало shell-шаблона.Настройка TTS · Руководство по Python-плагинам
Бэкенд STT (любой CLI — whisper.cpp, собственный бинарник whisper, локальный ASR-CLI)На конфиге (рекомендуется) — объявите под stt.providers.<name> с type: command в config.yaml или задайте HERMES_LOCAL_STT_COMMAND как старый запасной вариант с одной командой. ЛИБО Python-плагин-бэкенд — ctx.register_transcription_provider() для движков на Python-SDK (OpenRouter, SenseAudio, Gemini-STT и т. д.).Настройка STT · Руководство по Python-плагинам
Внешние инструменты через MCP (файловая система, GitHub, Linear, Notion, любой MCP-сервер)На конфиге — объявите mcp_servers.<name> с command: / url: в config.yaml. Hermes сам обнаружит инструменты сервера и зарегистрирует их рядом со встроенными.MCP
Дополнительные источники навыков (собственные GitHub-репозитории, приватные индексы навыков)CLI — hermes skills tap add <repo>Хаб навыков · Публикация собственного tap
Хуки событий шлюза (срабатывают на gateway:startup, session:start, agent:end, command:*)Бросьте HOOK.yaml + handler.py в ~/.hermes/hooks/<name>/Хуки событий
Shell-хуки (запускают shell-команду на событиях — уведомления, журналы аудита, оповещения на десктопе)На конфиге — объявите под hooks: в config.yamlShell-хуки
заметка

Не всё подряд оформлено как Python-плагин. Часть поверхностей расширения намеренно работает через shell-команды на конфиге (TTS, STT, shell-хуки) — так любой уже имеющийся у вас CLI становится плагином без единой строки Python. Другие — это внешние серверы (MCP), к которым агент подключается и сам регистрирует их инструменты. А некоторые — drop-in-каталоги (хуки шлюза) с собственным форматом манифеста. Выбирайте поверхность под тот стиль интеграции, что подходит вашей задаче; руководства по разработке из таблицы выше разбирают плейсхолдеры, обнаружение и примеры.

Декларативные плагины в NixOS

В NixOS плагины ставятся декларативно — через опции модуля, без hermes plugins install. Полное описание — в руководстве по настройке Nix.

services.hermes-agent = {
  # Directory plugin (source tree with plugin.yaml)
  extraPlugins = [ (pkgs.fetchFromGitHub { ... }) ];
  # Entry-point plugin (pip package)
  extraPythonPackages = [ (pkgs.python312Packages.buildPythonPackage { ... }) ];
  # Enable in config
  settings.plugins.enabled = [ "my-plugin" ];
};

Декларативные плагины подключаются симлинком с префиксом nix-managed- — они уживаются с плагинами, установленными вручную, и удаляются сами, как только их убирают из конфигурации Nix.

Управление плагинами

hermes plugins                               # единый интерактивный интерфейс
hermes plugins list                          # таблица: enabled / disabled / not enabled
hermes plugins install user/repo             # установить из Git, затем спросить Enable? [y/N]
hermes plugins install user/repo --enable    # установить И включить (без запроса)
hermes plugins install user/repo --no-enable # установить, но оставить выключенным (без запроса)
hermes plugins update my-plugin              # подтянуть свежую версию
hermes plugins remove my-plugin              # удалить
hermes plugins enable my-plugin              # добавить в список разрешений
hermes plugins disable my-plugin             # убрать из списка разрешений + добавить в disabled

Интерактивный интерфейс

Команда hermes plugins без аргументов открывает составной интерактивный экран:

Plugins
  ↑↓ navigate  SPACE toggle  ENTER configure/confirm  ESC done

  General Plugins
 → [✓] my-tool-plugin — Custom search tool
   [ ] webhook-notifier — Event hooks
   [ ] disk-cleanup — Auto-cleanup of ephemeral files [bundled]

  Provider Plugins
     Memory Provider          ▸ honcho
     Context Engine           ▸ compressor
  • Раздел General Plugins — флажки, переключаются пробелом. Отмечен = в plugins.enabled, снят = в plugins.disabled (явно выключен).
  • Раздел Provider Plugins — показывает текущий выбор. Нажмите ENTER, чтобы провалиться в radio-список и выбрать один активный провайдер.
  • Встроенные плагины стоят в том же списке с пометкой [bundled].

Выбор плагинов-провайдеров сохраняется в config.yaml:

memory:
  provider: "honcho"      # пустая строка = только встроенный

context:
  engine: "compressor"    # встроенный компрессор по умолчанию

Включён, выключен или ни то ни другое

У плагина бывает одно из трёх состояний:

СостояниеЧто означаетВ plugins.enabled?В plugins.disabled?
enabledЗагрузится в следующей сессииДаНет
disabledЯвно выключен — не загрузится, даже если заодно стоит в enabled(не важно)Да
not enabledОбнаружен, но к нему так и не подключилисьНетНет

Свежеустановленный или встроенный плагин по умолчанию получает состояние not enabled. Команда hermes plugins list показывает все три состояния по отдельности, так что видно, что отключили намеренно, а что просто ждёт включения.

В работающей сессии /plugins показывает, какие плагины загружены прямо сейчас.

Внедрение сообщений

Плагины умеют внедрять сообщения в активный диалог через ctx.inject_message():

ctx.inject_message("New data arrived from the webhook", role="user")

Сигнатура: ctx.inject_message(content: str, role: str = "user") -> bool

Как это работает:

  • Если агент простаивает (ждёт ввода пользователя), сообщение ставится в очередь как следующий ввод и начинает новый ход.
  • Если агент посреди хода (активно работает), сообщение прерывает текущую операцию — ровно как если бы пользователь набрал новое сообщение и нажал Enter.
  • Для ролей, отличных от "user", содержимое получает префикс [role] (например, [system] ...).
  • Возвращает True, если сообщение успешно поставлено в очередь, и False, если ссылки на CLI нет (например, в режиме шлюза).

Благодаря этому плагины вроде просмотрщиков удалённого управления, мостов для обмена сообщениями или приёмников вебхуков могут подавать сообщения в диалог из внешних источников.

заметка

inject_message доступен только в режиме CLI. В режиме шлюза ссылки на CLI нет, и метод возвращает False.

См. полное руководство — там разобраны контракты обработчиков, формат схемы, поведение хуков, обработка ошибок и типичные ошибки.

ESC