Signal (signal-cli)

Status: Externe CLI-Integration. Das Gateway kommuniziert mit signal-cli über HTTP JSON-RPC + SSE.

Voraussetzungen

  • OpenClaw auf deinem Server installiert (Linux-Ablauf unten getestet auf Ubuntu 24).
  • signal-cli auf dem Host verfügbar, auf dem das Gateway läuft.
  • Eine Telefonnummer, die eine Verifizierungs-SMS empfangen kann (für den SMS-Registrierungsweg).
  • Browser-Zugang für Signal-Captcha (signalcaptchas.org) während der Registrierung.

Schnelleinrichtung (Einsteiger)

  1. Verwende eine separate Signal-Nummer für den Bot (empfohlen).
  2. Installiere signal-cli (Java erforderlich bei JVM-Build).
  3. Wähle einen Einrichtungsweg:
    • Weg A (QR-Link): signal-cli link -n "OpenClaw" und scanne mit Signal.
    • Weg B (SMS-Registrierung): Registriere eine dedizierte Nummer mit Captcha + SMS-Verifizierung.
  4. Konfiguriere OpenClaw und starte das Gateway neu.
  5. Sende eine erste DM und genehmige das Pairing (openclaw pairing approve signal <CODE>).

Minimale Konfiguration:

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

Feldreferenz:

FeldBeschreibung
accountBot-Telefonnummer im E.164-Format (+15551234567)
cliPathPfad zu signal-cli (signal-cli wenn im PATH)
dmPolicyDM-Zugriffsrichtlinie (pairing empfohlen)
allowFromTelefonnummern oder uuid:<id>-Werte, die DMs senden dürfen

Was es ist

  • Signal-Kanal via signal-cli (nicht eingebettetes libsignal).
  • Deterministisches Routing: Antworten gehen immer zurück zu Signal.
  • DMs teilen die Haupt-Session des Agenten; Gruppen sind isoliert (agent:<agentId>:signal:group:<groupId>).

Konfigurationsschreibvorgänge

Standardmäßig darf Signal Konfigurationsaktualisierungen schreiben, die durch /config set|unset ausgelöst werden (erfordert commands.config: true).

Deaktivieren mit:

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

Das Nummernmodell (wichtig)

  • Das Gateway verbindet sich mit einem Signal-Gerät (dem signal-cli-Konto).
  • Wenn du den Bot auf deinem persönlichen Signal-Konto betreibst, ignoriert er deine eigenen Nachrichten (Schleifenschutz).
  • Für „Ich schreibe dem Bot und er antwortet” verwende eine separate Bot-Nummer.

Einrichtungsweg A: Bestehendes Signal-Konto verknüpfen (QR)

  1. Installiere signal-cli (JVM- oder Native-Build).
  2. Verknüpfe ein Bot-Konto:
    • signal-cli link -n "OpenClaw" dann scanne den QR-Code in Signal.
  3. Konfiguriere Signal und starte das Gateway.

Beispiel:

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

Multi-Account-Unterstützung: Verwende channels.signal.accounts mit Pro-Konto-Konfiguration und optionalem name. Siehe gateway/configuration für das gemeinsame Muster.

Einrichtungsweg B: Dedizierte Bot-Nummer registrieren (SMS, Linux)

Verwende diesen Weg, wenn du eine dedizierte Bot-Nummer möchtest, anstatt ein bestehendes Signal-App-Konto zu verknüpfen.

  1. Besorge eine Nummer, die SMS empfangen kann (oder Sprachverifizierung für Festnetz).
    • Verwende eine dedizierte Bot-Nummer, um Konto-/Session-Konflikte zu vermeiden.
  2. Installiere signal-cli auf dem Gateway-Host:
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

Wenn du den JVM-Build (signal-cli-${VERSION}.tar.gz) verwendest, installiere zuerst JRE 25+. Halte signal-cli aktuell; Upstream weist darauf hin, dass alte Releases brechen können, wenn sich Signal-Server-APIs ändern.

  1. Nummer registrieren und verifizieren:
signal-cli -a +<BOT_PHONE_NUMBER> register

Falls ein Captcha erforderlich ist:

  1. Öffne https://signalcaptchas.org/registration/generate.html.
  2. Löse das Captcha, kopiere den signalcaptcha://...-Link-Zielwert von „Open Signal”.
  3. Führe den Befehl wenn möglich von derselben externen IP wie die Browser-Session aus.
  4. Führe die Registrierung sofort erneut aus (Captcha-Tokens laufen schnell ab):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. OpenClaw konfigurieren, Gateway neustarten, Kanal prüfen:
# Bei Gateway als User-systemd-Service:
systemctl --user restart openclaw-gateway

# Dann prüfen:
openclaw doctor
openclaw channels status --probe
  1. DM-Absender pairen:
    • Sende eine beliebige Nachricht an die Bot-Nummer.
    • Code auf dem Server genehmigen: openclaw pairing approve signal <PAIRING_CODE>.
    • Speichere die Bot-Nummer als Kontakt auf deinem Telefon, um „Unbekannter Kontakt” zu vermeiden.

Wichtig: Die Registrierung einer Telefonnummer mit signal-cli kann die Signal-App-Session dieser Nummer deauthentifizieren. Bevorzuge eine dedizierte Bot-Nummer oder verwende den QR-Link-Modus, wenn du dein bestehendes Telefon-App-Setup behalten möchtest.

Upstream-Referenzen:

  • signal-cli README: https://github.com/AsamK/signal-cli
  • Captcha-Ablauf: https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • Verknüpfungsablauf: https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

Externer Daemon-Modus (httpUrl)

Wenn du signal-cli selbst verwalten möchtest (langsame JVM-Kaltstarts, Container-Init oder geteilte CPUs), starte den Daemon separat und richte OpenClaw darauf:

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

Dies überspringt Auto-Spawn und die Startwartung in OpenClaw. Für langsame Starts beim Auto-Spawning setze channels.signal.startupTimeoutMs.

Zugriffssteuerung (DMs + Gruppen)

DMs:

  • Standard: channels.signal.dmPolicy = "pairing".
  • Unbekannte Absender erhalten einen Pairing-Code; Nachrichten werden ignoriert, bis sie genehmigt sind (Codes verfallen nach 1 Stunde).
  • Genehmigung über:
    • openclaw pairing list signal
    • openclaw pairing approve signal <CODE>
  • Pairing ist der Standard-Token-Austausch für Signal-DMs. Details: Pairing
  • Nur-UUID-Absender (aus sourceUuid) werden als uuid:<id> in channels.signal.allowFrom gespeichert.

Gruppen:

  • channels.signal.groupPolicy = open | allowlist | disabled.
  • channels.signal.groupAllowFrom steuert, wer in Gruppen auslösen kann, wenn allowlist gesetzt ist.
  • channels.signal.groups["<group-id>" | "*"] kann Gruppenverhalten mit requireMention, tools und toolsBySender überschreiben.
  • Verwende channels.signal.accounts.<id>.groups für Pro-Konto-Überschreibungen in Multi-Account-Setups.
  • Laufzeithinweis: Wenn channels.signal vollständig fehlt, fällt die Laufzeit für Gruppenprüfungen auf groupPolicy="allowlist" zurück (auch wenn channels.defaults.groupPolicy gesetzt ist).

Funktionsweise (Verhalten)

  • signal-cli läuft als Daemon; das Gateway liest Events via SSE.
  • Eingehende Nachrichten werden in den gemeinsamen Kanalumschlag normalisiert.
  • Antworten werden immer an dieselbe Nummer oder Gruppe zurückgeleitet.

Medien + Limits

  • Ausgehender Text wird auf channels.signal.textChunkLimit aufgeteilt (Standard 4000).
  • Optionales Zeilenumbruch-Chunking: Setze channels.signal.chunkMode="newline", um an Leerzeilen (Absatzgrenzen) vor dem Längen-Chunking aufzuteilen.
  • Anhänge werden unterstützt (Base64 von signal-cli abgerufen).
  • Standard-Medien-Obergrenze: channels.signal.mediaMaxMb (Standard 8).
  • Verwende channels.signal.ignoreAttachments, um Medien-Downloads zu überspringen.
  • Gruppenverlaufskontext verwendet channels.signal.historyLimit (oder channels.signal.accounts.*.historyLimit), Fallback auf messages.groupChat.historyLimit. Setze 0 zum Deaktivieren (Standard 50).

Tippanzeige + Lesebestätigungen

  • Tippindikatoren: OpenClaw sendet Tippsignale via signal-cli sendTyping und erneuert sie, während eine Antwort läuft.
  • Lesebestätigungen: Wenn channels.signal.sendReadReceipts aktiv ist, leitet OpenClaw Lesebestätigungen für erlaubte DMs weiter.
  • signal-cli stellt Lesebestätigungen für Gruppen nicht bereit.

Reaktionen (Nachrichten-Tool)

  • Verwende message action=react mit channel=signal.
  • Ziele: Absender-E.164 oder UUID (verwende uuid:<id> aus der Pairing-Ausgabe; nackte UUID funktioniert auch).
  • messageId ist der Signal-Zeitstempel der Nachricht, auf die reagiert wird.
  • Gruppenreaktionen erfordern targetAuthor oder targetAuthorUuid.

Beispiele:

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

Konfiguration:

  • channels.signal.actions.reactions: Reaktionsaktionen aktivieren/deaktivieren (Standard true).
  • channels.signal.reactionLevel: off | ack | minimal | extensive.
    • off/ack deaktiviert Agent-Reaktionen (Nachrichten-Tool react gibt Fehler).
    • minimal/extensive aktiviert Agent-Reaktionen und setzt die Anleitungsstufe.
  • Pro-Konto-Überschreibungen: channels.signal.accounts.<id>.actions.reactions, channels.signal.accounts.<id>.reactionLevel.

Zustellziele (CLI/Cron)

  • DMs: signal:+15551234567 (oder einfache E.164).
  • UUID-DMs: uuid:<id> (oder nackte UUID).
  • Gruppen: signal:group:<groupId>.
  • Benutzernamen: username:<name> (wenn von deinem Signal-Konto unterstützt).

Fehlerbehebung

Führe zuerst diese Befehle aus:

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

Dann bestätige bei Bedarf den DM-Pairing-Status:

openclaw pairing list signal

Häufige Fehler:

  • Daemon erreichbar, aber keine Antworten: Konto-/Daemon-Einstellungen (httpUrl, account) und Empfangsmodus prüfen.
  • DMs ignoriert: Absender wartet auf Pairing-Genehmigung.
  • Gruppennachrichten ignoriert: Gruppen-Absender-/Mention-Gating blockiert Zustellung.
  • Konfigurationsvalidierungsfehler nach Änderungen: openclaw doctor --fix ausführen.
  • Signal fehlt in der Diagnose: Bestätige channels.signal.enabled: true.

Zusätzliche Prüfungen:

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

Für den Triage-Ablauf: /channels/troubleshooting.

Sicherheitshinweise

  • signal-cli speichert Kontoschlüssel lokal (typischerweise ~/.local/share/signal-cli/data/).
  • Sichere den Signal-Kontostatus vor Servermigration oder Neuaufbau.
  • Behalte channels.signal.dmPolicy: "pairing", sofern du nicht explizit breiteren DM-Zugang möchtest.
  • SMS-Verifizierung ist nur für Registrierungs- oder Wiederherstellungsabläufe nötig, aber der Verlust der Kontrolle über die Nummer/das Konto kann die Neuregistrierung erschweren.

Konfigurationsreferenz (Signal)

Vollständige Konfiguration: Configuration

Provider-Optionen:

  • channels.signal.enabled: Kanal-Start aktivieren/deaktivieren.
  • channels.signal.account: E.164 für das Bot-Konto.
  • channels.signal.cliPath: Pfad zu signal-cli.
  • channels.signal.httpUrl: Vollständige Daemon-URL (überschreibt host/port).
  • channels.signal.httpHost, channels.signal.httpPort: Daemon-Bind (Standard 127.0.0.1:8080).
  • channels.signal.autoStart: Daemon automatisch starten (Standard true wenn httpUrl nicht gesetzt).
  • channels.signal.startupTimeoutMs: Start-Warte-Timeout in ms (Obergrenze 120000).
  • channels.signal.receiveMode: on-start | manual.
  • channels.signal.ignoreAttachments: Anhang-Downloads überspringen.
  • channels.signal.ignoreStories: Stories vom Daemon ignorieren.
  • channels.signal.sendReadReceipts: Lesebestätigungen weiterleiten.
  • channels.signal.dmPolicy: pairing | allowlist | open | disabled (Standard: pairing).
  • channels.signal.allowFrom: DM-Allowlist (E.164 oder uuid:<id>). open erfordert "*". Signal hat keine Benutzernamen; verwende Telefon-/UUID-IDs.
  • channels.signal.groupPolicy: open | allowlist | disabled (Standard: allowlist).
  • channels.signal.groupAllowFrom: Gruppen-Absender-Allowlist.
  • channels.signal.groups: Pro-Gruppen-Überschreibungen nach Signal-Gruppen-ID (oder "*"). Unterstützte Felder: requireMention, tools, toolsBySender.
  • channels.signal.accounts.<id>.groups: Pro-Konto-Version von channels.signal.groups für Multi-Account-Setups.
  • channels.signal.historyLimit: Max. Gruppennachrichten als Kontext (0 deaktiviert).
  • channels.signal.dmHistoryLimit: DM-Verlaufslimit in Benutzer-Turns. Pro-Benutzer-Überschreibungen: channels.signal.dms["<phone_or_uuid>"].historyLimit.
  • channels.signal.textChunkLimit: Ausgehende Blockgröße (Zeichen).
  • channels.signal.chunkMode: length (Standard) oder newline, um an Leerzeilen (Absatzgrenzen) vor dem Längen-Chunking aufzuteilen.
  • channels.signal.mediaMaxMb: Medien-Obergrenze ein-/ausgehend (MB).

Zugehörige globale Optionen:

  • agents.list[].groupChat.mentionPatterns (Signal unterstützt keine nativen Mentions).
  • messages.groupChat.mentionPatterns (globaler Fallback).
  • messages.responsePrefix.