Настройка Signal

Hermes подключается к Signal через демон signal-cli, запущенный в режиме HTTP. Адаптер получает сообщения в реальном времени по SSE (Server-Sent Events), а ответы отправляет через JSON-RPC.

Среди массовых мессенджеров Signal больше всех заботится о приватности: сквозное шифрование по умолчанию, открытый протокол, минимум собираемых метаданных. Для агентских сценариев, где безопасность критична, это удачный выбор.

инфо
Никаких новых зависимостей Python

Для всего обмена данными адаптер Signal использует httpx — он уже входит в ядро зависимостей Hermes. Дополнительных пакетов Python ставить не нужно. Понадобится лишь установить signal-cli отдельно.


Что понадобится

  • signal-cli — клиент Signal на Java (GitHub)
  • среда выполнения Java 17+ — её требует signal-cli
  • номер телефона с установленным Signal (чтобы привязать как вторичное устройство)

Установка signal-cli

# macOS
brew install signal-cli

# Linux (download latest release)
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} \
  https://github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//')
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz"
sudo tar xf "signal-cli-${VERSION}.tar.gz" -C /opt
sudo ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/
осторожно

В репозиториях apt и snap signal-cli отсутствует. Команды для Linux выше скачивают его напрямую из релизов на GitHub.


Шаг 1. Привяжите аккаунт Signal

signal-cli работает как привязанное устройство — по принципу WhatsApp Web, только для Signal. Телефон при этом остаётся основным устройством.

# Generate a linking URI (displays a QR code or link)
signal-cli link -n "HermesAgent"
  1. Откройте Signal на телефоне
  2. Перейдите в Settings → Linked Devices
  3. Нажмите Link New Device
  4. Отсканируйте QR-код или введите URI

Шаг 2. Запустите демон signal-cli

# Replace +1234567890 with your Signal phone number (E.164 format)
signal-cli --account +1234567890 daemon --http 127.0.0.1:8080
совет

Пусть процесс работает в фоне. Подойдут systemd, tmux, screen или запуск в виде службы.

Проверьте, что демон запущен:

curl http://127.0.0.1:8080/api/v1/check
# Should return: {"versions":{"signal-cli":...}}

Шаг 3. Настройте Hermes

Самый простой путь:

hermes gateway setup

Выберите в меню платформ Signal. Мастер настройки:

  1. проверит, установлен ли signal-cli
  2. спросит HTTP-URL (по умолчанию http://127.0.0.1:8080)
  3. протестирует связь с демоном
  4. запросит номер телефона вашего аккаунта
  5. настроит список разрешённых пользователей и политики доступа

Ручная настройка

Добавьте в ~/.hermes/.env:

# Required
SIGNAL_HTTP_URL=http://127.0.0.1:8080
SIGNAL_ACCOUNT=+1234567890

# Security (recommended)
SIGNAL_ALLOWED_USERS=+1234567890,+0987654321    # Comma-separated E.164 numbers or UUIDs

# Optional
SIGNAL_GROUP_ALLOWED_USERS=groupId1,groupId2     # Enable groups (omit to disable, * for all)
SIGNAL_HOME_CHANNEL=+1234567890                  # Default delivery target for cron jobs

После этого запустите шлюз:

hermes gateway              # Foreground
hermes gateway install      # Install as a user service
sudo hermes gateway install --system   # Linux only: boot-time system service

Контроль доступа

Доступ к личным сообщениям

Доступ к личным сообщениям устроен так же, как на остальных платформах Hermes:

  1. SIGNAL_ALLOWED_USERS задан → писать могут только перечисленные пользователи
  2. список разрешений не задан → незнакомый пользователь получает код сопряжения в личке (подтвердите его командой hermes pairing approve signal CODE)
  3. SIGNAL_ALLOW_ALL_USERS=true → писать может кто угодно (используйте с осторожностью)

Доступ к группам

Группами управляет переменная окружения SIGNAL_GROUP_ALLOWED_USERS:

КонфигурацияПоведение
Не задана (по умолчанию)Все групповые сообщения игнорируются. Бот отвечает только в личке.
Заданы ID группОтслеживаются лишь перечисленные группы (например, groupId1,groupId2).
Значение *Бот отвечает в любой группе, участником которой состоит.

Возможности

Вложения

Адаптер умеет принимать и отправлять медиафайлы в обе стороны.

Входящие (пользователь → агент):

  • Изображения — PNG, JPEG, GIF, WebP (тип определяется по сигнатуре файла)
  • Аудио — MP3, OGG, WAV, M4A (голосовые сообщения расшифровываются, если настроен Whisper)
  • Документы — PDF, ZIP и другие форматы файлов

Исходящие (агент → пользователь):

Агент отправляет медиафайлы через теги MEDIA: в ответах. Доступны такие способы доставки:

  • Изображенияsend_multiple_images и send_image_file отправляют PNG, JPEG, GIF, WebP как нативные вложения Signal
  • Голосsend_voice отправляет аудиофайлы (OGG, MP3, WAV, M4A, AAC) вложениями
  • Видеоsend_video отправляет видеофайлы MP4
  • Документыsend_document отправляет файл любого типа (PDF, ZIP и т. д.)

Все исходящие медиа идут через стандартный API вложений Signal. В отличие от ряда других платформ, Signal на уровне протокола не разделяет голосовые сообщения и файловые вложения.

Лимит размера вложения — 100 МБ (в обе стороны).

внимание

Серверы Signal ограничивают скорость загрузки вложений: при отправке нескольких изображений адаптер задействует планировщик, который разбивает их на партии по 32 штуки и придерживает выгрузку под политику серверов Signal.

Нативное форматирование, цитаты в ответах и реакции

Сообщения в Signal отображаются с нативным форматированием, а не сырыми символами markdown. Адаптер переводит markdown (**bold**, *italic*, `code`, ~~strike~~, ||spoiler||, заголовки) в bodyRanges Signal — и текст приходит получателю уже со стилями, без видимых ** или `.

Цитаты в ответах. Когда Hermes отвечает на конкретное сообщение, он теперь оформляет нативный ответ-цитату — тот самый интерфейс, который пользователи Signal видят, нажимая «Reply» сами. Для ответов на входящие сообщения это происходит автоматически.

Реакции. Агент может реагировать на сообщения через стандартный API реакций; в Signal они появляются как эмодзи-реакции на упомянутом сообщении, а не отдельным текстом.

Ничего из этого настраивать не нужно — в свежих сборках signal-cli всё включено по умолчанию. Если версия signal-cli слишком старая, Hermes откатывается на доставку обычным текстом и один раз пишет предупреждение в лог.

Индикаторы набора

Пока бот обрабатывает сообщение, он показывает индикатор набора текста и обновляет его каждые 8 секунд.

Отображение прогресса инструментов

Signal не поддерживает редактирование уже отправленных сообщений. Поэтому Hermes не показывает всплывающие пузыри прогресса вызова инструментов в Signal — даже если включён режим /verbose и для платформы сохранён режим, отличный от off.

Активность инструментов по-прежнему видна в CLI, а итоговые ответы в Signal содержат обычный вывод агента. Если нужен прогресс по каждому инструменту прямо в чате — используйте платформу с поддержкой редактирования сообщений.

Скрытие номеров телефонов

В логах все номера телефонов скрываются автоматически:

  • +15551234567+155****4567
  • Это касается и логов шлюза Hermes, и глобальной системы редактирования

Заметки себе (настройка на одном номере)

Если вы запускаете signal-cli как привязанное вторичное устройство на собственном номере (а не на отдельном номере для бота), то общаться с Hermes можно через функцию Signal «Note to Self».

Просто отправьте сообщение самому себе с телефона — signal-cli его подхватит, и Hermes ответит в той же переписке.

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

  • сообщения «Note to Self» приходят как конверты syncMessage.sentMessage
  • адаптер распознаёт те из них, что адресованы собственному аккаунту бота, и обрабатывает их как обычные входящие
  • защита от эха (отслеживание timestamp отправленных сообщений) не даёт зациклиться — ответы самого бота отфильтровываются автоматически

Дополнительная настройка не нужна. Всё работает само, пока SIGNAL_ACCOUNT совпадает с вашим номером телефона.

Контроль состояния

Адаптер следит за SSE-соединением и автоматически переподключается, если:

  • соединение разорвалось (с экспоненциальной задержкой: 2 с → 60 с)
  • активности нет в течение 120 секунд (тогда адаптер пингует signal-cli для проверки)

Решение проблем

ПроблемаРешение
«Cannot reach signal-cli» при настройкеУбедитесь, что демон signal-cli запущен: signal-cli --account +YOUR_NUMBER daemon --http 127.0.0.1:8080
Сообщения не приходятПроверьте, что SIGNAL_ALLOWED_USERS содержит номер отправителя в формате E.164 (с префиксом +)
«signal-cli not found on PATH»Установите signal-cli и добавьте его в PATH либо используйте Docker
Соединение постоянно рвётсяЗагляните в логи signal-cli на предмет ошибок. Убедитесь, что установлена Java 17+.
Групповые сообщения игнорируютсяЗадайте SIGNAL_GROUP_ALLOWED_USERS с конкретными ID групп или *, чтобы разрешить все группы.
Бот никому не отвечаетЗадайте SIGNAL_ALLOWED_USERS, используйте сопряжение в личке или явно разрешите всех пользователей через политику шлюза, если нужен более широкий доступ.
Дублирующиеся сообщенияУбедитесь, что на вашем номере слушает только один экземпляр signal-cli

Безопасность

внимание

Всегда настраивайте контроль доступа. По умолчанию у бота есть доступ к терминалу. Без SIGNAL_ALLOWED_USERS или сопряжения в личке шлюз из соображений безопасности отклоняет все входящие сообщения.

  • Номера телефонов скрываются во всём выводе логов
  • Для безопасного подключения новых пользователей применяйте сопряжение в личке или явные списки разрешений
  • Держите группы выключенными, пока поддержка групп вам реально не нужна, либо вносите в список разрешений только те группы, которым доверяете
  • Сквозное шифрование Signal защищает содержимое сообщений при передаче
  • Данные сессии signal-cli в ~/.local/share/signal-cli/ содержат учётные данные аккаунта — берегите их как пароль

Справочник переменных окружения

ПеременнаяОбязательнаПо умолчаниюОписание
SIGNAL_HTTP_URLДаHTTP-эндпоинт signal-cli
SIGNAL_ACCOUNTДаНомер телефона бота (E.164)
SIGNAL_ALLOWED_USERSНетНомера телефонов/UUID через запятую
SIGNAL_GROUP_ALLOWED_USERSНетID групп для отслеживания или * для всех (без значения группы отключены)
SIGNAL_ALLOW_ALL_USERSНетfalseРазрешить взаимодействие любому пользователю (пропустить список разрешений)
SIGNAL_HOME_CHANNELНетЦель доставки по умолчанию для cron-задач
ESC