Настройка Matrix
Hermes Agent работает с Matrix — открытым федеративным протоколом обмена сообщениями. У Matrix есть приятное свойство: можно поднять собственный homeserver или подключиться к публичному вроде matrix.org, и в обоих случаях переписка остаётся под вашим контролем. Бот подключается через Python SDK mautrix, прогоняет сообщения через конвейер Hermes Agent (вызов инструментов, память, рассуждения) и отвечает в реальном времени. Поддерживаются текст, вложения, изображения, аудио, видео, а при желании — сквозное шифрование (E2EE).
Подойдёт любой homeserver — Synapse, Conduit, Dendrite или matrix.org.
Но сначала — то, что интересует большинство: как Hermes ведёт себя после подключения.
Как ведёт себя Hermes
| Контекст | Поведение |
|---|---|
| Личные сообщения (DM) | Hermes отвечает на каждое сообщение. @упоминание не требуется. У каждого DM своя сессия. Установите MATRIX_DM_MENTION_THREADS=true, чтобы при @упоминании бота в личке открывалась ветка. |
| Комнаты | По умолчанию для ответа Hermes нужно @упоминание. Установите MATRIX_REQUIRE_MENTION=false или добавьте ID комнат в MATRIX_FREE_RESPONSE_ROOMS, чтобы бот отвечал без упоминаний. Приглашения в комнаты принимаются автоматически. |
| Ветки (threads) | Hermes поддерживает ветки Matrix (MSC3440). Когда вы отвечаете в ветке, её контекст остаётся изолированным от основной ленты комнаты. В ветках, где бот уже участвовал, упоминание не нужно. |
| Автоветки | По умолчанию на каждое сообщение, на которое Hermes отвечает в комнате, он заводит отдельную ветку. Так разговоры не перемешиваются. Отключается через MATRIX_AUTO_THREAD=false. Поставьте MATRIX_DM_AUTO_THREAD=true (по умолчанию false), чтобы автоветки заводились и для личных сообщений — это не то же самое, что MATRIX_DM_MENTION_THREADS, который открывает ветку лишь при @упоминании бота в личке. |
| Команды | Hermes принимает обычные /команды, если их отправляет ваш Matrix-клиент. Когда клиент резервирует / под локальные команды, используйте !commands; Hermes приводит известные алиасы !command к виду /command. |
| Интерактивное управление | Подтверждение опасных команд и выбор модели через /model могут работать на реакциях Matrix. Реакции подтверждения можно ограничить тем пользователем, который запросил действие. |
| Размышления и работа инструментов | Когда включён прогресс шлюза, Matrix показывает размышления и активность инструментов в отдельных редактируемых панелях внутри ветки, чтобы обновления не засыпали основную ленту комнаты. |
| Общие комнаты с несколькими участниками | По умолчанию Hermes хранит историю сессий отдельно для каждого пользователя внутри комнаты. Два собеседника в одной комнате не делят общую переписку — пока вы явно не отключите это поведение. |
Бот автоматически входит в комнаты по приглашению. Просто пригласите его Matrix-пользователя в любую комнату — он зайдёт и начнёт отвечать.
Матрица возможностей
Таблица собрана из декларации возможностей адаптера Matrix и покрытия тестами. У E2EE три режима, потому что развёртывание само решает, как обходиться с зашифрованными комнатами: отключить их, включать по возможности или требовать обязательно.
| Возможность | Matrix |
|---|---|
| текст | да |
| ветки | да |
| реакции | да |
| подтверждения | да |
| выбор модели | да |
| панели размышлений | да |
| изображения | да |
| несколько изображений | да |
| файлы | да |
| голос/аудио | да |
| видео | да |
| E2EE | off / optional / required |
| диагностика | да |
Модель сессий в Matrix
По умолчанию:
- у каждого DM своя сессия
- у каждой ветки своё пространство имён сессий
- у каждого пользователя в общей комнате своя сессия внутри неё
Это задаётся в config.yaml:
group_sessions_per_user: true
Ставьте false только если вам действительно нужен один общий разговор на всю комнату:
group_sessions_per_user: false
Общие сессии бывают удобны для совместной работы в комнате, но у них есть оборотная сторона:
- участники делят разрастание контекста и расход токенов
- чья-то долгая задача с обилием вызовов инструментов раздувает контекст всем остальным
- незавершённый запуск одного человека может прервать уточнение другого в той же комнате
Настройка упоминаний и веток
Поведение упоминаний и автоведения веток настраивается через переменные окружения или config.yaml:
matrix:
require_mention: true # Require @mention in rooms (default: true)
allowed_users: # Matrix users allowed to trigger agent turns
- "@alice:matrix.org"
allowed_rooms: # Matrix rooms allowed to trigger agent turns
- "!abc123:matrix.org"
free_response_rooms: # Rooms exempt from mention requirement
- "!abc123:matrix.org"
ignore_user_patterns: # Bridge/appservice ghost users to ignore
- "^@telegram_"
- "^@whatsapp_"
process_notices: false # Ignore m.notice by default
session_scope: room # auto|room|thread; room is recommended for project rooms
auto_thread: true # Auto-create threads for responses (default: true)
dm_mention_threads: false # Create thread when @mentioned in DM (default: false)
Либо через переменные окружения:
MATRIX_REQUIRE_MENTION=true
MATRIX_ALLOWED_USERS=@alice:matrix.org
MATRIX_ALLOWED_ROOMS=!abc123:matrix.org
MATRIX_FREE_RESPONSE_ROOMS=!abc123:matrix.org,!def456:matrix.org
MATRIX_IGNORE_USER_PATTERNS='^@telegram_,^@whatsapp_'
MATRIX_PROCESS_NOTICES=false
MATRIX_SESSION_SCOPE=room # recommended for stable project-room context
MATRIX_AUTO_THREAD=true
MATRIX_DM_MENTION_THREADS=false
MATRIX_REACTIONS=true # default: true — emoji reactions during processing
MATRIX_ALLOW_ROOM_MENTIONS=false
MATRIX_REACTIONS=false выключает эмодзи-реакции жизненного цикла обработки (👀/✅/❌), которые бот ставит на входящие сообщения. Пригодится в комнатах, где события-реакции создают шум или их поддерживают не все участвующие клиенты.
Hermes отправляет структурированные упоминания Matrix для явных Matrix-ID вроде @alice:example.org. Уведомления на всю комнату через @room по умолчанию отключены; ставьте MATRIX_ALLOW_ROOM_MENTIONS=true только в тех комнатах, где боту позволено дёргать всех сразу.
Если вы обновляетесь с версии, где ещё не было MATRIX_REQUIRE_MENTION, раньше бот отвечал на все сообщения в комнатах. Чтобы сохранить прежнее поведение, установите MATRIX_REQUIRE_MENTION=false.
Изоляция проектных комнат
Если один и тот же Matrix-бот работает у вас в нескольких проектных комнатах, настройте стабильные сессии в привязке к комнате:
MATRIX_SESSION_SCOPE=room
MATRIX_AUTO_THREAD=false
MATRIX_SESSION_SCOPE принимает значения:
| Scope | Поведение |
|---|---|
auto | Поведение по умолчанию, совместимое со старым. Синтетическими ветками управляет прежняя настройка MATRIX_AUTO_THREAD. |
room | Сообщения комнаты вне веток остаются в одной стабильной сессии комнаты. Настоящие ветки Matrix по-прежнему используют свой корень ветки. |
thread | Для сообщений комнаты вне веток синтезируется ветка/сессия из ID события-триггера. |
Теперь Hermes добавляет в промпт агента текущее имя комнаты Matrix, её ID, тему, ID сообщения и пометку о границе комнаты Matrix. /status тоже показывает текущую комнату/scope сессии Matrix, а /resume не станет молча возобновлять именованную сессию из другой комнаты Matrix — для этого придётся явно указать /resume --cross-room <имя сессии>.
MATRIX_SESSION_SCOPE=room управляет дорожкой комнаты/ветки. Прежняя настройка group_sessions_per_user по-прежнему определяет, делят ли эту дорожку пользователи внутри комнаты. При group_sessions_per_user: true (по умолчанию) у Алисы и Боба будут отдельные сессии Project B. При group_sessions_per_user: false у комнаты одна общая переписка Project B.
Дальше — весь процесс настройки по шагам: от создания учётной записи бота до первого сообщения.
Шаг 1. Создайте учётную запись бота
Боту нужна отдельная учётная запись Matrix. Сделать её можно несколькими способами.
Вариант A. Регистрация на своём homeserver (рекомендуется)
Если у вас собственный homeserver (Synapse, Conduit, Dendrite):
- Создайте нового пользователя через admin API или утилиту регистрации:
# Synapse example
register_new_matrix_user -c /etc/synapse/homeserver.yaml http://localhost:8008
- Выберите имя вроде
hermes— полный User ID будет@hermes:your-server.org.
Вариант B. matrix.org или другой публичный homeserver
- Откройте Element Web и заведите новую учётную запись.
- Подберите имя для бота (например,
hermes-bot).
Вариант C. Своя учётная запись
Можно запустить Hermes и под собой. Тогда бот публикует сообщения от вашего имени — удобно для личного ассистента.
Шаг 2. Получите access-токен
Hermes нужен access-токен для аутентификации на homeserver. Есть два пути.
Вариант A. Access-токен (рекомендуется)
Самый надёжный способ получить токен.
Через Element:
- Войдите в Element под учётной записью бота.
- Откройте Settings → Help & About.
- Пролистайте вниз и разверните Advanced — там показан access-токен.
- Скопируйте его сразу.
Через API:
curl -X POST https://your-server/_matrix/client/v3/login \
-H "Content-Type: application/json" \
-d '{
"type": "m.login.password",
"user": "@hermes:your-server.org",
"password": "your-password"
}'
В ответе будет поле access_token — скопируйте его.
Access-токен даёт полный доступ к Matrix-аккаунту бота. Никогда не публикуйте его и не коммитьте в Git. Если токен утёк, отзовите его, выйдя из всех сессий этого пользователя.
Вариант B. Вход по паролю
Вместо access-токена можно передать Hermes User ID бота и пароль — при запуске он залогинится сам. Проще, но пароль будет храниться в файле .env.
MATRIX_USER_ID=@hermes:your-server.org
MATRIX_PASSWORD=your-password
Шаг 3. Найдите свой Matrix User ID
Hermes Agent опирается на ваш Matrix User ID, чтобы решать, кому разрешено общаться с ботом. Matrix User ID имеет формат @username:server.
Чтобы узнать свой:
- Откройте Element (или другой привычный Matrix-клиент).
- Кликните по аватару → Settings.
- User ID показан вверху профиля (например,
@alice:matrix.org).
Matrix User ID всегда начинается с @ и содержит :, после которого идёт имя сервера. Например: @alice:matrix.org, @bob:your-server.com.
Шаг 4. Настройте Hermes Agent
Вариант A. Интерактивная настройка (рекомендуется)
Запустите пошаговый помощник:
hermes gateway setup
Выберите Matrix, когда спросят, затем по запросу укажите URL homeserver, access-токен (или User ID и пароль) и список разрешённых User ID.
Вариант B. Ручная настройка
Добавьте в файл ~/.hermes/.env:
С access-токеном:
# Required
MATRIX_HOMESERVER=https://matrix.example.org
MATRIX_ACCESS_TOKEN=***
# Optional: user ID (auto-detected from token if omitted)
# MATRIX_USER_ID=@hermes:matrix.example.org
# Security: restrict who can interact with the bot
MATRIX_ALLOWED_USERS=@alice:matrix.example.org
# Optional: restrict which rooms can trigger the bot
MATRIX_ALLOWED_ROOMS=!abc123:matrix.example.org
# Multiple allowed users (comma-separated)
# MATRIX_ALLOWED_USERS=@alice:matrix.example.org,@bob:matrix.example.org
С входом по паролю:
# Required
MATRIX_HOMESERVER=https://matrix.example.org
MATRIX_USER_ID=@hermes:matrix.example.org
MATRIX_PASSWORD=***
# Security
MATRIX_ALLOWED_USERS=@alice:matrix.example.org
Усиление защиты для приватных развёртываний
Для приватных развёртываний Matrix задайте оба списка разрешений — и по пользователям, и по комнатам. Если MATRIX_ALLOWED_USERS не задан, агента сможет запустить любой отправитель, который дотянется до бота в общей комнате. Если не задан MATRIX_ALLOWED_ROOMS, агента сможет запустить любая комната, куда вошёл бот. В закрытом развёртывании нужно задать оба:
MATRIX_ALLOWED_USERS=@alice:matrix.example.org,@bob:matrix.example.org
MATRIX_ALLOWED_ROOMS=!ops:matrix.example.org,!dmroom:matrix.example.org
Развёртываниям с мостами и appservice нужна дополнительная защита от петель. Hermes по умолчанию игнорирует собственные события, пользователей в стиле appservice, чей localpart начинается с _, дубли ID событий, старые события при запуске, события-замены при редактировании и события m.notice. Добавьте паттерны ghost-пользователей под свой мост, если он использует другое соглашение об именах:
MATRIX_IGNORE_USER_PATTERNS='^@telegram_,^@slack_,^@whatsapp_'
Включайте обработку notice только тогда, когда m.notice действительно шлёт доверенный человеческий процесс:
MATRIX_PROCESS_NOTICES=true
Исходящие уведомления на всю комнату по умолчанию отключены. Держите MATRIX_ALLOW_ROOM_MENTIONS=false, пока боту явно не разрешено будить через @room всю комнату.
В диагностике и отладочных данных Matrix-токены, recovery-ключи, идентификаторы устройств и тела сообщений вымарываются. Загрузка медиа ограничена content-URI Matrix вида mxc:// и отклоняется при превышении MATRIX_MAX_MEDIA_BYTES. Считайте федеративные комнаты и недоверенные homeservers недоверенным вводом: держите списки разрешённых комнат узкими, для работы с обилием инструментов предпочитайте личку или приватные комнаты и не авторизуйте ghost-пользователей мостов или appservice-марионеток как разрешённых пользователей.
Дополнительные настройки поведения в ~/.hermes/config.yaml:
group_sessions_per_user: true
group_sessions_per_user: trueдержит контекст каждого участника изолированным внутри общих комнат
Запуск шлюза
После настройки запустите шлюз Matrix:
hermes gateway
За несколько секунд бот подключится к homeserver и начнёт синхронизацию. Напишите ему — в личку или в комнату, куда он вошёл, — чтобы проверить.
hermes gateway можно запускать в фоне или как systemd-сервис для постоянной работы. Подробности — в документации по развёртыванию.
Сквозное шифрование (E2EE)
Hermes поддерживает сквозное шифрование Matrix, так что с ботом можно переписываться в зашифрованных комнатах.
Требования
Для E2EE нужны библиотека mautrix с дополнениями для шифрования и C-библиотека libolm:
# Install mautrix with E2EE support
pip install 'mautrix[encryption]'
# Or install with hermes extras
pip install 'hermes-agent[matrix]'
Также в системе должна стоять libolm:
# Debian/Ubuntu
sudo apt install libolm-dev
# macOS
brew install libolm
# Fedora
sudo dnf install libolm-devel
Включение E2EE
Добавьте в ~/.hermes/.env:
MATRIX_E2EE_MODE=required
MATRIX_E2EE_MODE принимает значения:
| Режим | Поведение |
|---|---|
off | Не инициализировать E2EE в Matrix. |
optional | Пробовать E2EE, когда доступны зависимости, но оставлять незашифрованные комнаты рабочими, если крипто не запустилось. |
required | Падать с ошибкой, если зависимости E2EE или настройка крипто недоступны. |
В режиме optional при недоступной настройке крипто Hermes может откатиться к работе без E2EE. Режим required падает с ошибкой, а не тихо понижает уровень.
Ради обратной совместимости MATRIX_ENCRYPTION=true по-прежнему включает поведение обязательного E2EE.
Когда E2EE включено, Hermes:
- хранит ключи шифрования в
~/.hermes/platforms/matrix/store/(для старых установок:~/.hermes/matrix/store/) - выгружает ключи устройства при первом подключении
- автоматически расшифровывает входящие и шифрует исходящие сообщения
- автоматически входит в зашифрованные комнаты по приглашению
Инструменты и управление Matrix
В Matrix-разговорах Hermes даёт агенту специфичные для Matrix инструменты:
matrix_send_reactionmatrix_redact_messagematrix_create_roommatrix_invite_usermatrix_fetch_historymatrix_set_presence
Эти инструменты привязаны к контексту Matrix и в наборах инструментов для других платформ недоступны. Инструменты администраторского толка по умолчанию выключены: редактирование (redaction) требует MATRIX_TOOLS_ALLOW_REDACTION=true, приглашения — MATRIX_TOOLS_ALLOW_INVITES=true, создание комнат — MATRIX_TOOLS_ALLOW_ROOM_CREATE=true. Для создания публичных комнат вдобавок нужен MATRIX_ALLOW_PUBLIC_ROOMS=true.
По умолчанию инструменты Matrix ограничены текущей комнатой Matrix. Явные цели в других комнатах требуют MATRIX_TOOLS_ALLOW_CROSS_ROOM=true; для редактирования и действий вроде приглашений в чужих комнатах дополнительно нужен MATRIX_TOOLS_ALLOW_CROSS_ROOM_DESTRUCTIVE=true. Если задан MATRIX_ALLOWED_ROOMS, инструменты Matrix могут работать только с этими комнатами.
Управление реакциями:
- ✅ подтвердить один раз
- ♾️ подтверждать всегда
- ❌ отклонить
- реакции-числа для выбора в
/model
Поставьте MATRIX_APPROVAL_REQUIRE_SENDER=false, если вы сознательно хотите, чтобы запросом на подтверждение или выбором модели мог управлять любой авторизованный пользователь Matrix в комнате. По умолчанию это привязано к тому, кто запросил действие, — когда Hermes знает, кто его инициировал.
Лимиты на медиа
Hermes загружает и скачивает изображения, файлы, аудио и видео Matrix через медиа-API Matrix. Несколько сгенерированных изображений отправляются как один упорядоченный логический пакет, сохраняя подписи и контекст ветки по всему пакету.
По умолчанию медиа Matrix крупнее 100 МБ отклоняется до загрузки/скачивания. Поменять можно так:
MATRIX_MAX_MEDIA_BYTES=104857600
Входящее медиа должно использовать content-URI Matrix вида mxc://. Произвольные HTTP(S)-ссылки на медиа в событиях Matrix Hermes отклоняет, чтобы не превратить федеративную комнату в неограниченный загрузчик.
Интеграционные тесты с Synapse
В Hermes есть опциональный стенд на Synapse для локальной проверки:
docker compose -f tests/e2e/matrix_synapse_gateway/docker-compose.yml up -d
HERMES_MATRIX_SYNAPSE_INTEGRATION=1 \
scripts/run_tests.sh -m "integration and matrix_synapse" \
tests/e2e/matrix_synapse_gateway/test_gateway.py
docker compose -f tests/e2e/matrix_synapse_gateway/docker-compose.yml down -v
Стенд создаёт временных пользователей через регистрацию Synapse по общему секрету и покрывает отправку/приём в приватной комнате, приглашение/вход в именованную комнату, загрузку/скачивание медиа, доставку ответов бота и фильтрацию старых событий при запуске. Дымовое покрытие E2EE отмечено отдельно через matrix_e2ee, чтобы на машинах разработчиков оно оставалось опциональным.
Проверка кросс-подписью (рекомендуется)
Если на вашем Matrix-аккаунте включена кросс-подпись (в Element это поведение по умолчанию), задайте recovery-ключ, чтобы при запуске бот мог сам подписать своё устройство. Без этого другие Matrix-клиенты могут отказаться делиться с ботом сессиями шифрования после ротации ключей устройства.
MATRIX_RECOVERY_KEY=EsT... your recovery key here
Где его найти: в Element откройте Settings → Security & Privacy → Encryption → ваш recovery-ключ (он же «Security Key»). Это тот самый ключ, который вам предлагали сохранить при первой настройке кросс-подписи.
При каждом запуске, если задан MATRIX_RECOVERY_KEY, Hermes импортирует ключи кросс-подписи из защищённого secret storage homeserver и подписывает текущее устройство. Операция идемпотентна, её безопасно держать включённой постоянно.
Если Hermes сам создаёт новый recovery-ключ Matrix, в лог он этот ключ в открытом виде не пишет. Задайте перед запуском MATRIX_RECOVERY_KEY_OUTPUT_FILE=/secure/path/matrix-recovery-key.txt, чтобы сгенерированный ключ один раз записался в файл с правами 0600; существующий файл не перезаписывается.
Если удалить ~/.hermes/platforms/matrix/store/crypto.db, бот теряет свою криптографическую идентичность. Простой перезапуск с тем же device ID не восстановит её полностью — на homeserver остаются одноразовые ключи, подписанные старым ключом идентичности, и пиры не смогут установить новые Olm-сессии.
Hermes обнаруживает это при запуске и отказывается включать E2EE, записывая в лог: device XXXX has stale one-time keys on the server signed with a previous identity key.
Самый простой способ восстановления — сгенерировать новый access-токен (он получает свежий device ID без хвоста устаревших ключей). См. раздел «Обновление с предыдущей версии с E2EE» ниже. Это надёжнее всего и не требует трогать базу данных homeserver.
Восстановление вручную (для продвинутых — сохраняет тот же device ID):
-
Остановите Synapse и удалите старое устройство из его базы:
sudo systemctl stop matrix-synapse sudo sqlite3 /var/lib/matrix-synapse/homeserver.db " DELETE FROM e2e_device_keys_json WHERE device_id = 'DEVICE_ID' AND user_id = '@hermes:your-server'; DELETE FROM e2e_one_time_keys_json WHERE device_id = 'DEVICE_ID' AND user_id = '@hermes:your-server'; DELETE FROM e2e_fallback_keys_json WHERE device_id = 'DEVICE_ID' AND user_id = '@hermes:your-server'; DELETE FROM devices WHERE device_id = 'DEVICE_ID' AND user_id = '@hermes:your-server'; " sudo systemctl start matrix-synapseЛибо через Synapse admin API (обратите внимание на URL-кодированный User ID):
curl -X DELETE -H "Authorization: Bearer ADMIN_TOKEN" \ 'https://your-server/_synapse/admin/v2/users/%40hermes%3Ayour-server/devices/DEVICE_ID'Учтите: удаление устройства через admin API может заодно сделать недействительным связанный access-токен. Возможно, после этого придётся сгенерировать новый.
-
Удалите локальный crypto store и перезапустите Hermes:
rm -f ~/.hermes/platforms/matrix/store/crypto.db* # restart hermes
Другие Matrix-клиенты (Element, matrix-commander) могут кэшировать старые ключи устройства. После восстановления наберите в Element /discardsession, чтобы принудительно создать с ботом новую сессию шифрования.
Если mautrix[encryption] не установлен или отсутствует libolm, бот автоматически переходит на обычный (незашифрованный) клиент. В логах появится предупреждение.
Домашняя комната
Можно назначить «домашнюю комнату», куда бот шлёт сообщения по собственной инициативе (вывод cron-задач, напоминания, уведомления). Задать её можно двумя способами.
Через slash-команду
Наберите /sethome в любой Matrix-комнате, где есть бот. Эта комната станет домашней.
Если Matrix-клиент перехватывает slash-команды, используйте !sethome.
Ручная настройка
Добавьте в ~/.hermes/.env:
MATRIX_HOME_ROOM=!abc123def456:matrix.example.org
Список разрешённых комнат (allowed_rooms)
Ограничьте бота фиксированным набором Matrix-комнат. Когда параметр задан, бот отвечает только в комнатах, чей ID есть в списке — сообщения из любых других комнат молча игнорируются, даже если бота упомянули.
Личные чаты (DM) под этот фильтр не попадают, поэтому авторизованные пользователи всегда могут связаться с ботом один на один.
matrix:
allowed_rooms:
- "!abc123def456:matrix.example.org"
- "!opsroom789:matrix.example.org"
Либо через переменную окружения (через запятую):
MATRIX_ALLOWED_ROOMS="!abc123def456:matrix.example.org,!opsroom789:matrix.example.org"
Поведение:
- Пусто / не задано → без ограничений (по умолчанию).
- Не пусто → ID комнаты должен быть в списке. Проверка выполняется раньше всех остальных фильтров (требование упоминания, список разрешённых отправителей и т. д.).
- Используйте внутренний ID комнаты (
!abc...:server), а не её алиас (#room:server). Внутренний ID комнаты в Element смотрят через Room → Settings → Advanced.
См. также: разделение slash-команд на admin и user.
Как найти Room ID: в Element откройте комнату → Settings → Advanced → там показан Internal room ID (начинается с !).
Команды в Matrix
В Matrix Hermes поддерживает те же команды шлюза, что и на других платформах сообщений, включая /commands, /model, /stop, /queue, /steer, /goal, /subgoal, /background, /bg, /btw, /tasks и /yolo.
Некоторые Matrix-клиенты резервируют ведущий / под собственные локальные команды и могут не отправлять в комнату неизвестные slash-команды. На такой случай есть безопасный для Matrix алиас !:
!commands
!model
!model gpt-5.5 --provider openrouter
!queue continue with the next task
!stop
Hermes нормализует !command только тогда, когда команда известна шлюзу, зарегистрирована плагином или относится к установленному навыку. Обычные восклицания вроде !important остаются обычными сообщениями чата.
Устранение неполадок
Бот не отвечает на сообщения
Причина: бот не вошёл в комнату, вашего User ID нет в MATRIX_ALLOWED_USERS, комнаты нет в MATRIX_ALLOWED_ROOMS или в сообщении из комнаты не было упоминания бота.
Решение: пригласите бота в комнату — по приглашению он входит автоматически. Убедитесь, что ваш User ID есть в MATRIX_ALLOWED_USERS (в полном формате @user:server), а ID комнаты — в MATRIX_ALLOWED_ROOMS, если этот список задан. В комнатах упоминайте бота или добавьте комнату в MATRIX_FREE_RESPONSE_ROOMS. Перезапустите шлюз.
Бот входит в комнаты, но молча теряет каждое сообщение (рассинхрон часов)
Причина: системные часы хоста идут впереди реального времени. Адаптер Matrix применяет 5-секундный стартовый фильтр-послабление (event_ts < startup_ts - 5), чтобы игнорировать события, которые приходят повторно при первичной синхронизации. Когда часы спешат, каждое входящее событие выглядит «старше запуска» и отбрасывается до того, как дойдёт до обработчика — бот вроде бы подключён, но никогда не отвечает. См. #12614.
Симптом: в логе шлюза появляется Matrix: dropped N live events as 'too old' more than 30s after startup.
Решение: синхронизируйте часы хоста по NTP и перезапустите бота:
# Debian/Ubuntu
sudo timedatectl set-ntp true
timedatectl status # confirm "System clock synchronized: yes"
# macOS
sudo sntp -sS time.apple.com
«Failed to authenticate» / «whoami failed» при запуске
Причина: неверный access-токен или URL homeserver.
Решение: проверьте, что MATRIX_HOMESERVER указывает на ваш homeserver (с https://, без завершающего слеша). Убедитесь, что MATRIX_ACCESS_TOKEN действителен — проверьте через curl:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://your-server/_matrix/client/v3/account/whoami
Если в ответе пришли данные о пользователе — токен рабочий. Если ошибка — сгенерируйте новый.
Ошибка «mautrix not installed»
Причина: не установлен Python-пакет mautrix.
Решение: установите его:
pip install 'mautrix[encryption]'
Либо с дополнениями Hermes:
pip install 'hermes-agent[matrix]'
Ошибки шифрования / «could not decrypt event»
Причина: нет ключей шифрования, не установлена libolm или устройству бота не доверяют.
Решение:
- Проверьте, что в системе стоит
libolm(см. раздел про E2EE выше). - Убедитесь, что в
.envзаданоMATRIX_ENCRYPTION=true. - В своём Matrix-клиенте (Element) откройте профиль бота -> Sessions -> подтвердите/доверьтесь устройству бота.
- Если бот только что вошёл в зашифрованную комнату, он может расшифровать только сообщения, отправленные после входа. Старые сообщения недоступны.
Обновление с предыдущей версии с E2EE
Если вы вдобавок вручную удаляли crypto.db, загляните в предупреждение «Удаление crypto store» в разделе E2EE выше — там есть дополнительные шаги, чтобы убрать устаревшие одноразовые ключи с homeserver.
Если раньше вы использовали Hermes с MATRIX_ENCRYPTION=true и обновляетесь до версии с новым crypto store на базе SQLite, криптографическая идентичность бота изменилась. Ваш Matrix-клиент (Element) может кэшировать старые ключи устройства и отказываться делиться с ботом сессиями шифрования.
Симптомы: бот подключается, в логах видно «E2EE enabled», но все сообщения показывают «could not decrypt event», и бот не отвечает.
Что происходит: старое состояние шифрования (от прежнего бэкенда matrix-nio или сериализационного mautrix) несовместимо с новым crypto store на SQLite. Бот создаёт свежую криптографическую идентичность, но у вашего Matrix-клиента ещё закэшированы старые ключи, и он не отдаёт сессию шифрования комнаты устройству, у которого ключи поменялись. Так устроена защита Matrix — клиенты считают подозрительной смену ключей идентичности у одного и того же устройства.
Решение (разовая миграция):
-
Сгенерируйте новый access-токен, чтобы получить свежий device ID. Проще всего так:
curl -X POST https://your-server/_matrix/client/v3/login \ -H "Content-Type: application/json" \ -d '{ "type": "m.login.password", "identifier": {"type": "m.id.user", "user": "@hermes:your-server.org"}, "password": "***", "initial_device_display_name": "Hermes Agent" }'Скопируйте новый
access_tokenи обновитеMATRIX_ACCESS_TOKENв~/.hermes/.env. -
Удалите старое состояние шифрования:
rm -f ~/.hermes/platforms/matrix/store/crypto.db rm -f ~/.hermes/platforms/matrix/store/crypto_store.* -
Задайте recovery-ключ (если используете кросс-подпись — а большинство пользователей Element используют). Добавьте в
~/.hermes/.env:MATRIX_RECOVERY_KEY=EsT... your recovery key hereТак бот при запуске сам подпишется ключами кросс-подписи, и Element сразу начнёт доверять новому устройству. Без этого Element может счесть новое устройство непроверенным и не делиться сессиями шифрования. Recovery-ключ ищите в Element в Settings → Security & Privacy → Encryption.
-
Заставьте Matrix-клиент сменить сессию шифрования. В Element откройте личную комнату с ботом и наберите
/discardsession. Это вынудит Element создать новую сессию шифрования и поделиться ею с новым устройством бота. -
Перезапустите шлюз:
hermes gateway runЕсли
MATRIX_RECOVERY_KEYзадан, в логах должно появитьсяMatrix: cross-signing verified via recovery key. -
Отправьте новое сообщение. Бот должен расшифровать его и ответить как обычно.
После миграции сообщения, отправленные до обновления, расшифровать нельзя — старые ключи шифрования утрачены. Это касается только перехода; новые сообщения работают нормально.
Новых установок это не касается. Миграция нужна, только если у вас была рабочая настройка E2EE на прежней версии Hermes и вы обновляетесь.
Зачем новый access-токен? Каждый Matrix access-токен привязан к конкретному device ID. Переиспользование того же device ID с новыми ключами шифрования заставляет другие Matrix-клиенты перестать доверять устройству (смену ключей идентичности они воспринимают как возможный взлом). Новый access-токен получает новый device ID без хвоста устаревших ключей, поэтому другие клиенты доверяют ему сразу.
Режим прокси (E2EE на macOS)
E2EE в Matrix требует libolm, а она не собирается на macOS ARM64 (Apple Silicon). Дополнение hermes-agent[matrix] доступно только под Linux. Если вы на macOS, режим прокси позволяет крутить E2EE в Docker-контейнере на Linux-виртуалке, тогда как сам агент работает нативно на macOS с полным доступом к локальным файлам, памяти и навыкам.
Как это работает
macOS (Host):
└─ hermes gateway
├─ api_server adapter ← listens on 0.0.0.0:8642
├─ AIAgent ← single source of truth
├─ Sessions, memory, skills
└─ Local file access (Obsidian, projects, etc.)
Linux VM (Docker):
└─ hermes gateway (proxy mode)
├─ Matrix adapter ← E2EE decryption/encryption
└─ HTTP forward → macOS:8642/v1/chat/completions
(no LLM API keys, no agent, no inference)
Docker-контейнер занимается только протоколом Matrix и E2EE. Когда приходит сообщение, он расшифровывает его и пересылает текст на хост обычным HTTP-запросом. Хост запускает агента, вызывает инструменты, формирует ответ и стримит его обратно. Контейнер шифрует ответ и отправляет в Matrix. Все сессии едины — CLI, Matrix, Telegram и любая другая платформа делят одну память и общую историю переписки.
Шаг 1. Настройте хост (macOS)
Включите API-сервер, чтобы хост принимал входящие запросы от Docker-контейнера.
Добавьте в ~/.hermes/.env:
API_SERVER_ENABLED=true
API_SERVER_KEY=your-secret-key-here
API_SERVER_HOST=0.0.0.0
API_SERVER_HOST=0.0.0.0привязывается ко всем интерфейсам, чтобы до него дотянулся Docker-контейнер.API_SERVER_KEYобязателен для привязки не к loopback. Возьмите длинную случайную строку.- API-сервер по умолчанию слушает порт 8642 (меняется через
API_SERVER_PORT).
Запустите шлюз:
hermes gateway
Вы должны увидеть, как API-сервер стартует вместе с прочими настроенными платформами. Проверьте доступность с виртуалки:
# From the Linux VM
curl http://<mac-ip>:8642/health
Шаг 2. Настройте Docker-контейнер (Linux VM)
Контейнеру нужны учётные данные Matrix и URL прокси. Ключи к LLM API ему НЕ нужны.
docker-compose.yml:
services:
hermes-matrix:
build: .
environment:
# Matrix credentials
MATRIX_HOMESERVER: "https://matrix.example.org"
MATRIX_ACCESS_TOKEN: "syt_..."
MATRIX_ALLOWED_USERS: "@you:matrix.example.org"
MATRIX_ENCRYPTION: "true"
MATRIX_DEVICE_ID: "HERMES_BOT"
# Proxy mode — forward to host agent
GATEWAY_PROXY_URL: "http://192.168.1.100:8642"
GATEWAY_PROXY_KEY: "your-secret-key-here"
volumes:
- ./matrix-store:/root/.hermes/platforms/matrix/store
Dockerfile:
FROM python:3.11-slim
RUN apt-get update && apt-get install -y libolm-dev && rm -rf /var/lib/apt/lists/*
RUN pip install 'hermes-agent[matrix]'
CMD ["hermes", "gateway"]
Вот и весь контейнер. Никаких ключей к OpenRouter, Anthropic или любому другому провайдеру инференса.
Шаг 3. Запустите обе части
-
Сначала запустите шлюз на хосте:
hermes gateway -
Запустите Docker-контейнер:
docker compose up -d -
Напишите сообщение в зашифрованной Matrix-комнате. Контейнер расшифрует его, перешлёт на хост и стримит ответ обратно.
Справочник по настройкам
Режим прокси настраивается на стороне контейнера (тонкий шлюз):
| Настройка | Описание |
|---|---|
GATEWAY_PROXY_URL | URL удалённого API-сервера Hermes (например, http://192.168.1.100:8642) |
GATEWAY_PROXY_KEY | Bearer-токен для аутентификации (должен совпадать с API_SERVER_KEY на хосте) |
gateway.proxy_url | То же, что GATEWAY_PROXY_URL, но в config.yaml |
На стороне хоста нужны:
| Настройка | Описание |
|---|---|
API_SERVER_ENABLED | Установить в true |
API_SERVER_KEY | Bearer-токен (общий с контейнером) |
API_SERVER_HOST | Установить в 0.0.0.0 для доступа по сети |
API_SERVER_PORT | Номер порта (по умолчанию: 8642) |
Работает для любой платформы
Режим прокси не ограничен Matrix. Им может пользоваться любой адаптер платформы — задайте GATEWAY_PROXY_URL на любом экземпляре шлюза, и тот будет перенаправлять запросы удалённому агенту вместо локального. Удобно для любого развёртывания, где адаптер платформы должен работать в иной среде, чем агент (сетевая изоляция, требования E2EE, ограничения по ресурсам).
Непрерывность сессии держится на заголовке X-Hermes-Session-Id. API-сервер хоста отслеживает сессии по этому ID, поэтому разговоры сохраняются между сообщениями ровно так же, как с локальным агентом.
Ограничения (v1): сообщения о ходе работы инструментов от удалённого агента обратно не транслируются — пользователь видит только финальный стримящийся ответ, без отдельных вызовов инструментов. Запросы на подтверждение опасных команд обрабатываются на стороне хоста и не доходят до пользователя Matrix. В будущих обновлениях это можно поправить.
Бот подключается и отправляет, но игнорирует входящие
Причина: обработчики событий Matrix срабатывают, только когда полезная нагрузка синхронизации проходит через механизм handle_sync() из mautrix. Голый опрос client.sync(), который ни разу не вызывает handle_sync(), может оставить адаптер подключённым (отправка работает), тогда как входящие сообщения так и не доходят до _on_room_message.
Решение: Hermes использует явный цикл синхронизации, который вызывает client.handle_sync() и на первичной синхронизации, и на каждом инкрементальном ответе. Это совпадает с диагнозом из апстрим-issue #7914 и закрытого PR #37807, но при этом сохраняет собственные фоновые задачи обслуживания Hermes (учёт комнат, в которые он вошёл, обработка приглашений, обмен ключами E2EE) вместо передачи всего жизненного цикла в client.start(). Если после перезапуска шлюза входящие всё ещё не приходят, проверьте, что обработчики зарегистрированы до первой синхронизации, и поищите в логах sync event dispatch error.
Проблемы синхронизации / бот отстаёт
Причина: долгие запуски инструментов могут тормозить цикл синхронизации, либо медленно отвечает homeserver.
Решение: цикл синхронизации сам повторяет попытку каждые 5 секунд при ошибке. Поищите в логах Hermes предупреждения про sync. Если бот стабильно отстаёт, убедитесь, что у homeserver достаточно ресурсов.
Бот не в сети
Причина: шлюз Hermes не запущен или не смог подключиться.
Решение: проверьте, что hermes gateway работает. Посмотрите вывод в терминале на предмет ошибок. Частые причины: неверный URL homeserver, истёкший access-токен, недоступный homeserver.
«User not allowed» / Бот вас игнорирует
Причина: вашего User ID нет в MATRIX_ALLOWED_USERS.
Решение: добавьте свой User ID в MATRIX_ALLOWED_USERS в ~/.hermes/.env и перезапустите шлюз. Указывайте полный формат @user:server.
Бот игнорирует целую комнату
Причина: задан MATRIX_ALLOWED_ROOMS, а ID текущей комнаты в нём нет; либо комната требует упоминания, а в сообщении бота не упомянули.
Решение: добавьте ID комнаты в MATRIX_ALLOWED_ROOMS или уберите список разрешённых комнат, если это личное развёртывание. Чтобы найти Room ID в Element, откройте настройки комнаты и загляните в Advanced.
Сообщения моста зацикливаются или эхом возвращаются
Причина: марионетка моста/appservice возвращает вывод бота как новое пользовательское сообщение, либо мост использует нестандартные ID ghost-пользователей.
Решение: держите ghost-пользователей моста вне MATRIX_ALLOWED_USERS, добавьте подходящую запись в MATRIX_IGNORE_USER_PATTERNS и оставьте MATRIX_PROCESS_NOTICES=false, пока notice не станут частью доверенного процесса.
Безопасность
Всегда задавайте MATRIX_ALLOWED_USERS, а для общих и приватных развёртываний — ещё и MATRIX_ALLOWED_ROOMS. Без них агента может запустить любой, кто способен написать боту в общей комнате. Авторизуйте только тех людей и те комнаты, которым доверяете: у авторизованных пользователей есть полный доступ к возможностям агента, включая вызов инструментов и доступ к системе.
Подробнее о защите развёртывания Hermes Agent — в руководстве по безопасности.
Заметки
- Любой homeserver: работает с Synapse, Conduit, Dendrite, matrix.org или любым homeserver, соответствующим спецификации Matrix. Конкретное серверное ПО не требуется.
- Федерация: на федеративном homeserver бот может общаться с пользователями других серверов — достаточно добавить их полные ID
@user:serverвMATRIX_ALLOWED_USERS. - Автовход: бот сам принимает приглашения и входит в комнаты. Отвечать он начинает сразу после входа.
- Поддержка медиа: Hermes умеет отправлять и принимать изображения, аудио, видео и файловые вложения. Медиа загружаются на ваш homeserver через Matrix content repository API.
- Нативные голосовые сообщения (MSC3245): адаптер Matrix автоматически помечает исходящие голосовые сообщения флагом
org.matrix.msc3245.voice. Благодаря этому ответы TTS и голосовое аудио отображаются как нативные голосовые пузырьки в Element и других клиентах с поддержкой MSC3245, а не как обычные аудиовложения. Входящие голосовые сообщения с флагом MSC3245 тоже корректно распознаются и направляются в транскрипцию speech-to-text. Настраивать ничего не нужно — всё работает автоматически.