Signal (signal-cli)
Статус: интеграция через внешний CLI. Шлюз взаимодействует с signal-cli по HTTP JSON-RPC + SSE.
Требования
- OpenClaw установлен на сервере (процесс ниже проверен на Ubuntu 24).
signal-cliдоступен на хосте, где запущен шлюз.- Номер телефона, способный принять одно верификационное SMS (для регистрации через SMS).
- Браузер для капчи Signal (
signalcaptchas.org) при регистрации.
Быстрая настройка (для начинающих)
- Используйте отдельный номер Signal для бота (рекомендуется).
- Установите
signal-cli(требуется Java для JVM-сборки). - Выберите путь настройки:
- Путь A (QR-ссылка):
signal-cli link -n "OpenClaw"и отсканируйте QR в Signal. - Путь B (регистрация по SMS): зарегистрируйте выделенный номер с капчей + SMS-верификацией.
- Путь A (QR-ссылка):
- Настройте OpenClaw и перезапустите шлюз.
- Отправьте первое ЛС и подтвердите спаривание (
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) |
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 } },
}
Модель номеров (важно)
- Шлюз подключается к устройству Signal (аккаунту
signal-cli). - Если бот запущен на вашем личном аккаунте Signal, он будет игнорировать ваши собственные сообщения (защита от петли).
- Для сценария «я пишу боту, он отвечает» используйте отдельный номер бота.
Путь настройки A: привязка существующего аккаунта Signal (QR)
- Установите
signal-cli(JVM или нативная сборка). - Привяжите аккаунт бота:
signal-cli link -n "OpenClaw", затем отсканируйте QR в Signal.
- Настройте Signal и запустите шлюз.
Пример:
{
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на хосте шлюза:
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 /opt
sudo ln -sf /opt/signal-cli /usr/local/bin/
signal-cli --version
Для JVM-сборки (signal-cli-${VERSION}.tar.gz) сначала установите JRE 25+.
Держите signal-cli обновлённым; авторы отмечают, что старые версии могут ломаться при изменении API сервера Signal.
- Зарегистрируйте и верифицируйте номер:
signal-cli -a +<BOT_PHONE_NUMBER> register
Если требуется капча:
- Откройте
https://signalcaptchas.org/registration/generate.html. - Пройдите капчу, скопируйте ссылку
signalcaptcha://...из «Open Signal». - По возможности запускайте с того же внешнего IP, что и браузерная сессия.
- Немедленно запустите регистрацию повторно (токены капчи быстро истекают):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
- Настройте OpenClaw, перезапустите шлюз, проверьте канал:
# Если шлюз запущен как пользовательский systemd-сервис:
systemctl --user restart openclaw-gateway
# Затем проверьте:
openclaw doctor
openclaw channels status --probe
- Выполните спаривание отправителя ЛС:
- Отправьте любое сообщение на номер бота.
- Подтвердите код на сервере:
openclaw pairing approve signal <PAIRING_CODE>. - Сохраните номер бота как контакт на телефоне, чтобы избежать «Неизвестный контакт».
Предупреждение: Регистрация номера телефона через
signal-cliможет деаутентифицировать основную сессию приложения Signal для этого номера. Предпочтительнее использовать выделенный номер бота или режим QR-привязки, если нужно сохранить существующую настройку.
Внешние ссылки:
- 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.
Контроль доступа (ЛС + группы)
ЛС:
- По умолчанию:
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.channels.signal.groups["<group-id>" | "*"]может переопределить поведение группы:requireMention,toolsиtoolsBySender.- Используйте
channels.signal.accounts.<id>.groupsдля переопределений по аккаунтам в мульти-аккаунтных конфигурациях. - Примечание: если
channels.signalполностью отсутствует, runtime использует fallback кgroupPolicy="allowlist"для групповых проверок (даже если заданchannels.defaults.groupPolicy).
Как это работает (поведение)
signal-cliработает как демон; шлюз читает события через SSE.- Входящие сообщения нормализуются в общий конверт канала.
- Ответы всегда маршрутизируются обратно на тот же номер или в ту же группу.
Медиа + ограничения
- Исходящий текст разбивается по
channels.signal.textChunkLimit(по умолчанию 4000). - Необязательная разбивка по переводам строк: задайте
channels.signal.chunkMode="newline"для разделения по пустым строкам (границам абзацев) перед разбивкой по длине. - Вложения поддерживаются (base64, получаемые из
signal-cli). - Лимит медиа по умолчанию:
channels.signal.mediaMaxMb(по умолчанию 8). - Используйте
channels.signal.ignoreAttachmentsдля пропуска загрузки медиа. - Контекст истории группы использует
channels.signal.historyLimit(илиchannels.signal.accounts.*.historyLimit), с fallback к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=true
message 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.
Цели доставки (CLI/cron)
- ЛС:
signal:+15551234567(или просто E.164). - UUID ЛС:
uuid:<id>(или голый UUID). - Группы:
signal:group:<groupId>. - Имена пользователей:
username:<name>(при поддержке вашим аккаунтом Signal).
Устранение неполадок
Выполните эти команды первыми:
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe
Затем проверьте состояние спаривания ЛС при необходимости:
openclaw pairing list signal
Частые сбои:
- Демон доступен, но ответов нет: проверьте настройки аккаунта/демона (
httpUrl,account) и режим приёма. - ЛС игнорируются: отправитель ожидает подтверждения спаривания.
- Групповые сообщения игнорируются: блокировка по отправителю/упоминанию в группе.
- Ошибки валидации конфигурации после правок: запустите
openclaw doctor --fix. - Signal отсутствует в диагностике: подтвердите
channels.signal.enabled: true.
Дополнительные проверки:
openclaw pairing list signal
pgrep -af signal-cli
grep -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.account: E.164 аккаунта бота.channels.signal.cliPath: путь кsignal-cli.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: список доступа отправителей в группах.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(глобальный fallback).messages.responsePrefix.