Плагины
В 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) — запускает зарегистрированный инструмент с автоматически подключённым контекстом родительского агента |
| Добавить команды CLI | ctx.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) |
| pip | entry_points hermes_agent.plugins | Распространяемые пакеты |
| Nix | services.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_finalize | CLI или шлюз сворачивает активную сессию (/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.yaml | plugins/model-providers/ |
Провайдеры памяти и движки контекста — это плагины-провайдеры: активен может быть только один экземпляр каждого типа. Провайдеры моделей тоже плагины, но их загружается сразу много; пользователь выбирает один за раз через --provider или config.yaml. Обычные плагины включаются в любом сочетании.
Подключаемые интерфейсы — куда идти за каждым
Таблица выше показывает четыре категории плагинов, но внутри «обычных плагинов» PluginContext открывает сразу несколько точек расширения — а ещё Hermes принимает расширения за пределами Python-системы плагинов (бэкенды на конфигах, команды через shell-хуки, внешние серверы и т. д.). По этой таблице найдёте нужную документацию под то, что хотите собрать:
| Хочу добавить… | Как | Руководство по разработке |
|---|---|---|
| Инструмент, который сможет вызвать LLM | Python-плагин — 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.yaml | Shell-хуки |
Не всё подряд оформлено как 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.
См. полное руководство — там разобраны контракты обработчиков, формат схемы, поведение хуков, обработка ошибок и типичные ошибки.