Saltar para o conteúdo principal

Signal (signal-cli)

Status: integração externa via CLI. O Gateway se comunica com signal-cli por HTTP JSON-RPC + SSE.

Pré-requisitos

  • OpenClaw instalado no seu servidor (fluxo para Linux abaixo testado no Ubuntu 24).
  • signal-cli disponível no host onde o gateway é executado.
  • Um número de telefone que possa receber um SMS de verificação (para o fluxo de registro por SMS).
  • Acesso a um navegador para o captcha do Signal (signalcaptchas.org) durante o registro.

Configuração (caminho rápido)

  1. Use um número de Signal separado para o bot (recomendado).
  2. Instale signal-cli (Java necessário).
  3. Escolha um dos caminhos de configuração:
    • signal-cli link -n "OpenClaw"
    • Caminho B (registro por SMS): registre um número dedicado com captcha + verificação por SMS.
  4. Configure o OpenClaw e inicie o gateway.
  5. Envie a 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:
CampoDescrição
accountNúmero de telefone do bot no formato E.164 (+15551234567)
Início rápido (iniciante)Caminho para signal-cli (signal-cli se estiver no PATH)
dmPolicyPolítica de acesso por DM (pairing recomendado)
allowFromNúmeros de telefone ou valores uuid:&lt;id&gt; autorizados a enviar DM

O que é

  • Canal do Signal via signal-cli (não é libsignal embutido).
  • Roteamento determinístico: as respostas sempre retornam ao Signal.
  • DMs compartilham a sessão principal do agente; grupos são isolados (agent:<agentId>:signal:group:<groupId>).

Escritas de configuração

Por padrão, o Signal pode escrever atualizações de configuração disparadas por /config set|unset (requer commands.config: true). Desative com:
{
  channels: { signal: { configWrites: false } },
}

O modelo de números (importante)

  • O gateway se conecta a um dispositivo do Signal (a conta signal-cli).
  • Se você executar o bot na sua conta pessoal do Signal, ele ignorará suas próprias mensagens (proteção contra loop).
  • Para “eu envio mensagem ao bot e ele responde”, use um número de bot separado.

Caminho de configuração A: vincular conta existente do Signal (QR)

  1. Instale signal-cli (Java necessário).
  2. Vincule uma conta de bot:
    • signal-cli link -n "OpenClaw" e então escaneie o QR no Signal.
  3. 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 bot (SMS, Linux)

Use isto quando quiser um número dedicado para o bot em vez de vincular uma conta existente do app Signal.
  1. Obtenha um número que possa receber SMS (ou verificação por voz para telefones fixos).
    • Use um número dedicado para o bot para evitar conflitos de conta/sessão.
  2. Instale o signal-cli no 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 você usar a build JVM (signal-cli-${VERSION}.tar.gz), instale primeiro o JRE 25+. Mantenha o signal-cli atualizado; o upstream observa que versões antigas podem deixar de funcionar conforme as APIs do servidor Signal mudam.
  1. Registre e verifique o número:
signal-cli -a +<BOT_PHONE_NUMBER> register
Se for necessário captcha:
  1. Abra https://signalcaptchas.org/registration/generate.html.
  2. Conclua o captcha e copie o link signalcaptcha://... do alvo “Open Signal”.
  3. Execute a partir do mesmo IP externo da sessão do navegador, quando possível.
  4. Execute o registro novamente imediatamente (os tokens de captcha expiram rapidamente):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. Vincule o dispositivo do bot e inicie o daemon:
# Se você executar o gateway como um serviço systemd de usuário:
systemctl --user restart openclaw-gateway

# Depois verifique:
openclaw doctor
openclaw channels status --probe
  1. Emparelhe seu remetente de DM:
    • Envie qualquer mensagem para o número do bot.
    • Aprove o código no servidor: openclaw pairing approve signal <PAIRING_CODE>.
    • Salve o número do bot como contato no seu telefone para evitar “Unknown contact”.
Importante: registrar uma conta de número de telefone com signal-cli pode desautenticar a sessão principal do app Signal para esse número. Prefira um número dedicado para o bot ou use o modo de vinculação por QR se precisar manter a configuração atual do app no seu telefone. Referências upstream:
  • signal-cli README: https://github.com/AsamK/signal-cli
  • Fluxo de captcha: https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • Fluxo de vinculação: https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

Modo de daemon externo (httpUrl)

Se você quiser gerenciar o signal-cli por conta própria (inicializações frias lentas da JVM, init de container ou CPUs compartilhadas), execute 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; as mensagens são ignoradas até aprovação (códigos expiram após 1 hora).
  • Aprovar via:
    • openclaw pairing list signal
    • openclaw pairing approve signal <CODE>
  • Pareamento é a troca de token padrão para DMs do Signal. Detalhes: Pareamento
  • Remetentes somente por UUID (de sourceUuid) são armazenados como uuid:<id> em channels.signal.allowFrom.
Grupos:
  • channels.signal.groupPolicy = open | allowlist | disabled.
  • channels.signal.groupAllowFrom controla quem pode acionar em grupos quando allowlist está definido.

Como funciona (comportamento)

  • signal-cli roda como um daemon; o gateway lê eventos via SSE.
  • Mensagens de entrada são normalizadas no envelope de canal compartilhado.
  • As respostas sempre retornam ao mesmo número ou grupo.

Mídia + limites

  • Texto de saída é dividido em blocos de channels.signal.textChunkLimit (padrão 4000).
  • Divisão opcional por nova linha: defina channels.signal.chunkMode="newline" para dividir em linhas em branco (limites de parágrafo) antes da divisão por comprimento.
  • Anexos suportados (base64 obtido de signal-cli).
  • Limite padrão de mídia: channels.signal.mediaMaxMb (padrão 8).
  • Use channels.signal.ignoreAttachments para pular o download de mídia.
  • O contexto do histórico de grupos usa channels.signal.historyLimit (ou channels.signal.accounts.*.historyLimit), com fallback para messages.groupChat.historyLimit. Defina 0 para desativar (padrão 50).

Digitação + recibos de leitura

  • Indicadores de digitação: o OpenClaw envia sinais de digitação via signal-cli sendTyping e os renova enquanto uma resposta está em execução.
  • Recibos de leitura: quando channels.signal.sendReadReceipts é true, o OpenClaw encaminha recibos de leitura para DMs permitidas.
  • O signal-cli não expõe recibos de leitura para grupos.

Reações (ferramenta de mensagem)

  • Use message action=react com channel=signal.
  • Alvos: remetente E.164 ou UUID (use uuid:<id> da saída de pareamento; UUID simples também funciona).
  • messageId é o timestamp do Signal da mensagem à qual você está reagindo.
  • Reações em grupos exigem targetAuthor ou targetAuthorUuid.
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/ack desativa reações do agente (a ferramenta de mensagem react gerará erro).
    • minimal/extensive habilita reações do agente e define o nível de orientação.
  • Substituições 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 do Signal).

Soluçã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 DMs se necessário:
openclaw pairing list signal
Falhas comuns:
  • Daemon acessível, mas sem respostas: verifique as configurações da conta/daemon (httpUrl, account) e o modo de recebimento.
  • DMs ignoradas: o remetente está pendente de aprovação de pareamento.
  • Mensagens de grupo ignoradas: o bloqueio por remetente/menção do grupo impede a entrega.
  • Erros de validação de configuração após edições: execute openclaw doctor --fix.
  • Signal ausente nos diagnósticos: 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 o fluxo de triagem: /channels/troubleshooting.

Notas de segurança

  • signal-cli armazena as chaves da conta localmente (normalmente em ~/.local/share/signal-cli/data/).
  • Faça backup do estado da conta Signal antes de migrar ou reconstruir o servidor.
  • Mantenha channels.signal.dmPolicy: "pairing" a menos que você queira explicitamente um acesso por DM mais amplo.
  • A verificação por SMS é necessária apenas para fluxos de registro ou recuperação, mas perder o controle do número/conta pode complicar um novo registro.

Referência de configuração (Signal)

Configuração completa: Configuração Opções do provedor:
  • channels.signal.enabled: habilitar/desabilitar a inicialização do canal.
  • channels.signal.account: E.164 da conta do bot.
  • channels.signal.cliPath: caminho para signal-cli.
  • channels.signal.httpUrl: URL completa do daemon (substitui 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 se httpUrl não estiver definido).
  • channels.signal.startupTimeoutMs: tempo limite 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 recibos de leitura.
  • channels.signal.dmPolicy: pairing | allowlist | open | disabled (padrão: pareamento).
  • channels.signal.allowFrom: lista de permissões de DMs (E.164 ou uuid:<id>). open requer "*". O Signal não tem nomes de usuário; use IDs de telefone/UUID.
  • channels.signal.groupPolicy: open | allowlist | disabled (padrão: lista de permissões).
  • channels.signal.groupAllowFrom: lista de permissões de remetentes em grupos.
  • channels.signal.historyLimit: máximo de mensagens de grupo a incluir como contexto (0 desativa).
  • channels.signal.dmHistoryLimit: limite de histórico de DMs em turnos do usuário. Substituições por usuário: channels.signal.dms["<phone_or_uuid>"].historyLimit.
  • channels.signal.textChunkLimit: tamanho do bloco de saída (caracteres).
  • channels.signal.chunkMode: length (padrão) ou newline para dividir em linhas em branco (limites de parágrafo) antes da divisão por comprimento.
  • channels.signal.mediaMaxMb: limite de mídia de entrada/saída (MB).
Opções globais relacionadas:
  • agents.list[].groupChat.mentionPatterns (o Signal não oferece suporte a menções nativas).
  • messages.groupChat.mentionPatterns (fallback global).
  • messages.responsePrefix.