Signal (signal-cli)

Статус: интеграция через внешний CLI. Шлюз взаимодействует с signal-cli по HTTP JSON-RPC + SSE.

Требования

  • OpenClaw установлен на сервере (процесс ниже проверен на Ubuntu 24).
  • signal-cli доступен на хосте, где запущен шлюз.
  • Номер телефона, способный принять одно верификационное SMS (для регистрации через SMS).
  • Браузер для капчи Signal (signalcaptchas.org) при регистрации.

Быстрая настройка (для начинающих)

  1. Используйте отдельный номер Signal для бота (рекомендуется).
  2. Установите signal-cli (требуется Java для JVM-сборки).
  3. Выберите путь настройки:
    • Путь A (QR-ссылка): signal-cli link -n "OpenClaw" и отсканируйте QR в Signal.
    • Путь B (регистрация по SMS): зарегистрируйте выделенный номер с капчей + SMS-верификацией.
  4. Настройте OpenClaw и перезапустите шлюз.
  5. Отправьте первое ЛС и подтвердите спаривание (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)

  1. Установите signal-cli (JVM или нативная сборка).
  2. Привяжите аккаунт бота:
    • signal-cli link -n "OpenClaw", затем отсканируйте QR в Signal.
  3. Настройте Signal и запустите шлюз.

Пример:

{
  channels: {
    signal: {
      enabled: true,
      account: "+15551234567",
      cliPath: "signal-cli",
      dmPolicy: "pairing",
      allowFrom: ["+15557654321"],
    },
  },
}

Мульти-аккаунт: используйте channels.signal.accounts с конфигурацией для каждого аккаунта и необязательным name. Подробнее: gateway/configuration.

Путь настройки B: регистрация выделенного номера бота (SMS, Linux)

Используйте, когда нужен выделенный номер бота вместо привязки существующего аккаунта Signal.

  1. Получите номер, способный принимать SMS (или голосовую верификацию для стационарных телефонов).
    • Используйте выделенный номер бота для избежания конфликтов аккаунтов/сессий.
  2. Установите 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.

  1. Зарегистрируйте и верифицируйте номер:
signal-cli -a +<BOT_PHONE_NUMBER> register

Если требуется капча:

  1. Откройте https://signalcaptchas.org/registration/generate.html.
  2. Пройдите капчу, скопируйте ссылку signalcaptcha://... из «Open Signal».
  3. По возможности запускайте с того же внешнего IP, что и браузерная сессия.
  4. Немедленно запустите регистрацию повторно (токены капчи быстро истекают):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. Настройте OpenClaw, перезапустите шлюз, проверьте канал:
# Если шлюз запущен как пользовательский systemd-сервис:
systemctl --user restart openclaw-gateway

# Затем проверьте:
openclaw doctor
openclaw channels status --probe
  1. Выполните спаривание отправителя ЛС:
    • Отправьте любое сообщение на номер бота.
    • Подтвердите код на сервере: 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 signal
    • openclaw 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 отключают реакции агента (инструмент message react вернёт ошибку).
    • 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.