Mainstream messaging

Signal

Status: integracja z zewnętrznym CLI. Gateway komunikuje się z signal-cli przez HTTP JSON-RPC + SSE.

Wymagania wstępne

  • OpenClaw zainstalowany na serwerze (poniższy przepływ dla Linuxa przetestowano na Ubuntu 24).
  • signal-cli dostępne na hoście, na którym działa gateway.
  • Numer telefonu, który może odebrać jeden SMS weryfikacyjny (dla ścieżki rejestracji przez SMS).
  • Dostęp do przeglądarki dla captcha Signal (signalcaptchas.org) podczas rejestracji.

Szybka konfiguracja (dla początkujących)

  1. Użyj osobnego numeru Signal dla bota (zalecane).
  2. Zainstaluj signal-cli (Java jest wymagana, jeśli używasz kompilacji JVM).
  3. Wybierz jedną ścieżkę konfiguracji:
    • Ścieżka A (link QR): signal-cli link -n "OpenClaw" i zeskanuj w Signal.
    • Ścieżka B (rejestracja SMS): zarejestruj dedykowany numer z captcha + weryfikacją SMS.
  4. Skonfiguruj OpenClaw i uruchom ponownie gateway.
  5. Wyślij pierwszą wiadomość prywatną i zatwierdź parowanie (openclaw pairing approve signal <CODE>).

Minimalna konfiguracja:

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

Opis pól:

Pole Opis
account Numer telefonu bota w formacie E.164 (+15551234567)
cliPath Ścieżka do signal-cli (signal-cli, jeśli jest w PATH)
dmPolicy Zasady dostępu do wiadomości prywatnych (zalecane pairing)
allowFrom Numery telefonów lub wartości uuid:<id> dopuszczone do wiadomości prywatnych

Co to jest

  • Kanał Signal przez signal-cli (nie osadzony libsignal).
  • Deterministyczne trasowanie: odpowiedzi zawsze wracają do Signal.
  • Wiadomości prywatne współdzielą główną sesję agenta; grupy są izolowane (agent:<agentId>:signal:group:<groupId>).

Zapisy konfiguracji

Domyślnie Signal może zapisywać aktualizacje konfiguracji wywołane przez /config set|unset (wymaga commands.config: true).

Wyłącz za pomocą:

{
  channels: { signal: { configWrites: false } },
}

Model numeru (ważne)

  • Gateway łączy się z urządzeniem Signal (kontem signal-cli).
  • Jeśli uruchomisz bota na swoim osobistym koncie Signal, będzie ignorował twoje własne wiadomości (ochrona przed pętlą).
  • Dla scenariusza „piszę do bota, a on odpowiada” użyj osobnego numeru bota.

Ścieżka konfiguracji A: połącz istniejące konto Signal (QR)

  1. Zainstaluj signal-cli (kompilację JVM lub natywną).
  2. Połącz konto bota:
    • signal-cli link -n "OpenClaw", a potem zeskanuj QR w Signal.
  3. Skonfiguruj Signal i uruchom gateway.

Przykład:

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

Obsługa wielu kont: użyj channels.signal.accounts z konfiguracją dla każdego konta i opcjonalnym name. Zobacz gateway/configuration, aby poznać wspólny wzorzec.

Ścieżka konfiguracji B: zarejestruj dedykowany numer bota (SMS, Linux)

Użyj tej opcji, gdy chcesz mieć dedykowany numer bota zamiast łączyć istniejące konto aplikacji Signal.

  1. Uzyskaj numer, który może odbierać SMS (lub weryfikację głosową dla numerów stacjonarnych).
    • Użyj dedykowanego numeru bota, aby uniknąć konfliktów konta/sesji.
  2. Zainstaluj signal-cli na hoście 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 /opt
sudo ln -sf /opt/signal-cli /usr/local/bin/
signal-cli --version

Jeśli używasz kompilacji JVM (signal-cli-${VERSION}.tar.gz), najpierw zainstaluj JRE 25+. Aktualizuj signal-cli; upstream wskazuje, że stare wydania mogą przestać działać, gdy zmienią się API serwera Signal.

  1. Zarejestruj i zweryfikuj numer:
signal-cli -a +&lt;BOT_PHONE_NUMBER&gt; register

Jeśli captcha jest wymagana:

  1. Otwórz https://signalcaptchas.org/registration/generate.html.
  2. Ukończ captcha, skopiuj cel linku signalcaptcha://... z „Open Signal”.
  3. Jeśli to możliwe, uruchom z tego samego zewnętrznego IP co sesja przeglądarki.
  4. Natychmiast uruchom rejestrację ponownie (tokeny captcha szybko wygasają):
signal-cli -a +&lt;BOT_PHONE_NUMBER&gt; register --captcha '&lt;SIGNALCAPTCHA_URL&gt;'
signal-cli -a +&lt;BOT_PHONE_NUMBER&gt; verify &lt;VERIFICATION_CODE&gt;
  1. Skonfiguruj OpenClaw, uruchom ponownie gateway, zweryfikuj kanał:
# If you run the gateway as a user systemd service:
systemctl --user restart openclaw-gateway.service

# Then verify:
openclaw doctor
openclaw channels status --probe
  1. Sparuj nadawcę wiadomości prywatnych:
    • Wyślij dowolną wiadomość na numer bota.
    • Zatwierdź kod na serwerze: openclaw pairing approve signal &lt;PAIRING_CODE&gt;.
    • Zapisz numer bota jako kontakt w telefonie, aby uniknąć „Unknown contact”.

Odwołania upstream:

  • README signal-cli: https://github.com/AsamK/signal-cli
  • Przepływ captcha: https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • Przepływ łączenia: https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

Tryb zewnętrznego demona (httpUrl)

Jeśli chcesz samodzielnie zarządzać signal-cli (wolne zimne starty JVM, inicjalizacja kontenera lub współdzielone CPU), uruchom demona osobno i wskaż go w OpenClaw:

{
  channels: {
    signal: {
      httpUrl: "http://127.0.0.1:8080",
      autoStart: false,
    },
  },
}

To pomija automatyczne uruchamianie procesu i oczekiwanie na start w OpenClaw. Przy wolnych startach podczas automatycznego uruchamiania ustaw channels.signal.startupTimeoutMs.

Kontrola dostępu (wiadomości prywatne + grupy)

Wiadomości prywatne:

  • Domyślnie: channels.signal.dmPolicy = "pairing".
  • Nieznani nadawcy otrzymują kod parowania; wiadomości są ignorowane do czasu zatwierdzenia (kody wygasają po 1 godzinie).
  • Zatwierdź przez:
    • openclaw pairing list signal
    • openclaw pairing approve signal &lt;CODE&gt;
  • Parowanie jest domyślną wymianą tokenów dla wiadomości prywatnych Signal. Szczegóły: Parowanie
  • Nadawcy wyłącznie z UUID (z sourceUuid) są zapisywani jako uuid:<id> w channels.signal.allowFrom.

Grupy:

  • channels.signal.groupPolicy = open | allowlist | disabled.
  • channels.signal.groupAllowFrom kontroluje, które grupy lub nadawcy mogą wyzwalać odpowiedzi grupowe, gdy ustawiono allowlist; wpisami mogą być identyfikatory grup Signal (surowe, group:<id> lub signal:group:<id>), numery telefonów nadawców, wartości uuid:<id> albo *.
  • channels.signal.groups["<group-id>" | "*"] może nadpisać zachowanie grupy za pomocą requireMention, tools i toolsBySender.
  • Użyj channels.signal.accounts.<id>.groups dla nadpisań per konto w konfiguracjach wielokontowych.
  • Dodanie grupy Signal do listy dozwolonych przez groupAllowFrom samo w sobie nie wyłącza bramkowania wzmiankami. Konkretnie skonfigurowany wpis channels.signal.groups["<group-id>"] przetwarza każdą wiadomość grupową, chyba że ustawiono requireMention=true.
  • Uwaga o środowisku wykonawczym: jeśli channels.signal całkowicie brakuje, środowisko wykonawcze wraca do groupPolicy="allowlist" dla kontroli grup (nawet jeśli ustawiono channels.defaults.groupPolicy).

Jak to działa (zachowanie)

  • signal-cli działa jako demon; gateway odczytuje zdarzenia przez SSE.
  • Wiadomości przychodzące są normalizowane do współdzielonej koperty kanału.
  • Odpowiedzi zawsze są trasowane z powrotem do tego samego numeru lub grupy.

Multimedia + limity

  • Tekst wychodzący jest dzielony do channels.signal.textChunkLimit (domyślnie 4000).
  • Opcjonalne dzielenie według nowych linii: ustaw channels.signal.chunkMode="newline", aby dzielić według pustych linii (granic akapitów) przed dzieleniem według długości.
  • Załączniki są obsługiwane (base64 pobierane z signal-cli).
  • Załączniki notatek głosowych używają nazwy pliku z signal-cli jako zapasowego MIME, gdy brakuje contentType, dzięki czemu transkrypcja audio nadal może klasyfikować notatki głosowe AAC.
  • Domyślny limit multimediów: channels.signal.mediaMaxMb (domyślnie 8).
  • Użyj channels.signal.ignoreAttachments, aby pominąć pobieranie multimediów.
  • Kontekst historii grupy używa channels.signal.historyLimit (lub channels.signal.accounts.*.historyLimit) i wraca do messages.groupChat.historyLimit. Ustaw 0, aby wyłączyć (domyślnie 50).

Wpisywanie + potwierdzenia odczytu

  • Wskaźniki pisania: OpenClaw wysyła sygnały pisania przez signal-cli sendTyping i odświeża je, gdy trwa odpowiedź.
  • Potwierdzenia odczytu: gdy channels.signal.sendReadReceipts ma wartość true, OpenClaw przekazuje potwierdzenia odczytu dla dozwolonych wiadomości prywatnych.
  • Signal-cli nie udostępnia potwierdzeń odczytu dla grup.

Reakcje (narzędzie wiadomości)

  • Użyj message action=react z channel=signal.
  • Cele: nadawca E.164 lub UUID (użyj uuid:<id> z wyjścia parowania; sam UUID też działa).
  • messageId to znacznik czasu Signal dla wiadomości, na którą reagujesz.
  • Reakcje w grupach wymagają targetAuthor lub targetAuthorUuid.

Przykłady:

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=✅

Konfiguracja:

  • channels.signal.actions.reactions: włącza/wyłącza akcje reakcji (domyślnie true).
  • channels.signal.reactionLevel: off | ack | minimal | extensive.
    • off/ack wyłącza reakcje agenta (narzędzie wiadomości react zwróci błąd).
    • minimal/extensive włącza reakcje agenta i ustawia poziom wskazówek.
  • Nadpisania per konto: channels.signal.accounts.<id>.actions.reactions, channels.signal.accounts.<id>.reactionLevel.

Cele dostarczania (CLI/cron)

  • Wiadomości prywatne: signal:+15551234567 (lub zwykłe E.164).
  • Wiadomości prywatne UUID: uuid:<id> (lub sam UUID).
  • Grupy: signal:group:<groupId>.
  • Nazwy użytkowników: username:<name> (jeśli obsługiwane przez twoje konto Signal).

Rozwiązywanie problemów

Najpierw uruchom tę sekwencję:

openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe

Następnie w razie potrzeby potwierdź stan parowania wiadomości prywatnych:

openclaw pairing list signal

Typowe awarie:

  • Demon osiągalny, ale brak odpowiedzi: zweryfikuj ustawienia konta/demona (httpUrl, account) i tryb odbioru.
  • Wiadomości prywatne ignorowane: nadawca oczekuje na zatwierdzenie parowania.
  • Wiadomości grupowe ignorowane: bramkowanie nadawcy grupy/wzmianki blokuje dostarczenie.
  • Błędy walidacji konfiguracji po edycjach: uruchom openclaw doctor --fix.
  • Brak Signal w diagnostyce: potwierdź channels.signal.enabled: true.

Dodatkowe kontrole:

openclaw pairing list signal
pgrep -af signal-cli
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20

Przepływ triage: /channels/troubleshooting.

Uwagi dotyczące bezpieczeństwa

  • signal-cli przechowuje klucze konta lokalnie (zwykle ~/.local/share/signal-cli/data/).
  • Wykonaj kopię zapasową stanu konta Signal przed migracją serwera lub jego ponowną budową.
  • Zachowaj channels.signal.dmPolicy: "pairing", chyba że wyraźnie chcesz szerszego dostępu do wiadomości prywatnych.
  • Weryfikacja SMS jest potrzebna tylko w przepływach rejestracji lub odzyskiwania, ale utrata kontroli nad numerem/kontem może skomplikować ponowną rejestrację.

Opis konfiguracji (Signal)

Pełna konfiguracja: Konfiguracja

Opcje dostawcy:

  • channels.signal.enabled: włącz/wyłącz uruchamianie kanału.
  • channels.signal.account: E.164 dla konta bota.
  • channels.signal.cliPath: ścieżka do signal-cli.
  • channels.signal.httpUrl: pełny adres URL demona (zastępuje host/port).
  • channels.signal.httpHost, channels.signal.httpPort: adres nasłuchu demona (domyślnie 127.0.0.1:8080).
  • channels.signal.autoStart: automatycznie uruchamiaj demona (domyślnie true, jeśli httpUrl nie jest ustawione).
  • channels.signal.startupTimeoutMs: limit czasu oczekiwania na uruchomienie w ms (maks. 120000).
  • channels.signal.receiveMode: on-start | manual.
  • channels.signal.ignoreAttachments: pomiń pobieranie załączników.
  • channels.signal.ignoreStories: ignoruj relacje z demona.
  • channels.signal.sendReadReceipts: przekazuj potwierdzenia odczytu.
  • channels.signal.dmPolicy: pairing | allowlist | open | disabled (domyślnie: pairing).
  • channels.signal.allowFrom: lista dozwolonych DM (E.164 lub uuid:<id>). open wymaga "*". Signal nie ma nazw użytkowników; używaj identyfikatorów telefonu/UUID.
  • channels.signal.groupPolicy: open | allowlist | disabled (domyślnie: allowlist).
  • channels.signal.groupAllowFrom: lista dozwolonych grup; akceptuje identyfikatory grup Signal (surowe, group:<id> lub signal:group:<id>), numery nadawców E.164 albo wartości uuid:<id>.
  • channels.signal.groups: zastąpienia dla poszczególnych grup, kluczowane identyfikatorem grupy Signal (lub "*"). Obsługiwane pola: requireMention, tools, toolsBySender.
  • channels.signal.accounts.<id>.groups: wersja channels.signal.groups dla poszczególnych kont w konfiguracjach wielokontowych.
  • channels.signal.historyLimit: maksymalna liczba wiadomości grupowych do uwzględnienia jako kontekst (0 wyłącza).
  • channels.signal.dmHistoryLimit: limit historii DM w turach użytkownika. Zastąpienia dla poszczególnych użytkowników: channels.signal.dms["<phone_or_uuid>"].historyLimit.
  • channels.signal.textChunkLimit: rozmiar fragmentu wychodzącego (znaki).
  • channels.signal.chunkMode: length (domyślnie) lub newline, aby dzielić według pustych wierszy (granic akapitów) przed dzieleniem według długości.
  • channels.signal.mediaMaxMb: limit multimediów przychodzących/wychodzących (MB).

Powiązane opcje globalne:

  • agents.list[].groupChat.mentionPatterns (Signal nie obsługuje natywnych wzmianek).
  • messages.groupChat.mentionPatterns (globalna rezerwa).
  • messages.responsePrefix.

Powiązane