Signal (signal-cli)
Status: Externe CLI-Integration. Der Gateway kommuniziert mit signal-cli über HTTP JSON-RPC + SSE.
Schnellstart (für Einsteiger)
- Nutze eine separate Signal-Nummer für den Bot (empfohlen).
- Installiere
signal-cli(Java erforderlich). - Verknüpfe das Bot-Gerät und starte den Daemon:
signal-cli link -n "OpenClaw"
- Konfiguriere OpenClaw und starte den Gateway.
Minimale Konfiguration:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
Was ist das?
- Signal Channel über
signal-cli(nicht eingebettetes libsignal). - Deterministisches Routing: Antworten gehen immer zurück zu Signal.
- DMs teilen sich die Haupt-Session des Agent; Gruppen sind isoliert (
agent:<agentId>:signal:group:<groupId>).
Config-Schreibzugriff
Standardmäßig darf Signal Config-Updates durchführen, die durch /config set|unset ausgelöst werden (erfordert commands.config: true).
Deaktivieren mit:
{
channels: { signal: { configWrites: false } },
}
Das Nummernmodell (wichtig)
- Der Gateway verbindet sich mit einem Signal-Gerät (dem
signal-cli-Account). - Wenn du den Bot auf deinem persönlichen Signal-Account laufen lässt, ignoriert er deine eigenen Nachrichten (Loop-Schutz).
- Für “Ich schreibe dem Bot und er antwortet” brauchst du eine separate Bot-Nummer.
Setup (schneller Weg)
- Installiere
signal-cli(Java erforderlich). - Verknüpfe einen Bot-Account:
signal-cli link -n "OpenClaw"und scanne dann den QR-Code in Signal.
- Konfiguriere Signal und starte den Gateway.
Beispiel:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
Multi-Account-Unterstützung: Nutze channels.signal.accounts mit individueller Konfiguration pro Account und optionalem name. Das gemeinsame Muster findest du unter gateway/configuration.
Externer Daemon-Modus (httpUrl)
Wenn du signal-cli selbst verwalten möchtest (langsame JVM-Kaltstarts, Container-Init oder geteilte CPUs), führe den Daemon separat aus und weise OpenClaw darauf hin:
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}
Damit wird das automatische Spawnen und die Startup-Wartezeit in OpenClaw übersprungen. Bei langsamen Starts beim Auto-Spawning setze channels.signal.startupTimeoutMs.
Zugriffskontrolle (DMs + Gruppen)
DMs:
- Standard:
channels.signal.dmPolicy = "pairing". - Unbekannte Absender erhalten einen Pairing-Code; Nachrichten werden ignoriert, bis sie freigegeben sind (Codes laufen nach 1 Stunde ab).
- Freigabe über:
openclaw pairing list signalopenclaw pairing approve signal <CODE>
- Pairing ist der Standard-Token-Austausch für Signal-DMs. Details: Pairing
- UUID-only-Absender (von
sourceUuid) werden alsuuid:<id>inchannels.signal.allowFromgespeichert.
Gruppen:
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromsteuert, wer in Gruppen triggern kann, wennallowlistgesetzt ist.
Wie es funktioniert (Verhalten)
signal-cliläuft als Daemon; der Gateway liest Events via SSE.- Eingehende Nachrichten werden in das gemeinsame Channel-Envelope normalisiert.
- Antworten werden immer zurück zur gleichen Nummer oder Gruppe geroutet.
Medien + Limits
- Ausgehender Text wird in Chunks von
channels.signal.textChunkLimitaufgeteilt (Standard 4000). - Optionales Newline-Chunking: Setze
channels.signal.chunkMode="newline", um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird. - Attachments werden unterstützt (base64 von
signal-cliabgerufen). - Standard-Medien-Cap:
channels.signal.mediaMaxMb(Standard 8). - Nutze
channels.signal.ignoreAttachments, um Medien-Downloads zu überspringen. - Gruppen-Verlaufskontext nutzt
channels.signal.historyLimit(oderchannels.signal.accounts.*.historyLimit), mit Fallback aufmessages.groupChat.historyLimit. Setze0zum Deaktivieren (Standard 50).
Tippindikatoren + Lesebestätigungen
- Tippindikatoren: OpenClaw sendet Tippsignale via
signal-cli sendTypingund aktualisiert sie, während eine Antwort läuft. - Lesebestätigungen: Wenn
channels.signal.sendReadReceiptsauf true steht, leitet OpenClaw Lesebestätigungen für erlaubte DMs weiter. - Signal-cli stellt keine Lesebestätigungen für Gruppen bereit.
Reaktionen (message tool)
- Nutze
message action=reactmitchannel=signal. - Ziele: Absender-E.164 oder UUID (nutze
uuid:<id>aus der Pairing-Ausgabe; blanke UUID funktioniert auch). messageIdist der Signal-Timestamp der Nachricht, auf die du reagierst.- Gruppenreaktionen erfordern
targetAuthorodertargetAuthorUuid.
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/ackdeaktiviert Agent-Reaktionen (message toolreactgibt einen Fehler).minimal/extensiveaktiviert Agent-Reaktionen und setzt das Guidance-Level.
- Pro-Account-Overrides:
channels.signal.accounts.<id>.actions.reactions,channels.signal.accounts.<id>.reactionLevel.
Zustellziele (CLI/cron)
- DMs:
signal:+15551234567(oder blanke E.164). - UUID-DMs:
uuid:<id>(oder blanke UUID). - Gruppen:
signal:group:<groupId>. - Usernames:
username:<name>(falls von deinem Signal-Account unterstützt).
Konfigurationsreferenz (Signal)
Vollständige Konfiguration: Configuration
Provider-Optionen:
channels.signal.enabled: Channel-Startup aktivieren/deaktivieren.channels.signal.account: E.164 für den Bot-Account.channels.signal.cliPath: Pfad zusignal-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 spawnen (Standard true, wennhttpUrlnicht gesetzt).channels.signal.startupTimeoutMs: Startup-Wartezeit-Timeout in ms (max 120000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: Attachment-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 oderuuid:<id>).openerfordert"*". Signal hat keine Usernames; nutze Telefon-/UUID-IDs.channels.signal.groupPolicy:open | allowlist | disabled(Standard: allowlist).channels.signal.groupAllowFrom: Gruppen-Absender-Allowlist.channels.signal.historyLimit: Max. Gruppennachrichten als Context (0 deaktiviert).channels.signal.dmHistoryLimit: DM-Verlaufslimit in User-Turns. Pro-User-Overrides:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: Ausgehende Chunk-Größe (Zeichen).channels.signal.chunkMode:length(Standard) odernewline, um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird.channels.signal.mediaMaxMb: Eingehende/ausgehende Medien-Cap (MB).
Verwandte globale Optionen:
agents.list[].groupChat.mentionPatterns(Signal unterstützt keine nativen Mentions).messages.groupChat.mentionPatterns(globaler Fallback).messages.responsePrefix.