@openclaw/signal). Il Gateway comunica con signal-cli tramite HTTP: mediante il daemon nativo (JSON-RPC + SSE) oppure il container bbernhard/signal-cli-rest-api (REST + WebSocket). OpenClaw non incorpora libsignal.
Il modello dei numeri (leggere prima questa sezione)
- Il Gateway si connette a un dispositivo Signal: l’account
signal-cli. - L’esecuzione del bot sul proprio account Signal personale fa sì che ignori i propri messaggi (protezione dai loop).
- Per ottenere il comportamento «invio un messaggio al bot e questo risponde», utilizzare un numero separato per il bot.
Installazione
openclaw plugins install clawhub:@openclaw/signal o npm:@openclaw/signal. plugins install registra e abilita il plugin; non è necessario un passaggio enable separato. Consultare Plugin per le regole generali di installazione.
Configurazione rapida
1
Scegliere un numero
Utilizzare un numero Signal separato per il bot (scelta consigliata).
2
Installare il plugin
3
Eseguire la configurazione guidata
signal-cli è disponibile in PATH e, se manca, propone di installarlo: scarica la build nativa ufficiale GraalVM su Linux x86-64 oppure esegue l’installazione tramite Homebrew su macOS e altre architetture. Quindi richiede il numero del bot e il percorso signal-cli.Per la configurazione non interattiva, openclaw channels add --channel signal accetta anche --signal-number <e164> per il numero di telefono del bot, oltre a --http-host <host> e --http-port <port> per l’endpoint del daemon Signal (valore predefinito 127.0.0.1:8080).4
Collegare o registrare l'account
- Collegamento tramite codice QR (metodo più rapido):
signal-cli link -n "OpenClaw", quindi eseguire la scansione con Signal. Consultare il Percorso A. - Registrazione tramite SMS: numero dedicato con captcha e verifica tramite SMS. Consultare il Percorso B.
5
Verificare ed eseguire l'associazione
openclaw pairing approve signal <CODE>.
Supporto multi-account: utilizzare
channels.signal.accounts con una configurazione per ciascun account e name facoltativo. Consultare Canali multi-account per il modello condiviso.
Funzionamento
- Instradamento deterministico: le risposte vengono sempre rinviate a Signal.
- I messaggi diretti condividono la sessione principale dell’agente; i gruppi sono isolati (
agent:<agentId>:signal:group:<groupId>). - Per impostazione predefinita, Signal può scrivere gli aggiornamenti della configurazione attivati da
/config set|unset(richiedecommands.config: true). Disabilitare questa funzione conchannels.signal.configWrites: false.
Percorso di configurazione A: collegare un account Signal esistente (codice QR)
- Installare
signal-cli(build JVM o nativa) oppure consentire aopenclaw channels adddi installarlo. - Collegare un account del bot:
signal-cli link -n "OpenClaw", quindi eseguire la scansione del codice QR in Signal. - Configurare Signal e avviare il Gateway.
Percorso di configurazione B: registrare un numero dedicato per il bot (SMS, Linux)
Utilizzare questa procedura per un numero dedicato al bot anziché collegare l’account di un’app Signal esistente. La procedura seguente è stata verificata su Ubuntu 24.- Procurarsi un numero in grado di ricevere SMS (o la verifica vocale per i numeri di rete fissa). Un numero dedicato al bot evita conflitti tra account o sessioni.
- Installare
signal-clisull’host del Gateway:
signal-cli-${VERSION}.tar.gz), installare prima un JRE. Mantenere signal-cli aggiornato; il progetto upstream segnala che le versioni meno recenti possono smettere di funzionare quando cambiano le API dei server Signal.
- Registrare e verificare il numero:
- Aprire
https://signalcaptchas.org/registration/generate.html. - Completare il captcha e copiare la destinazione del collegamento
signalcaptcha://...da “Open Signal”. - Se possibile, eseguire l’operazione dallo stesso indirizzo IP esterno della sessione del browser (i token captcha scadono rapidamente).
- Registrare e verificare immediatamente:
- Configurare OpenClaw, riavviare il Gateway e verificare il canale:
- Associare il mittente dei messaggi diretti:
- Inviare un messaggio qualsiasi al numero del bot.
- Approvare sul server:
openclaw pairing approve signal <PAIRING_CODE>. - Salvare il numero del bot come contatto sul telefono per evitare “Unknown contact”.
- README di
signal-cli:https://github.com/AsamK/signal-cli - Procedura captcha:
https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha - Procedura di collegamento:
https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)
Modalità daemon esterno (httpUrl)
Per gestire autonomamentesignal-cli (avvii a freddo lenti della JVM, inizializzazione del container, CPU condivise), eseguire separatamente il daemon e indirizzare OpenClaw verso di esso:
channels.signal.startupTimeoutMs.
Modalità container (bbernhard/signal-cli-rest-api)
Anziché eseguiresignal-cli in modo nativo, utilizzare il container Docker bbernhard/signal-cli-rest-api, che espone signal-cli mediante un’interfaccia REST + WebSocket.
Requisiti:
- Il container deve essere eseguito con
MODE=json-rpcper ricevere i messaggi in tempo reale. - Registrare o collegare l’account Signal all’interno del container prima di connettere OpenClaw.
docker-compose.yml:
apiMode determina il protocollo utilizzato da OpenClaw:
Quando
apiMode è "auto", OpenClaw memorizza nella cache per 30 secondi la modalità rilevata per ciascun URL del daemon, così da evitare verifiche ripetute (la modalità nativa ha la precedenza quando entrambi i trasporti funzionano correttamente). La ricezione tramite container viene selezionata per lo streaming solo dopo che /v1/receive/{account} esegue l’upgrade a WebSocket, operazione che richiede MODE=json-rpc.
La modalità container supporta le stesse operazioni Signal della modalità nativa quando il container espone API corrispondenti: invio, ricezione, allegati, indicatori di digitazione, conferme di lettura e visualizzazione, reazioni, gruppi e testo con stili. OpenClaw converte le chiamate RPC native di Signal nei payload REST del container, inclusi gli ID gruppo group.{base64(internal_id)} e text_mode: "styled" per il testo formattato.
Note operative:
- Utilizzare
autoStart: falsecon la modalità container; OpenClaw non deve avviare un daemon nativo quando è selezionatoapiMode: "container". - Utilizzare
MODE=json-rpcper la ricezione.MODE=normalpuò far apparire/v1/aboutoperativo, ma/v1/receive/{account}non eseguirà l’upgrade a WebSocket, pertanto OpenClaw non selezionerà lo streaming di ricezione del container in modalitàauto. - Impostare
apiMode: "container"quandohttpUrlpunta all’API REST bbernhard,"native"quando punta a JSON-RPC/SSE nativo disignal-clie"auto"quando la distribuzione può variare. - I download degli allegati in modalità container rispettano gli stessi limiti di byte per i contenuti multimediali della modalità nativa. Le risposte sovradimensionate vengono rifiutate prima di essere memorizzate completamente nel buffer quando il server invia
Content-Length, altrimenti durante lo streaming.
Controllo degli accessi (messaggi diretti + gruppi)
Messaggi diretti:- Valore predefinito:
channels.signal.dmPolicy = "pairing". - I mittenti sconosciuti ricevono un codice di associazione; i messaggi vengono ignorati finché l’associazione non viene approvata (i codici scadono dopo 1 ora).
- Approvare tramite
openclaw pairing list signaleopenclaw pairing approve signal <CODE>. - L’associazione è lo scambio di token predefinito per i messaggi diretti di Signal. Dettagli: Associazione
- I mittenti identificati solo tramite UUID (da
sourceUuid) vengono memorizzati comeuuid:<id>inchannels.signal.allowFrom.
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromdetermina quali gruppi o mittenti possono attivare le risposte nei gruppi quando è impostatoallowlist; le voci possono essere ID gruppo Signal (non elaborati,group:<id>osignal:group:<id>), numeri di telefono dei mittenti, valoriuuid:<id>oppure*.channels.signal.groups["<group-id>" | "*"]può ignorare il comportamento dei gruppi medianterequireMention,toolsetoolsBySender.- Utilizzare
channels.signal.accounts.<id>.groupsper le sostituzioni specifiche di ciascun account nelle configurazioni multi-account. - L’inserimento di un gruppo Signal nell’elenco consentito tramite
groupAllowFromnon disabilita automaticamente il requisito delle menzioni. Una vocechannels.signal.groups["<group-id>"]configurata in modo specifico elabora ogni messaggio del gruppo, a meno che non sia impostatorequireMention=true. - Con
requireMention=true, le @menzioni native di Signal vengono confrontate, tramite i metadati strutturati delle menzioni, con il numero di telefono oaccountUuiddell’account del bot. I valorimentionPatternsconfigurati rimangono un metodo alternativo basato su testo normale. - Nota sull’esecuzione: se
channels.signalè completamente assente, durante l’esecuzione viene usatogroupPolicy="allowlist"come alternativa per i controlli dei gruppi (anche se è impostatochannels.defaults.groupPolicy).
Funzionamento (comportamento)
- Modalità nativa:
signal-cliviene eseguito come daemon; il Gateway legge gli eventi tramite SSE. - Modalità container: il Gateway invia tramite API REST e riceve tramite WebSocket.
- I messaggi in entrata vengono normalizzati nell’envelope condiviso del canale.
- Le risposte vengono sempre instradate allo stesso numero o gruppo.
- Le risposte ai messaggi in entrata includono i metadati di citazione nativi di Signal quando il backend accetta il timestamp e l’autore del messaggio in entrata; se i metadati di citazione sono assenti o vengono rifiutati, OpenClaw invia la risposta come messaggio normale.
- Configurare l’uso delle citazioni native con
channels.signal.replyToMode = off | first | all | batchedoppure conchannels.signal.replyToModeByChatType.direct/groupper le sostituzioni specifiche per tipo di chat. I valori a livello di account inchannels.signal.accounts.<id>hanno la precedenza.
Contenuti multimediali + limiti
- Il testo in uscita viene suddiviso in blocchi secondo
channels.signal.textChunkLimit(valore predefinito 4000). - Suddivisione facoltativa in corrispondenza delle nuove righe: impostare
channels.signal.streaming.chunkMode="newline"per suddividere in corrispondenza delle righe vuote (limiti dei paragrafi) prima della suddivisione per lunghezza. - Gli allegati sono supportati (base64 recuperato da
signal-cli). - Gli allegati delle note vocali usano il nome file
signal-clicome ripiego MIME quandocontentTypeè assente, affinché la trascrizione audio possa comunque classificare i memo vocali AAC. - Limite predefinito per i contenuti multimediali:
channels.signal.mediaMaxMb(valore predefinito 8). - Usare
channels.signal.ignoreAttachmentsper ignorare il download dei contenuti multimediali. - Il contesto della cronologia dei gruppi usa
channels.signal.historyLimit(ochannels.signal.accounts.*.historyLimit), con ripiego sumessages.groupChat.historyLimit. Impostare0per disabilitarlo (valore predefinito 50).
Indicatori di digitazione + conferme di lettura
- Indicatori di digitazione: OpenClaw invia segnali di digitazione tramite
signal-cli sendTypinge li aggiorna mentre è in corso la generazione di una risposta. - Conferme di lettura: quando
channels.signal.sendReadReceiptsè true, OpenClaw inoltra le conferme di lettura per i messaggi diretti consentiti. signal-clinon espone le conferme di lettura per i gruppi.
Reazioni allo stato del ciclo di vita
Impostaremessages.statusReactions.enabled: true per consentire a Signal di mostrare il ciclo di vita condiviso delle reazioni in coda/elaborazione/strumento/compaction/completato/errore nei turni in entrata. Signal usa il timestamp del messaggio in entrata come destinazione della reazione; le reazioni di gruppo vengono inviate con l’ID del gruppo Signal e 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). Impostare channels.signal.reactionLevel: "off" per disabilitare le reazioni di stato di Signal.
messages.removeAckAfterReply: true elimina la reazione di stato finale dopo il tempo di permanenza configurato. In caso contrario, Signal ripristina la reazione di conferma iniziale dopo lo stato finale di completamento/errore.
Reazioni (strumento messaggi)
Usaremessage action=react con channel=signal.
- Destinazioni: E.164 o UUID del mittente (usare
uuid:<id>dall’output dell’associazione; funziona anche un UUID senza prefisso). messageIdè il timestamp Signal del messaggio a cui si reagisce.- Le reazioni di gruppo richiedono
targetAuthorotargetAuthorUuid.
channels.signal.actions.reactions: abilita/disabilita le azioni di reazione (valore predefinito true).channels.signal.reactionLevel:off | ack | minimal | extensive(valore predefinitominimal).off/ackdisabilita le reazioni dell’agente (lo strumento messaggireactrestituisce errori).minimal/extensiveabilita le reazioni dell’agente e imposta il livello di indicazioni.
- Sostituzioni per account:
channels.signal.accounts.<id>.actions.reactions,channels.signal.accounts.<id>.reactionLevel.
Reazioni di approvazione
Le richieste di approvazione per exec e Plugin di Signal usano i blocchi di instradamento di primo livelloapprovals.exec e approvals.plugin. Signal non dispone di un blocco channels.signal.execApprovals.
👍approva una volta.👎rifiuta.- Usare
/approve <id> allow-alwaysquando una richiesta offre un’approvazione persistente.
channels.signal.allowFrom, channels.signal.defaultTo o dai campi corrispondenti a livello di account. Le richieste di approvazione exec dirette nella stessa chat possono comunque impedire il ripiego locale duplicato /approve senza approvatori espliciti; per le approvazioni di gruppo senza approvatori, il ripiego locale rimane visibile.
Destinazioni di consegna (CLI/Cron)
- Messaggi diretti:
signal:+15551234567(o E.164 semplice). - Messaggi diretti tramite UUID:
uuid:<id>(o UUID senza prefisso). - Gruppi:
signal:group:<groupId>. - Nomi utente:
username:<name>(se supportati dall’account Signal).
Alias
Configurare alias per assegnare nomi stabili alle destinazioni Signal ricorrenti. Gli alias sono solo configurazioni lato OpenClaw; non creano né modificano i contatti Signal.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
Eseguire prima questa sequenza:- Daemon raggiungibile ma nessuna risposta: verificare le impostazioni dell’account/daemon (
httpUrl,account) e la modalità di ricezione. - Messaggi diretti ignorati: il mittente è in attesa dell’approvazione dell’associazione.
- Messaggi di gruppo ignorati: i criteri di accesso per mittente/menzione del gruppo bloccano la consegna.
- Errori di convalida della configurazione dopo le modifiche: eseguire
openclaw doctor --fix. - Signal assente dalla diagnostica: verificare
channels.signal.enabled: true.
Note sulla sicurezza
signal-cliarchivia localmente le chiavi dell’account (in genere~/.local/share/signal-cli/data/).- Eseguire il backup dello stato dell’account Signal prima di migrare o ricostruire il server.
- Mantenere
channels.signal.dmPolicy: "pairing", a meno che non si desideri esplicitamente un accesso più ampio ai messaggi diretti. - La verifica tramite SMS è necessaria solo per i flussi di registrazione o ripristino, ma la perdita del controllo del numero/account può complicare una nuova registrazione.
Riferimento della configurazione (Signal)
Configurazione completa: Configurazione Opzioni del provider:channels.signal.enabled: abilita/disabilita l’avvio del canale.channels.signal.apiMode:auto | native | container(valore predefinito: auto). Consultare Modalità container.channels.signal.account: E.164 per l’account del bot.channels.signal.accountUuid: UUID facoltativo dell’account del bot per il rilevamento delle @menzioni native e la protezione dai cicli.channels.signal.cliPath: percorso disignal-cli.channels.signal.configPath: directorysignal-cli --configfacoltativa.channels.signal.httpUrl: URL completo del daemon (sostituisce host/porta).channels.signal.httpHost,channels.signal.httpPort: binding del daemon (valore predefinito127.0.0.1:8080).channels.signal.autoStart: avvio automatico del daemon (valore predefinito true sehttpUrlnon è impostato).channels.signal.startupTimeoutMs: timeout di attesa dell’avvio in ms (min 1000, limite 120000; valore predefinito 30000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: ignora i download degli allegati.channels.signal.ignoreStories: ignora le storie provenienti dal daemon.channels.signal.sendReadReceipts: inoltra le conferme di lettura.channels.signal.dmPolicy:pairing | allowlist | open | disabled(valore predefinito: associazione).channels.signal.allowFrom: elenco consentito per i messaggi diretti (E.164 ouuid:<id>).openrichiede"*". Signal non dispone di nomi utente; usare ID telefonici/UUID.channels.signal.aliases: alias lato OpenClaw per le destinazioni di consegna di messaggi diretti o di gruppo.channels.signal.groupPolicy:open | allowlist | disabled(valore predefinito: elenco consentito).channels.signal.groupAllowFrom: elenco consentito per i gruppi; accetta ID di gruppo Signal (non elaborati,group:<id>osignal:group:<id>), numeri E.164 dei mittenti o valoriuuid:<id>.channels.signal.groups: sostituzioni per gruppo indicizzate in base all’ID del gruppo Signal (o"*"). Campi supportati:requireMention,tools,toolsBySender.channels.signal.accounts.<id>.groups: versione per account dichannels.signal.groupsper configurazioni con più account.channels.signal.accounts.<id>.aliases: alias per account, uniti agli alias di primo livello.channels.signal.replyToMode: modalità di citazione nativa delle risposte,off | first | all | batched(valore predefinito:all).channels.signal.replyToModeByChatType.direct,channels.signal.replyToModeByChatType.group: sostituzioni della citazione nativa delle risposte per tipo di chat.channels.signal.accounts.<id>.replyToMode,channels.signal.accounts.<id>.replyToModeByChatType.direct,channels.signal.accounts.<id>.replyToModeByChatType.group: sostituzioni della citazione delle risposte per account.channels.signal.historyLimit: numero massimo di messaggi di gruppo da includere come contesto (0 disabilita).channels.signal.dmHistoryLimit: limite della cronologia dei messaggi diretti espresso in turni utente. Sostituzioni per utente:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: dimensione dei blocchi in uscita espressa in caratteri (valore predefinito 4000).channels.signal.streaming.chunkMode:length(valore predefinito) onewlineper suddividere in corrispondenza delle righe vuote (limiti dei paragrafi) prima della suddivisione per lunghezza.channels.signal.mediaMaxMb: limite dei contenuti multimediali in entrata/uscita in MB (valore predefinito 8).channels.signal.reactionLevel:off | ack | minimal | extensive(valore predefinitominimal). Consultare Reazioni.channels.signal.reactionNotifications:off | own | all | allowlist(valore predefinitoown) - quando l’agente riceve notifiche delle reazioni in entrata di altri utenti.channels.signal.reactionAllowlist: mittenti le cui reazioni notificano l’agente quandoreactionNotifications: "allowlist".channels.signal.streaming.block.enabled,channels.signal.streaming.block.coalesce: controlli dello streaming in modalità a blocchi condivisi tra i canali. Consultare Streaming.
agents.list[].groupChat.mentionPatterns(fallback in testo normale; le @menzioni native di Signal vengono rilevate dai metadati strutturati quando è configurata l’identità dell’account del bot).messages.groupChat.mentionPatterns(fallback globale).messages.responsePrefix.
Argomenti correlati
- Panoramica dei canali - tutti i canali supportati
- Associazione - autenticazione tramite messaggio diretto e flusso di associazione
- Gruppi - comportamento delle chat di gruppo e controllo tramite menzioni
- Instradamento dei canali - instradamento delle sessioni per i messaggi
- Sicurezza - modello di accesso e rafforzamento della sicurezza