Mainstream messaging
Signal
Статус: внешняя интеграция с CLI. Gateway взаимодействует с signal-cli по HTTP — через нативный демон (JSON-RPC + SSE) или контейнер bbernhard/signal-cli-rest-api (REST + WebSocket).
Предварительные требования
- OpenClaw установлен на вашем сервере (поток для Linux ниже протестирован на Ubuntu 24).
- Один из вариантов:
signal-cliдоступен на хосте (нативный режим), или- Docker-контейнер
bbernhard/signal-cli-rest-api(контейнерный режим).
- Номер телефона, который может получить одно проверочное SMS (для регистрации через SMS).
- Доступ к браузеру для капчи Signal (
signalcaptchas.org) во время регистрации.
Быстрая настройка (для начинающих)
- Используйте отдельный номер Signal для бота (рекомендуется).
- Установите Plugin OpenClaw:
openclaw plugins install @openclaw/signal- Установите
signal-cli(если используете сборку JVM, требуется Java). - Выберите один путь настройки:
- Путь A (привязка по QR):
signal-cli link -n "OpenClaw"и отсканируйте код в Signal. - Путь B (регистрация по SMS): зарегистрируйте выделенный номер с капчей и SMS-проверкой.
- Путь A (привязка по QR):
- Настройте OpenClaw и перезапустите Gateway.
- Отправьте первое личное сообщение и подтвердите сопряжение (
openclaw pairing approve signal <CODE>).
Минимальная конфигурация:
{ channels: { signal: { enabled: true, account: "+15551234567", cliPath: "signal-cli", dmPolicy: "pairing", allowFrom: ["+15557654321"], }, },}Справочник полей:
| Поле | Описание |
|---|---|
account |
Номер телефона бота в формате E.164 (+15551234567) |
cliPath |
Путь к signal-cli (signal-cli, если он находится в PATH) |
configPath |
Каталог конфигурации signal-cli, передаваемый как --config |
dmPolicy |
Политика доступа к личным сообщениям (рекомендуется pairing) |
allowFrom |
Номера телефонов или значения uuid:<id>, которым разрешены личные сообщения |
Что это такое
- Канал Signal через
signal-cli(не встроенный libsignal). - Детерминированная маршрутизация: ответы всегда возвращаются в Signal.
- Личные сообщения используют основную сессию агента; группы изолированы (
agent:<agentId>:signal:group:<groupId>).
Запись конфигурации
По умолчанию Signal может записывать обновления конфигурации, вызванные /config set|unset (требуется commands.config: true).
Отключить можно так:
{ channels: { signal: { configWrites: false } },}Модель номера (важно)
- Gateway подключается к устройству Signal (учетной записи
signal-cli). - Если вы запускаете бота на своей личной учетной записи Signal, он будет игнорировать ваши собственные сообщения (защита от зацикливания).
- Для сценария «я пишу боту, а он отвечает» используйте отдельный номер бота.
Путь настройки A: привязать существующую учетную запись Signal (QR)
- Установите
signal-cli(сборку JVM или нативную сборку). - Привяжите учетную запись бота:
signal-cli link -n "OpenClaw", затем отсканируйте QR в Signal.
- Настройте Signal и запустите Gateway.
Пример:
{ channels: { signal: { enabled: true, account: "+15551234567", cliPath: "signal-cli", dmPolicy: "pairing", allowFrom: ["+15557654321"], }, },}Поддержка нескольких учетных записей: используйте channels.signal.accounts с конфигурацией для каждой учетной записи и необязательным name. Общий шаблон см. в разделе gateway/configuration.
Путь настройки B: зарегистрировать выделенный номер бота (SMS, Linux)
Используйте этот вариант, когда нужен выделенный номер бота вместо привязки существующей учетной записи приложения Signal.
- Получите номер, который может принимать SMS (или голосовую проверку для стационарных номеров).
- Используйте выделенный номер бота, чтобы избежать конфликтов учетной записи и сессии.
- Установите
signal-cliна хосте Gateway:
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux-native.tar.gz"sudo tar xf "signal-cli-${VERSION}-Linux-native.tar.gz" -C /optsudo ln -sf /opt/signal-cli /usr/local/bin/signal-cli --versionЕсли используете сборку JVM (signal-cli-${VERSION}.tar.gz), сначала установите JRE 25+.
Поддерживайте signal-cli в актуальном состоянии; upstream отмечает, что старые релизы могут ломаться при изменениях серверных API Signal.
- Зарегистрируйте и подтвердите номер:
signal-cli -a +<BOT_PHONE_NUMBER> registerЕсли требуется капча:
- Откройте
https://signalcaptchas.org/registration/generate.html. - Пройдите капчу, скопируйте целевой адрес ссылки
signalcaptcha://...из «Открыть Signal». - По возможности запускайте команду с того же внешнего IP, что и браузерная сессия.
- Сразу повторите регистрацию (токены капчи быстро истекают):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>- Настройте OpenClaw, перезапустите Gateway, проверьте канал:
# If you run the gateway as a user systemd service:systemctl --user restart openclaw-gateway.service # Then verify:openclaw doctoropenclaw channels status --probe- Сопрягите отправителя личных сообщений:
- Отправьте любое сообщение на номер бота.
- Подтвердите код на сервере:
openclaw pairing approve signal <PAIRING_CODE>. - Сохраните номер бота как контакт на телефоне, чтобы избежать пометки «Неизвестный контакт».
Ссылки upstream:
- README
signal-cli:https://github.com/AsamK/signal-cli - Поток капчи:
https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha - Поток привязки:
https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)
Режим внешнего демона (httpUrl)
Если вы хотите управлять signal-cli самостоятельно (медленные холодные запуски JVM, инициализация контейнера или общие CPU), запустите демон отдельно и укажите OpenClaw путь к нему:
{ channels: { signal: { httpUrl: "http://127.0.0.1:8080", autoStart: false, }, },}Это пропускает автоматический запуск процесса и ожидание старта внутри OpenClaw. Для медленных запусков при автоматическом запуске задайте channels.signal.startupTimeoutMs.
Контейнерный режим (bbernhard/signal-cli-rest-api)
Вместо нативного запуска signal-cli можно использовать Docker-контейнер bbernhard/signal-cli-rest-api. Он оборачивает signal-cli в REST API и интерфейс WebSocket.
Требования:
- Контейнер должен запускаться с
MODE=json-rpcдля получения сообщений в реальном времени. - Зарегистрируйте или привяжите учетную запись Signal внутри контейнера перед подключением OpenClaw.
Пример сервиса docker-compose.yml:
signal-cli: image: bbernhard/signal-cli-rest-api:latest environment: MODE: json-rpc ports: - "8080:8080" volumes: - signal-cli-data:/home/.local/share/signal-cliКонфигурация OpenClaw:
{ channels: { signal: { enabled: true, account: "+15551234567", httpUrl: "http://signal-cli:8080", autoStart: false, apiMode: "container", // or "auto" to detect automatically }, },}Поле apiMode управляет тем, какой протокол использует OpenClaw:
| Значение | Поведение |
|---|---|
"auto" |
(По умолчанию) Проверяет оба транспорта; потоковая передача валидирует получение через WebSocket контейнера |
"native" |
Принудительно использовать нативный signal-cli (JSON-RPC на /api/v1/rpc, SSE на /api/v1/events) |
"container" |
Принудительно использовать контейнер bbernhard (REST на /v2/send, WebSocket на /v1/receive/{account}) |
Когда apiMode равен "auto", OpenClaw кэширует обнаруженный режим на 30 секунд, чтобы избежать повторных проверок. Получение через контейнер выбирается для потоковой передачи только после того, как /v1/receive/{account} обновляется до WebSocket, что требует MODE=json-rpc.
Контейнерный режим поддерживает те же операции канала Signal, что и нативный режим, если контейнер предоставляет соответствующие API: отправка, получение, вложения, индикаторы набора, квитанции о прочтении/просмотре, реакции, группы и стилизованный текст. OpenClaw преобразует свои нативные RPC-вызовы Signal в REST-полезные нагрузки контейнера, включая ID групп group.{base64(internal_id)} и text_mode: "styled" для форматированного текста.
Операционные заметки:
- Используйте
autoStart: falseс контейнерным режимом. OpenClaw не должен запускать нативный демон, когда выбранapiMode: "container". - Используйте
MODE=json-rpcдля получения.MODE=normalможет сделать/v1/aboutвизуально исправным, но/v1/receive/{account}не обновляется до WebSocket, поэтому OpenClaw не выберет потоковое получение через контейнер в режимеauto. - Задайте
apiMode: "container", когда вы знаете, чтоhttpUrlуказывает на REST API bbernhard. ЗадайтеapiMode: "native", когда вы знаете, что он указывает на нативный JSON-RPC/SSEsignal-cli. Используйте"auto", когда развертывание может различаться. - Скачивание вложений в контейнерном режиме соблюдает те же лимиты байтов медиа, что и нативный режим. Слишком большие ответы отклоняются до полного буферизации, когда сервер отправляет
Content-Length, а иначе — во время потоковой передачи.
Управление доступом (личные сообщения + группы)
Личные сообщения:
- По умолчанию:
channels.signal.dmPolicy = "pairing". - Неизвестные отправители получают код сопряжения; сообщения игнорируются до подтверждения (коды истекают через 1 час).
- Подтвердить можно через:
openclaw pairing list signalopenclaw pairing approve signal <CODE>
- Сопряжение — стандартный обмен токенами для личных сообщений Signal. Подробности: Сопряжение
- Отправители только с UUID (из
sourceUuid) сохраняются какuuid:<id>вchannels.signal.allowFrom.
Группы:
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromуправляет тем, какие группы или отправители могут запускать ответы в группе, когда заданallowlist; записями могут быть ID групп Signal (сырые,group:<id>илиsignal:group:<id>), номера телефонов отправителей, значенияuuid:<id>или*.channels.signal.groups["<group-id>" | "*"]может переопределять поведение групп с помощьюrequireMention,toolsиtoolsBySender.- Используйте
channels.signal.accounts.<id>.groupsдля переопределений на уровне учетной записи в настройках с несколькими учетными записями. - Добавление группы Signal в список разрешенных через
groupAllowFromсамо по себе не отключает требование упоминания. Специально настроенная записьchannels.signal.groups["<group-id>"]обрабатывает каждое сообщение группы, если не заданоrequireMention=true. - Примечание о времени выполнения: если
channels.signalполностью отсутствует, во время выполнения для проверок групп используется резервное значениеgroupPolicy="allowlist"(даже если заданоchannels.defaults.groupPolicy).
Как это работает (поведение)
- Нативный режим:
signal-cliработает как демон; Gateway читает события через SSE. - Контейнерный режим: Gateway отправляет через REST API и получает через WebSocket.
- Входящие сообщения нормализуются в общий конверт канала.
- Ответы всегда маршрутизируются обратно на тот же номер или в ту же группу.
Медиа и лимиты
- Исходящий текст разбивается на части по
channels.signal.textChunkLimit(по умолчанию 4000). - Необязательное разбиение по переводам строк: задайте
channels.signal.chunkMode="newline", чтобы разбивать по пустым строкам (границам абзацев) перед разбиением по длине. - Вложения поддерживаются (base64 загружается из
signal-cli). - Вложения голосовых заметок используют имя файла
signal-cliкак резервный MIME-вариант, когдаcontentTypeотсутствует, чтобы транскрибация аудио по-прежнему могла классифицировать голосовые заметки AAC. - Лимит медиа по умолчанию:
channels.signal.mediaMaxMb(по умолчанию 8). - Используйте
channels.signal.ignoreAttachments, чтобы пропускать скачивание медиа. - Контекст истории групп использует
channels.signal.historyLimit(илиchannels.signal.accounts.*.historyLimit), с резервным переходом кmessages.groupChat.historyLimit. Задайте0, чтобы отключить (по умолчанию 50).
Набор текста и квитанции о прочтении
- Индикаторы набора текста: OpenClaw отправляет сигналы набора текста через
signal-cli sendTypingи обновляет их, пока выполняется ответ. - Уведомления о прочтении: когда
channels.signal.sendReadReceiptsравно true, OpenClaw пересылает уведомления о прочтении для разрешенных личных сообщений. - Signal-cli не предоставляет уведомления о прочтении для групп.
Реакции (инструмент message)
- Используйте
message action=reactсchannel=signal. - Цели: E.164 отправителя или UUID (используйте
uuid:<id>из вывода сопряжения; простой UUID тоже работает). messageId— это временная метка Signal для сообщения, на которое вы реагируете.- Для групповых реакций требуется
targetAuthorилиtargetAuthorUuid.
Примеры:
message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=truemessage action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅Конфигурация:
channels.signal.actions.reactions: включить/отключить действия реакций (по умолчанию true).channels.signal.reactionLevel:off | ack | minimal | extensive.off/ackотключает реакции агента (инструмент messagereactвернет ошибку).minimal/extensiveвключает реакции агента и задает уровень рекомендаций.
- Переопределения для отдельных учетных записей:
channels.signal.accounts.<id>.actions.reactions,channels.signal.accounts.<id>.reactionLevel.
Реакции подтверждения
Подсказки подтверждения exec и plugin используют маршрутизирующие блоки верхнего уровня approvals.exec и
approvals.plugin. У Signal нет блока
channels.signal.execApprovals.
👍подтверждает один раз.👎отклоняет.- Используйте
/approve <id> allow-always, когда запрос предлагает постоянное подтверждение.
Для разрешения реакции подтверждения требуются явные утверждающие лица Signal из
channels.signal.allowFrom, channels.signal.defaultTo или соответствующих полей уровня учетной записи.
Прямые подсказки подтверждения exec в том же чате все еще могут подавлять дублирующий локальный резервный вариант /approve
без явных утверждающих лиц; групповые подтверждения без утверждающих лиц оставляют локальный резервный вариант видимым.
Цели доставки (CLI/cron)
- Личные сообщения:
signal:+15551234567(или простой E.164). - Личные сообщения UUID:
uuid:<id>(или простой UUID). - Группы:
signal:group:<groupId>. - Имена пользователей:
username:<name>(если поддерживается вашей учетной записью Signal).
Устранение неполадок
Сначала выполните эту последовательность:
openclaw statusopenclaw gateway statusopenclaw logs --followopenclaw doctoropenclaw channels status --probeЗатем при необходимости подтвердите состояние сопряжения личных сообщений:
openclaw pairing list signalТипичные сбои:
- Демон доступен, но ответов нет: проверьте настройки учетной записи/демона (
httpUrl,account) и режим приема. - Личные сообщения игнорируются: отправитель ожидает подтверждения сопряжения.
- Групповые сообщения игнорируются: фильтрация отправителя/упоминаний группы блокирует доставку.
- Ошибки проверки конфигурации после правок: выполните
openclaw doctor --fix. - Signal отсутствует в диагностике: подтвердите
channels.signal.enabled: true.
Дополнительные проверки:
openclaw pairing list signalpgrep -af signal-cligrep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20Процесс триажа: /channels/troubleshooting.
Примечания по безопасности
signal-cliхранит ключи учетной записи локально (обычно в~/.local/share/signal-cli/data/).- Создайте резервную копию состояния учетной записи Signal перед миграцией сервера или пересборкой.
- Сохраняйте
channels.signal.dmPolicy: "pairing", если вам явно не нужен более широкий доступ к личным сообщениям. - SMS-проверка нужна только для регистрации или восстановления, но потеря контроля над номером/учетной записью может усложнить повторную регистрацию.
Справочник по конфигурации (Signal)
Полная конфигурация: Конфигурация
Параметры провайдера:
channels.signal.enabled: включить/отключить запуск канала.channels.signal.apiMode:auto | native | container(по умолчанию: auto). См. Контейнерный режим.channels.signal.account: E.164 для учетной записи бота.channels.signal.cliPath: путь кsignal-cli.channels.signal.configPath: необязательный каталогsignal-cli --config.channels.signal.httpUrl: полный URL демона (переопределяет host/port).channels.signal.httpHost,channels.signal.httpPort: привязка демона (по умолчанию 127.0.0.1:8080).channels.signal.autoStart: автоматически запускать демон (по умолчанию true, еслиhttpUrlне задан).channels.signal.startupTimeoutMs: время ожидания запуска в мс (предел 120000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: пропускать скачивание вложений.channels.signal.ignoreStories: игнорировать истории от демона.channels.signal.sendReadReceipts: пересылать уведомления о прочтении.channels.signal.dmPolicy:pairing | allowlist | open | disabled(по умолчанию: pairing).channels.signal.allowFrom: список разрешенных личных сообщений (E.164 илиuuid:<id>). Дляopenтребуется"*". В Signal нет имен пользователей; используйте телефонные номера/UUID.channels.signal.groupPolicy:open | allowlist | disabled(по умолчанию: allowlist).channels.signal.groupAllowFrom: список разрешенных групп; принимает идентификаторы групп Signal (raw,group:<id>илиsignal:group:<id>), номера отправителей E.164 или значенияuuid:<id>.channels.signal.groups: переопределения для отдельных групп, ключ — id группы Signal (или"*"). Поддерживаемые поля:requireMention,tools,toolsBySender.channels.signal.accounts.<id>.groups: версияchannels.signal.groupsдля отдельных учетных записей в конфигурациях с несколькими учетными записями.channels.signal.historyLimit: максимальное количество групповых сообщений, включаемых как контекст (0 отключает).channels.signal.dmHistoryLimit: лимит истории личных сообщений в пользовательских ходах. Переопределения для отдельных пользователей:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: размер исходящего фрагмента (символы).channels.signal.chunkMode:length(по умолчанию) илиnewlineдля разбиения по пустым строкам (границам абзацев) перед разбиением по длине.channels.signal.mediaMaxMb: ограничение входящих/исходящих медиа (МБ).
Связанные глобальные параметры:
agents.list[].groupChat.mentionPatterns(Signal не поддерживает нативные упоминания).messages.groupChat.mentionPatterns(глобальный резервный вариант).messages.responsePrefix.
Связанное
- Обзор каналов — все поддерживаемые каналы
- Сопряжение — аутентификация личных сообщений и процесс сопряжения
- Группы — поведение группового чата и фильтрация упоминаний
- Маршрутизация каналов — маршрутизация сеансов для сообщений
- Безопасность — модель доступа и усиление защиты