Mainstream messaging

Signal

Stato: integrazione CLI esterna. Gateway comunica con signal-cli tramite HTTP: demone nativo (JSON-RPC + SSE) oppure container bbernhard/signal-cli-rest-api (REST + WebSocket).

Prerequisiti

  • OpenClaw installato sul tuo server (il flusso Linux sotto è stato testato su Ubuntu 24).
  • Uno tra:
    • signal-cli disponibile sull'host (modalità nativa), oppure
    • container Docker bbernhard/signal-cli-rest-api (modalità container).
  • Un numero di telefono che possa ricevere un SMS di verifica (per il percorso di registrazione via SMS).
  • Accesso al browser per il captcha di Signal (signalcaptchas.org) durante la registrazione.

Configurazione rapida (principianti)

  1. Usa un numero Signal separato per il bot (consigliato).
  2. Installa il Plugin OpenClaw:
bash
openclaw plugins install @openclaw/signal
  1. Installa signal-cli (Java è richiesto se usi la build JVM).
  2. Scegli un percorso di configurazione:
    • Percorso A (collegamento QR): signal-cli link -n "OpenClaw" e scansiona con Signal.
    • Percorso B (registrazione SMS): registra un numero dedicato con captcha + verifica SMS.
  3. Configura OpenClaw e riavvia il Gateway.
  4. Invia un primo DM e approva l'abbinamento (openclaw pairing approve signal <CODE>).

Configurazione minima:

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

Riferimento dei campi:

Campo Descrizione
account Numero di telefono del bot in formato E.164 (+15551234567)
cliPath Percorso di signal-cli (signal-cli se è nel PATH)
configPath Directory di configurazione di signal-cli passata come --config
dmPolicy Criterio di accesso ai DM (pairing consigliato)
allowFrom Numeri di telefono o valori uuid:<id> autorizzati a inviare DM

Che cos'è

  • Canale Signal tramite signal-cli (non libsignal incorporato).
  • Routing deterministico: le risposte tornano sempre a Signal.
  • I DM condividono la sessione principale dell'agente; i gruppi sono isolati (agent:<agentId>:signal:group:<groupId>).

Scritture di configurazione

Per impostazione predefinita, Signal può scrivere aggiornamenti di configurazione attivati da /config set|unset (richiede commands.config: true).

Disabilita con:

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

Il modello dei numeri (importante)

  • Il Gateway si connette a un dispositivo Signal (l'account signal-cli).
  • Se esegui il bot sul tuo account Signal personale, ignorerà i tuoi messaggi (protezione dai loop).
  • Per "scrivo al bot e lui risponde", usa un numero bot separato.

Percorso di configurazione A: collega un account Signal esistente (QR)

  1. Installa signal-cli (build JVM o nativa).
  2. Collega un account bot:
    • signal-cli link -n "OpenClaw" quindi scansiona il QR in Signal.
  3. Configura Signal e avvia il Gateway.

Esempio:

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

Supporto multi-account: usa channels.signal.accounts con configurazione per account e name opzionale. Vedi gateway/configuration per il modello condiviso.

Percorso di configurazione B: registra un numero bot dedicato (SMS, Linux)

Usa questo percorso quando vuoi un numero bot dedicato invece di collegare un account dell'app Signal esistente.

  1. Procurati un numero che possa ricevere SMS (o verifica vocale per linee fisse).
    • Usa un numero bot dedicato per evitare conflitti di account/sessione.
  2. Installa signal-cli sull'host del Gateway:
bash
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 /optsudo ln -sf /opt/signal-cli /usr/local/bin/signal-cli --version

Se usi la build JVM (signal-cli-${VERSION}.tar.gz), installa prima JRE 25+. Mantieni signal-cli aggiornato; upstream segnala che le vecchie release possono smettere di funzionare quando le API server di Signal cambiano.

  1. Registra e verifica il numero:
bash
signal-cli -a +&lt;BOT_PHONE_NUMBER&gt; register

Se il captcha è richiesto:

  1. Apri https://signalcaptchas.org/registration/generate.html.
  2. Completa il captcha, copia la destinazione del link signalcaptcha://... da "Open Signal".
  3. Esegui dal medesimo IP esterno della sessione del browser quando possibile.
  4. Esegui di nuovo la registrazione immediatamente (i token captcha scadono rapidamente):
bash
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. Configura OpenClaw, riavvia il Gateway, verifica il canale:
bash
# If you run the gateway as a user systemd service:systemctl --user restart openclaw-gateway.service # Then verify:openclaw doctoropenclaw channels status --probe
  1. Abbina il mittente DM:
    • Invia qualsiasi messaggio al numero del bot.
    • Approva il codice sul server: openclaw pairing approve signal &lt;PAIRING_CODE&gt;.
    • Salva il numero del bot come contatto sul telefono per evitare "Unknown contact".

Riferimenti upstream:

  • README di signal-cli: https://github.com/AsamK/signal-cli
  • Flusso captcha: https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • Flusso di collegamento: https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

Modalità demone esterno (httpUrl)

Se vuoi gestire signal-cli autonomamente (avvii JVM a freddo lenti, inizializzazione container o CPU condivise), esegui il demone separatamente e indirizza OpenClaw a esso:

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

Questo salta l'avvio automatico e l'attesa di startup dentro OpenClaw. Per avvii lenti durante l'avvio automatico, imposta channels.signal.startupTimeoutMs.

Modalità container (bbernhard/signal-cli-rest-api)

Invece di eseguire signal-cli nativamente, puoi usare il container Docker bbernhard/signal-cli-rest-api. Questo incapsula signal-cli dietro un'API REST e un'interfaccia WebSocket.

Requisiti:

  • Il container deve essere eseguito con MODE=json-rpc per la ricezione dei messaggi in tempo reale.
  • Registra o collega il tuo account Signal dentro il container prima di connettere OpenClaw.

Servizio docker-compose.yml di esempio:

yaml
signal-cli:  image: bbernhard/signal-cli-rest-api:latest  environment:    MODE: json-rpc  ports:    - "8080:8080"  volumes:    - signal-cli-data:/home/.local/share/signal-cli

Configurazione OpenClaw:

json5
{  channels: {    signal: {      enabled: true,      account: "+15551234567",      httpUrl: "http://signal-cli:8080",      autoStart: false,      apiMode: "container", // or "auto" to detect automatically    },  },}

Il campo apiMode controlla quale protocollo usa OpenClaw:

Valore Comportamento
"auto" (Predefinito) Sonda entrambi i trasporti; lo streaming valida la ricezione WebSocket del container
"native" Forza signal-cli nativo (JSON-RPC su /api/v1/rpc, SSE su /api/v1/events)
"container" Forza il container bbernhard (REST su /v2/send, WebSocket su /v1/receive/{account})

Quando apiMode è "auto", OpenClaw memorizza nella cache la modalità rilevata per 30 secondi per evitare sonde ripetute. La ricezione container viene selezionata per lo streaming solo dopo che /v1/receive/{account} effettua l'upgrade a WebSocket, cosa che richiede MODE=json-rpc.

La modalità container supporta le stesse operazioni del canale Signal della modalità nativa quando il container espone API corrispondenti: invii, ricezioni, allegati, indicatori di digitazione, conferme di lettura/visualizzazione, reazioni, gruppi e testo con stile. OpenClaw traduce le sue chiamate RPC Signal native nei payload REST del container, inclusi gli ID gruppo group.{base64(internal_id)} e text_mode: "styled" per il testo formattato.

Note operative:

  • Usa autoStart: false con la modalità container. OpenClaw non dovrebbe avviare un demone nativo quando apiMode: "container" è selezionato.
  • Usa MODE=json-rpc per la ricezione. MODE=normal può far apparire sano /v1/about, ma /v1/receive/{account} non effettua l'upgrade a WebSocket, quindi OpenClaw non selezionerà lo streaming di ricezione container in modalità auto.
  • Imposta apiMode: "container" quando sai che httpUrl punta all'API REST di bbernhard. Imposta apiMode: "native" quando sai che punta a JSON-RPC/SSE di signal-cli nativo. Usa "auto" quando il deployment può variare.
  • I download degli allegati container rispettano gli stessi limiti di byte per i media della modalità nativa. Le risposte troppo grandi vengono rifiutate prima di essere bufferizzate completamente quando il server invia Content-Length, e altrimenti durante lo streaming.

Controllo degli accessi (DM + gruppi)

DM:

  • Predefinito: channels.signal.dmPolicy = "pairing".
  • I mittenti sconosciuti ricevono un codice di abbinamento; i messaggi vengono ignorati finché non sono approvati (i codici scadono dopo 1 ora).
  • Approva tramite:
    • openclaw pairing list signal
    • openclaw pairing approve signal &lt;CODE&gt;
  • L'abbinamento è lo scambio di token predefinito per i DM Signal. Dettagli: Abbinamento
  • I mittenti solo UUID (da sourceUuid) sono memorizzati come uuid:<id> in channels.signal.allowFrom.

Gruppi:

  • channels.signal.groupPolicy = open | allowlist | disabled.
  • channels.signal.groupAllowFrom controlla quali gruppi o mittenti possono attivare risposte di gruppo quando allowlist è impostato; le voci possono essere ID gruppo Signal (grezzi, group:<id> o signal:group:<id>), numeri di telefono dei mittenti, valori uuid:<id> o *.
  • channels.signal.groups["<group-id>" | "*"] può sovrascrivere il comportamento del gruppo con requireMention, tools e toolsBySender.
  • Usa channels.signal.accounts.<id>.groups per override per account nelle configurazioni multi-account.
  • L'inserimento di un gruppo Signal nell'allowlist tramite groupAllowFrom non disabilita di per sé il vincolo della menzione. Una voce channels.signal.groups["<group-id>"] configurata specificamente elabora ogni messaggio del gruppo a meno che requireMention=true sia impostato.
  • Nota di runtime: se channels.signal manca completamente, il runtime ripiega su groupPolicy="allowlist" per i controlli di gruppo (anche se channels.defaults.groupPolicy è impostato).

Come funziona (comportamento)

  • Modalità nativa: signal-cli viene eseguito come demone; il Gateway legge gli eventi tramite SSE.
  • Modalità container: il Gateway invia tramite API REST e riceve tramite WebSocket.
  • I messaggi in ingresso vengono normalizzati nell'envelope del canale condiviso.
  • Le risposte vengono sempre instradate allo stesso numero o gruppo.

Media + limiti

  • Il testo in uscita viene suddiviso in blocchi secondo channels.signal.textChunkLimit (predefinito 4000).
  • Suddivisione opzionale per righe vuote: imposta channels.signal.chunkMode="newline" per dividere sulle righe vuote (confini di paragrafo) prima della suddivisione per lunghezza.
  • Allegati supportati (base64 recuperato da signal-cli).
  • Gli allegati nota vocale usano il nome file di signal-cli come fallback MIME quando contentType manca, così la trascrizione audio può comunque classificare i promemoria vocali AAC.
  • Limite media predefinito: channels.signal.mediaMaxMb (predefinito 8).
  • Usa channels.signal.ignoreAttachments per saltare il download dei media.
  • Il contesto della cronologia di gruppo usa channels.signal.historyLimit (o channels.signal.accounts.*.historyLimit), con fallback a messages.groupChat.historyLimit. Imposta 0 per disabilitare (predefinito 50).

Digitazione + conferme di lettura

  • Indicatori di digitazione: OpenClaw invia segnali di digitazione tramite signal-cli sendTyping e li aggiorna mentre è in corso una risposta.
  • Conferme di lettura: quando channels.signal.sendReadReceipts è true, OpenClaw inoltra le conferme di lettura per i DM consentiti.
  • Signal-cli non espone le conferme di lettura per i gruppi.

Reazioni di stato del ciclo di vita

Imposta messages.statusReactions.enabled: true per consentire a Signal di mostrare il ciclo di vita condiviso delle reazioni queued/thinking/tool/compaction/done/error sui turni in ingresso. Signal usa il timestamp del messaggio in ingresso come destinazione della reazione; le reazioni di gruppo vengono inviate con l'id del gruppo Signal più il mittente originale come autore di destinazione.

Le reazioni di stato richiedono anche una reazione di conferma e un messages.ackReactionScope corrispondente (direct, group-all, group-mentions o all). Imposta channels.signal.reactionLevel: "off" per disabilitare le reazioni di stato di Signal. L'azione react dello strumento messaggio rimane più restrittiva: richiede reactionLevel: "minimal" o "extensive".

messages.removeAckAfterReply: true rimuove la reazione di stato finale dopo il tempo di mantenimento configurato. In caso contrario, Signal ripristina la reazione di conferma iniziale dopo lo stato finale done/error.

Reazioni (strumento messaggio)

  • Usa message action=react con channel=signal.
  • Destinazioni: mittente E.164 o UUID (usa uuid:<id> dall'output di associazione; funziona anche un UUID semplice).
  • messageId è il timestamp Signal del messaggio a cui stai reagendo.
  • Le reazioni di gruppo richiedono targetAuthor o targetAuthorUuid.

Esempi:

Code
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=truemessage action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅

Configurazione:

  • channels.signal.actions.reactions: abilita/disabilita le azioni di reazione (predefinito true).
  • channels.signal.reactionLevel: off | ack | minimal | extensive.
    • off/ack disabilita le reazioni dell'agente (lo strumento messaggio react restituirà un errore).
    • minimal/extensive abilita le reazioni dell'agente e imposta il livello di guida.
  • Override per account: channels.signal.accounts.<id>.actions.reactions, channels.signal.accounts.<id>.reactionLevel.

Reazioni di approvazione

I prompt di approvazione di esecuzione Signal e dei plugin usano i blocchi di instradamento di primo livello approvals.exec e approvals.plugin. Signal non ha un blocco channels.signal.execApprovals.

  • 👍 approva una volta.
  • 👎 nega.
  • Usa /approve <id> allow-always quando una richiesta offre un'approvazione persistente.

La risoluzione delle reazioni di approvazione richiede approvatori Signal espliciti da channels.signal.allowFrom, channels.signal.defaultTo o dai campi corrispondenti a livello di account. I prompt di approvazione exec diretti nella stessa chat possono comunque sopprimere il fallback locale /approve duplicato senza approvatori espliciti; le approvazioni di gruppo senza approvatore mantengono visibile il fallback locale.

Destinazioni di consegna (CLI/cron)

  • DM: signal:+15551234567 (o E.164 semplice).
  • DM UUID: uuid:<id> (o UUID semplice).
  • Gruppi: signal:group:<groupId>.
  • Nomi utente: username:<name> (se supportati dal tuo account Signal).

Alias

Configura gli alias quando vuoi nomi stabili per destinazioni Signal ricorrenti. Gli alias sono solo configurazione lato OpenClaw; non creano né modificano contatti Signal.

json5
{  channels: {    signal: {      aliases: {        me: "+15557654321",        jane: "uuid:123e4567-e89b-12d3-a456-426614174000",        ops: "group:<groupId>",      },      defaultTo: "signal:me",    },  },}

Usa gli alias ovunque siano accettate destinazioni di consegna Signal:

bash
openclaw message send --channel signal --target signal:ops --message "Deployment is complete"

Gli alias per account ereditano gli alias di primo livello e possono aggiungere o sovrascrivere nomi:

json5
{  channels: {    signal: {      aliases: {        me: "+15557654321",      },      accounts: {        work: {          aliases: {            ops: "group:<workGroupId>",          },        },      },    },  },}

openclaw directory peers list --channel signal e openclaw directory groups list --channel signal elencano gli alias configurati. La directory Signal è basata sulla configurazione; non interroga in tempo reale i contatti Signal né modifica l'account Signal.

Risoluzione dei problemi

Esegui prima questa sequenza:

bash
openclaw statusopenclaw gateway statusopenclaw logs --followopenclaw doctoropenclaw channels status --probe

Poi conferma lo stato di associazione dei DM, se necessario:

bash
openclaw pairing list signal

Errori comuni:

  • Demone raggiungibile ma nessuna risposta: verifica le impostazioni account/demone (httpUrl, account) e la modalità di ricezione.
  • DM ignorati: il mittente è in attesa di approvazione dell'associazione.
  • Messaggi di gruppo ignorati: il gating per mittente/menzione del gruppo blocca la consegna.
  • Errori di validazione della configurazione dopo modifiche: esegui openclaw doctor --fix.
  • Signal assente dalla diagnostica: conferma channels.signal.enabled: true.

Controlli aggiuntivi:

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

Per il flusso di triage: /channels/troubleshooting.

Note sulla sicurezza

  • signal-cli archivia localmente le chiavi dell'account (in genere ~/.local/share/signal-cli/data/).
  • Esegui il backup dello stato dell'account Signal prima di una migrazione o ricostruzione del server.
  • Mantieni channels.signal.dmPolicy: "pairing" salvo che tu voglia esplicitamente un accesso DM più ampio.
  • La verifica via SMS è necessaria solo per i flussi di registrazione o recupero, ma perdere il controllo del numero/account può complicare la nuova registrazione.

Riferimento di configurazione (Signal)

Configurazione completa: Configurazione

Opzioni del provider:

  • channels.signal.enabled: abilita/disabilita l'avvio del canale.
  • channels.signal.apiMode: auto | native | container (predefinito: auto). Vedi Modalità container.
  • channels.signal.account: E.164 per l'account del bot.
  • channels.signal.cliPath: percorso di signal-cli.
  • channels.signal.configPath: directory opzionale signal-cli --config.
  • channels.signal.httpUrl: URL completo del demone (sovrascrive host/porta).
  • channels.signal.httpHost, channels.signal.httpPort: bind del demone (predefinito 127.0.0.1:8080).
  • channels.signal.autoStart: avvia automaticamente il demone (predefinito true se httpUrl non è impostato).
  • channels.signal.startupTimeoutMs: timeout di attesa dell'avvio in ms (limite 120000).
  • channels.signal.receiveMode: on-start | manual.
  • channels.signal.ignoreAttachments: salta il download degli allegati.
  • channels.signal.ignoreStories: ignora le storie dal demone.
  • channels.signal.sendReadReceipts: inoltra le conferme di lettura.
  • channels.signal.dmPolicy: pairing | allowlist | open | disabled (predefinito: pairing).
  • channels.signal.allowFrom: allowlist DM (E.164 o uuid:<id>). open richiede "*". Signal non ha nomi utente; usa gli ID telefono/UUID.
  • channels.signal.aliases: alias lato OpenClaw per destinazioni di consegna DM o di gruppo.
  • channels.signal.groupPolicy: open | allowlist | disabled (predefinito: allowlist).
  • channels.signal.groupAllowFrom: allowlist di gruppo; accetta ID di gruppo Signal (raw, group:<id> o signal:group:<id>), numeri E.164 dei mittenti o valori uuid:<id>.
  • channels.signal.groups: override per gruppo indicizzati per id del gruppo Signal (o "*"). Campi supportati: requireMention, tools, toolsBySender.
  • channels.signal.accounts.<id>.groups: versione per account di channels.signal.groups per configurazioni multi-account.
  • channels.signal.accounts.<id>.aliases: alias per account, uniti agli alias di primo livello.
  • channels.signal.historyLimit: numero massimo di messaggi di gruppo da includere come contesto (0 disabilita).
  • channels.signal.dmHistoryLimit: limite della cronologia DM nei turni utente. Override per utente: channels.signal.dms["<phone_or_uuid>"].historyLimit.
  • channels.signal.textChunkLimit: dimensione dei blocchi in uscita (caratteri).
  • channels.signal.chunkMode: length (predefinito) o newline per dividere sulle righe vuote (confini di paragrafo) prima della suddivisione per lunghezza.
  • channels.signal.mediaMaxMb: limite dei media in ingresso/uscita (MB).

Opzioni globali correlate:

  • agents.list[].groupChat.mentionPatterns (Signal non supporta le menzioni native).
  • messages.groupChat.mentionPatterns (fallback globale).
  • messages.responsePrefix.

Correlati

Was this useful?
On this page

On this page