Signal (signal-cli)
Status: integração com CLI externo. O gateway se comunica com signal-cli via HTTP JSON-RPC + SSE.
Pré-requisitos
- OpenClaw instalado no seu servidor (fluxo Linux abaixo testado no Ubuntu 24).
signal-clidisponível no host onde o gateway roda.- Um número de telefone que possa receber um SMS de verificação (para o caminho de registro via SMS).
- Acesso ao navegador para captcha do Signal (
signalcaptchas.org) durante o registro.
Configuração rápida (iniciante)
- Use um número Signal separado para o bot (recomendado).
- Instale
signal-cli(Java necessário se usar o build JVM). - Escolha um caminho de configuração:
- Caminho A (link QR):
signal-cli link -n "OpenClaw"e escaneie com o Signal. - Caminho B (registro SMS): registre um número dedicado com captcha + verificação SMS.
- Caminho A (link QR):
- Configure o OpenClaw e reinicie o gateway.
- Envie uma primeira DM e aprove o pareamento (
openclaw pairing approve signal <CODE>).
Configuração mínima:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
Referência de campos:
| Campo | Descrição |
|---|---|
account | Número do bot no formato E.164 (+15551234567) |
cliPath | Caminho para signal-cli (signal-cli se no PATH) |
dmPolicy | Política de acesso a DM (pairing recomendado) |
allowFrom | Números de telefone ou valores uuid:<id> permitidos para DM |
O que é
- Canal Signal via
signal-cli(não libsignal embarcado). - Roteamento determinístico: respostas sempre voltam para o Signal.
- DMs compartilham a sessão principal do agente; grupos são isolados (
agent:<agentId>:signal:group:<groupId>).
Config writes
Por padrão, o Signal permite escrita de configuração acionada por /config set|unset (requer commands.config: true).
Desabilite com:
{
channels: { signal: { configWrites: false } },
}
O modelo de número (importante)
- O gateway se conecta a um dispositivo Signal (a conta do
signal-cli). - Se você rodar o bot na sua conta pessoal do Signal, ele ignorará suas próprias mensagens (proteção contra loop).
- Para o cenário “eu mando mensagem pro bot e ele responde”, use um número separado para o bot.
Caminho de configuração A: vincular conta Signal existente (QR)
- Instale
signal-cli(build JVM ou nativo). - Vincule uma conta de bot:
signal-cli link -n "OpenClaw"e escaneie o QR no Signal.
- Configure o Signal e inicie o gateway.
Exemplo:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}
Suporte a múltiplas contas: use channels.signal.accounts com configuração por conta e name opcional. Veja gateway/configuration para o padrão compartilhado.
Caminho de configuração B: registrar número dedicado para o bot (SMS, Linux)
Use quando quiser um número dedicado para o bot em vez de vincular uma conta existente do Signal.
- Obtenha um número que possa receber SMS (ou verificação por voz para linhas fixas).
- Use um número dedicado para o bot a fim de evitar conflitos de conta/sessão.
- Instale
signal-clino host do 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
Se usar o build JVM (signal-cli-${VERSION}.tar.gz), instale JRE 25+ primeiro.
Mantenha signal-cli atualizado; o upstream indica que versões antigas podem quebrar conforme as APIs do servidor Signal mudam.
- Registre e verifique o número:
signal-cli -a +<NUMERO_DO_BOT> register
Se captcha for necessário:
- Abra
https://signalcaptchas.org/registration/generate.html. - Complete o captcha, copie o link
signalcaptcha://...de “Open Signal”. - Execute a partir do mesmo IP externo da sessão do navegador quando possível.
- Execute o registro novamente imediatamente (tokens de captcha expiram rapidamente):
signal-cli -a +<NUMERO_DO_BOT> register --captcha '<URL_DO_SIGNALCAPTCHA>'
signal-cli -a +<NUMERO_DO_BOT> verify <CODIGO_DE_VERIFICACAO>
- Configure o OpenClaw, reinicie o gateway, verifique o canal:
# Se você roda o gateway como serviço systemd de usuário:
systemctl --user restart openclaw-gateway
# Depois verifique:
openclaw doctor
openclaw channels status --probe
- Pareie seu remetente de DM:
- Envie qualquer mensagem para o número do bot.
- Aprove o código no servidor:
openclaw pairing approve signal <CODIGO_DE_PAREAMENTO>. - Salve o número do bot como contato no seu telefone para evitar “Contato desconhecido”.
Importante: registrar uma conta de número de telefone com signal-cli pode desautenticar a sessão principal do app Signal para aquele número. Prefira um número dedicado para o bot, ou use o modo de link QR se precisar manter a configuração do app no telefone.
Referências upstream:
- README do
signal-cli:https://github.com/AsamK/signal-cli - Fluxo de captcha:
https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha - Fluxo de link:
https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)
Modo de daemon externo (httpUrl)
Se quiser gerenciar o signal-cli por conta própria (inicializações JVM lentas, init de container ou CPUs compartilhadas), rode o daemon separadamente e aponte o OpenClaw para ele:
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}
Isso ignora o auto-spawn e a espera de inicialização dentro do OpenClaw. Para inicializações lentas ao usar auto-spawn, defina channels.signal.startupTimeoutMs.
Controle de acesso (DMs + grupos)
DMs:
- Padrão:
channels.signal.dmPolicy = "pairing". - Remetentes desconhecidos recebem um código de pareamento; mensagens são ignoradas até aprovação (códigos expiram após 1 hora).
- Aprove via:
openclaw pairing list signalopenclaw pairing approve signal <CODE>
- O pareamento é a troca de token padrão para DMs do Signal. Detalhes: Pareamento
- Remetentes apenas com UUID (de
sourceUuid) são armazenados comouuid:<id>emchannels.signal.allowFrom.
Grupos:
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromcontrola quem pode acionar em grupos quandoallowlistestá definido.channels.signal.groups["<group-id>" | "*"]pode sobrescrever comportamento de grupo comrequireMention,toolsetoolsBySender.- Use
channels.signal.accounts.<id>.groupspara sobrescritas por conta em configurações multi-conta. - Nota de runtime: se
channels.signalestá completamente ausente, o runtime faz fallback paragroupPolicy="allowlist"para verificações de grupo (mesmo sechannels.defaults.groupPolicyestiver definido).
Como funciona (comportamento)
signal-cliroda como daemon; o gateway lê eventos via SSE.- Mensagens de entrada são normalizadas no envelope de canal compartilhado.
- Respostas sempre roteiam de volta para o mesmo número ou grupo.
Mídia + limites
- Texto de saída é dividido em
channels.signal.textChunkLimit(padrão 4000). - Divisão por nova linha opcional: defina
channels.signal.chunkMode="newline"para dividir em linhas em branco (limites de parágrafo) antes da divisão por tamanho. - Anexos suportados (base64 obtido do
signal-cli). - Limite de mídia padrão:
channels.signal.mediaMaxMb(padrão 8). - Use
channels.signal.ignoreAttachmentspara pular download de mídia. - Contexto de histórico de grupo usa
channels.signal.historyLimit(ouchannels.signal.accounts.*.historyLimit), com fallback paramessages.groupChat.historyLimit. Defina0para desabilitar (padrão 50).
Digitação + confirmações de leitura
- Indicadores de digitação: O OpenClaw envia sinais de digitação via
signal-cli sendTypinge os renova enquanto uma resposta está sendo gerada. - Confirmações de leitura: quando
channels.signal.sendReadReceiptsé true, o OpenClaw encaminha confirmações de leitura para DMs permitidas. - signal-cli não expõe confirmações de leitura para grupos.
Reações (ferramenta de mensagem)
- Use
message action=reactcomchannel=signal. - Alvos: E.164 do remetente ou UUID (use
uuid:<id>da saída de pareamento; UUID simples também funciona). messageIdé o timestamp do Signal para a mensagem à qual você está reagindo.- Reações em grupo requerem
targetAuthoroutargetAuthorUuid.
Exemplos:
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=✅
Configuração:
channels.signal.actions.reactions: habilitar/desabilitar ações de reação (padrão true).channels.signal.reactionLevel:off | ack | minimal | extensive.off/ackdesabilita reações do agente (ferramenta de mensagemreactretornará erro).minimal/extensivehabilita reações do agente e define o nível de orientação.
- Sobrescritas por conta:
channels.signal.accounts.<id>.actions.reactions,channels.signal.accounts.<id>.reactionLevel.
Alvos de entrega (CLI/cron)
- DMs:
signal:+15551234567(ou E.164 simples). - DMs por UUID:
uuid:<id>(ou UUID simples). - Grupos:
signal:group:<groupId>. - Nomes de usuário:
username:<name>(se suportado pela sua conta Signal).
Resolução de problemas
Execute esta sequência primeiro:
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe
Depois confirme o estado de pareamento de DM se necessário:
openclaw pairing list signal
Falhas comuns:
- Daemon acessível mas sem respostas: verifique configurações de conta/daemon (
httpUrl,account) e modo de recebimento. - DMs ignoradas: remetente pendente de aprovação de pareamento.
- Mensagens de grupo ignoradas: gating de remetente/menção de grupo bloqueando entrega.
- Erros de validação de config após edições: execute
openclaw doctor --fix. - Signal ausente do diagnóstico: confirme
channels.signal.enabled: true.
Verificações extras:
openclaw pairing list signal
pgrep -af signal-cli
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20
Para fluxo de triagem: /channels/troubleshooting.
Notas de segurança
signal-cliarmazena chaves de conta localmente (tipicamente~/.local/share/signal-cli/data/).- Faça backup do estado da conta Signal antes de migração ou reconstrução de servidor.
- Mantenha
channels.signal.dmPolicy: "pairing"a menos que você explicitamente queira acesso mais amplo a DM. - A verificação por SMS só é necessária para fluxos de registro ou recuperação, mas perder controle do número/conta pode complicar o re-registro.
Referência de configuração (Signal)
Configuração completa: Configuração
Opções do provedor:
channels.signal.enabled: habilitar/desabilitar inicialização do canal.channels.signal.account: E.164 para a conta do bot.channels.signal.cliPath: caminho parasignal-cli.channels.signal.httpUrl: URL completa do daemon (sobrescreve host/porta).channels.signal.httpHost,channels.signal.httpPort: bind do daemon (padrão 127.0.0.1:8080).channels.signal.autoStart: auto-spawn do daemon (padrão true sehttpUrlnão definido).channels.signal.startupTimeoutMs: timeout de espera de inicialização em ms (limite 120000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: pular downloads de anexos.channels.signal.ignoreStories: ignorar stories do daemon.channels.signal.sendReadReceipts: encaminhar confirmações de leitura.channels.signal.dmPolicy:pairing | allowlist | open | disabled(padrão: pairing).channels.signal.allowFrom: allowlist de DM (E.164 ouuuid:<id>).openrequer"*". Signal não tem nomes de usuário; use IDs de telefone/UUID.channels.signal.groupPolicy:open | allowlist | disabled(padrão: allowlist).channels.signal.groupAllowFrom: allowlist de remetentes de grupo.channels.signal.groups: sobrescritas por grupo chaveadas por ID de grupo Signal (ou"*"). Campos suportados:requireMention,tools,toolsBySender.channels.signal.accounts.<id>.groups: versão por conta dechannels.signal.groupspara configurações multi-conta.channels.signal.historyLimit: máximo de mensagens de grupo para incluir como contexto (0 desabilita).channels.signal.dmHistoryLimit: limite de histórico de DM em turnos de usuário. Sobrescritas por usuário:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: tamanho do chunk de saída (caracteres).channels.signal.chunkMode:length(padrão) ounewlinepara dividir em linhas em branco (limites de parágrafo) antes da divisão por tamanho.channels.signal.mediaMaxMb: limite de mídia de entrada/saída (MB).
Opções globais relacionadas:
agents.list[].groupChat.mentionPatterns(Signal não suporta menções nativas).messages.groupChat.mentionPatterns(fallback global).messages.responsePrefix.