@openclaw/signal). O Gateway se comunica com signal-cli por HTTP: seja pelo daemon nativo (JSON-RPC + SSE) ou pelo contêiner bbernhard/signal-cli-rest-api (REST + WebSocket). O OpenClaw não incorpora a libsignal.
O modelo de número (leia isto primeiro)
- O Gateway se conecta a um dispositivo Signal: a conta
signal-cli. - Executar o bot na sua conta pessoal do Signal faz com que ele ignore suas próprias mensagens (proteção contra loops).
- Para “eu envio uma mensagem ao bot e ele responde”, use um número separado para o bot.
Instalação
openclaw plugins install clawhub:@openclaw/signal ou npm:@openclaw/signal. plugins install registra e ativa o plugin; nenhuma etapa separada de enable é necessária. Consulte Plugins para ver as regras gerais de instalação.
Configuração rápida
1
Escolha um número
Use um número separado do Signal para o bot (recomendado).
2
Instale o plugin
3
Execute a configuração guiada
signal-cli está em PATH e, quando ausente, oferece a instalação: baixa a compilação nativa oficial do GraalVM no Linux x86-64 ou instala via Homebrew no macOS e em outras arquiteturas. Em seguida, solicita o número do bot e o caminho de signal-cli.Para configuração não interativa, openclaw channels add --channel signal também aceita --signal-number <e164> para o número de telefone do bot, além de --http-host <host> e --http-port <port> para o endpoint do daemon do Signal (padrão: 127.0.0.1:8080).4
5
Verifique e faça o pareamento
openclaw pairing approve signal <CODE>.
Compatibilidade com várias contas: use
channels.signal.accounts com configuração por conta e name opcional. Consulte Canais com várias contas para ver o padrão compartilhado.
O que é
- Roteamento determinístico: as respostas sempre retornam ao Signal.
- As mensagens diretas compartilham a sessão principal do agente; os grupos são isolados (
agent:<agentId>:signal:group:<groupId>). - Por padrão, o Signal pode gravar atualizações de configuração acionadas por
/config set|unset(requercommands.config: true). Desative comchannels.signal.configWrites: false.
Caminho de configuração A: vincular uma conta existente do Signal (QR)
- Instale
signal-cli(compilação JVM ou nativa) ou permita queopenclaw channels addfaça a instalação. - Vincule uma conta de bot:
signal-cli link -n "OpenClaw"; depois, escaneie o código QR no Signal. - Configure o Signal e inicie o Gateway.
Caminho de configuração B: registrar um número dedicado para o bot (SMS, Linux)
Use esta opção para um número dedicado ao bot, em vez de vincular uma conta existente do aplicativo Signal. O fluxo abaixo foi testado no Ubuntu 24.- Obtenha um número que possa receber SMS (ou verificação por voz, no caso de telefones fixos). Um número dedicado ao bot evita conflitos de conta/sessão.
- Instale
signal-clino host do Gateway:
signal-cli-${VERSION}.tar.gz), instale primeiro um JRE. Mantenha signal-cli atualizado; o projeto upstream observa que versões antigas podem deixar de funcionar à medida que as APIs do servidor do Signal mudam.
- Registre e verifique o número:
- Abra
https://signalcaptchas.org/registration/generate.html. - Conclua o captcha e copie o destino do link
signalcaptcha://...de “Open Signal”. - Quando possível, execute a partir do mesmo IP externo da sessão do navegador (os tokens de captcha expiram rapidamente).
- Registre e verifique imediatamente:
- Configure o OpenClaw, reinicie o Gateway e verifique o canal:
- Faça o pareamento do remetente da sua mensagem direta:
- Envie qualquer mensagem ao número do bot.
- Aprove no servidor:
openclaw pairing approve signal <PAIRING_CODE>. - Salve o número do bot como contato no telefone para evitar “Unknown contact”.
- README de
signal-cli: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)
Para gerenciarsignal-cli por conta própria (inicializações a frio lentas da JVM, inicialização do contêiner, CPUs compartilhadas), execute o daemon separadamente e aponte o OpenClaw para ele:
channels.signal.startupTimeoutMs.
Modo de contêiner (bbernhard/signal-cli-rest-api)
Em vez de executarsignal-cli nativamente, use o contêiner Docker bbernhard/signal-cli-rest-api, que disponibiliza signal-cli por meio de uma interface REST + WebSocket.
Requisitos:
- O contêiner deve ser executado com
MODE=json-rpcpara receber mensagens em tempo real. - Registre ou vincule sua conta do Signal dentro do contêiner antes de conectar o OpenClaw.
docker-compose.yml:
apiMode controla qual protocolo o OpenClaw usa:
Quando
apiMode é "auto", o OpenClaw armazena em cache o modo detectado por 30 segundos para cada URL de daemon, a fim de evitar sondagens repetidas (o modo nativo prevalece quando ambos os transportes estão íntegros). O recebimento pelo contêiner só é selecionado para streaming depois que /v1/receive/{account} faz upgrade para WebSocket, o que requer MODE=json-rpc.
O modo de contêiner é compatível com as mesmas operações do Signal que o modo nativo quando o contêiner expõe APIs correspondentes: envio, recebimento, anexos, indicadores de digitação, confirmações de leitura/visualização, reações, grupos e texto estilizado. O OpenClaw converte chamadas RPC nativas do Signal nas cargas REST do contêiner, incluindo IDs de grupo group.{base64(internal_id)} e text_mode: "styled" para texto formatado.
Observações operacionais:
- Use
autoStart: falsecom o modo de contêiner; o OpenClaw não deve iniciar um daemon nativo quandoapiMode: "container"estiver selecionado. - Use
MODE=json-rpcpara recebimento.MODE=normalpode fazer/v1/aboutparecer íntegro, mas/v1/receive/{account}não fará upgrade para WebSocket; portanto, o OpenClaw não selecionará o streaming de recebimento pelo contêiner no modoauto. - Defina
apiMode: "container"quandohttpUrlapontar para a API REST do bbernhard,"native"quando apontar para o JSON-RPC/SSE nativo designal-clie"auto"quando a implantação puder variar. - Os downloads de anexos no contêiner respeitam os mesmos limites de bytes de mídia do modo nativo. Respostas grandes demais são rejeitadas antes de serem totalmente armazenadas em buffer quando o servidor envia
Content-Lengthe, nos demais casos, durante o streaming.
Controle de acesso (mensagens diretas + grupos)
Mensagens diretas:- Padrão:
channels.signal.dmPolicy = "pairing". - Remetentes desconhecidos recebem um código de pareamento; as mensagens são ignoradas até a aprovação (os códigos expiram após 1 hora).
- Aprove por meio de
openclaw pairing list signaleopenclaw pairing approve signal <CODE>. - O pareamento é a troca de tokens padrão para mensagens diretas do Signal. Detalhes: Pareamento
- Remetentes apenas com UUID (de
sourceUuid) são armazenados comouuid:<id>emchannels.signal.allowFrom.
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromcontrola quais grupos ou remetentes podem acionar respostas em grupos quandoallowlistestá definido; as entradas podem ser IDs de grupo do Signal (brutos,group:<id>ousignal:group:<id>), números de telefone de remetentes, valores deuuid:<id>ou*.channels.signal.groups["<group-id>" | "*"]pode substituir o comportamento de grupos comrequireMention,toolsetoolsBySender.- Use
channels.signal.accounts.<id>.groupspara substituições por conta em configurações com várias contas. - Adicionar um grupo do Signal à lista de permissões por meio de
groupAllowFromnão desativa, por si só, a exigência de menção. Uma entradachannels.signal.groups["<group-id>"]configurada especificamente processa todas as mensagens do grupo, a menos querequireMention=trueesteja definido. - Com
requireMention=true, as @menções nativas do Signal são comparadas, usando metadados estruturados de menção, com o telefone ouaccountUuidda conta do bot. OsmentionPatternsconfigurados continuam sendo uma alternativa baseada em texto simples. - Observação sobre o runtime: se
channels.signalestiver completamente ausente, o runtime recorre agroupPolicy="allowlist"para verificações de grupos (mesmo quechannels.defaults.groupPolicyesteja definido).
Como funciona (comportamento)
- Modo nativo:
signal-clié executado como daemon; o Gateway lê os eventos via SSE. - Modo de contêiner: o Gateway envia via API REST e recebe via WebSocket.
- As mensagens recebidas são normalizadas no envelope compartilhado do canal.
- As respostas são sempre encaminhadas de volta ao mesmo número ou grupo.
- As respostas a mensagens recebidas incluem metadados nativos de citação do Signal quando o backend aceita o carimbo de data/hora e o autor da mensagem recebida; se os metadados da citação estiverem ausentes ou forem rejeitados, o OpenClaw enviará a resposta como uma mensagem normal.
- Configure o uso de citações nativas com
channels.signal.replyToMode = off | first | all | batchedouchannels.signal.replyToModeByChatType.direct/grouppara substituições por tipo de conversa. Os valores no nível da conta emchannels.signal.accounts.<id>têm precedência.
Mídia + limites
- O texto enviado é dividido em partes de acordo com
channels.signal.textChunkLimit(padrão: 4000). - Divisão opcional por nova linha: defina
channels.signal.streaming.chunkMode="newline"para dividir em linhas em branco (limites de parágrafo) antes da divisão por tamanho. - Há suporte a anexos (base64 obtido de
signal-cli). - Os anexos de notas de voz usam o nome de arquivo
signal-clicomo alternativa para o MIME quandocontentTypeestá ausente, para que a transcrição de áudio ainda possa classificar memorandos de voz AAC. - Limite padrão de mídia:
channels.signal.mediaMaxMb(padrão: 8). - Use
channels.signal.ignoreAttachmentspara ignorar o download de mídia. - O contexto do histórico do grupo usa
channels.signal.historyLimit(ouchannels.signal.accounts.*.historyLimit), com contingência paramessages.groupChat.historyLimit. Defina0para desativá-lo (padrão: 50).
Indicadores de digitação + confirmações de leitura
- Indicadores de digitação: o OpenClaw envia sinais de digitação via
signal-cli sendTypinge os atualiza enquanto uma resposta está em execução. - Confirmações de leitura: quando
channels.signal.sendReadReceiptsé verdadeiro, o OpenClaw encaminha confirmações de leitura para mensagens diretas permitidas. signal-clinão disponibiliza confirmações de leitura para grupos.
Reações de status do ciclo de vida
Definamessages.statusReactions.enabled: true para permitir que o Signal mostre o ciclo compartilhado de reações de enfileiramento/raciocínio/ferramenta/Compaction/conclusão/erro nas interações recebidas. O Signal usa o carimbo de data/hora da mensagem recebida como alvo da reação; as reações em grupos são enviadas com o ID do grupo do Signal e o remetente original como autor-alvo.
As reações de status também exigem uma reação de confirmação e um messages.ackReactionScope correspondente (direct, group-all, group-mentions ou all). Defina channels.signal.reactionLevel: "off" para desativar as reações de status do Signal.
messages.removeAckAfterReply: true remove a reação de status final após o tempo de retenção configurado. Caso contrário, o Signal restaura a reação de confirmação inicial após o estado final de conclusão/erro.
Reações (ferramenta de mensagens)
Usemessage action=react com channel=signal.
- Alvos: E.164 ou UUID do remetente (use
uuid:<id>da saída do pareamento; um UUID sem prefixo também funciona). messageIdé o carimbo de data/hora do Signal referente à mensagem à qual você está reagindo.- As reações em grupos exigem
targetAuthoroutargetAuthorUuid.
channels.signal.actions.reactions: ativa/desativa ações de reação (padrão: verdadeiro).channels.signal.reactionLevel:off | ack | minimal | extensive(padrão:minimal).off/ackdesativa as reações do agente (a ferramenta de mensagensreactretorna erros).minimal/extensiveativa as 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.
Reações de aprovação
As solicitações de aprovação de execução e de Plugin no Signal usam os blocos de roteamento de nível superiorapprovals.exec e approvals.plugin. O Signal não possui um bloco channels.signal.execApprovals.
👍aprova uma vez.👎nega.- Use
/approve <id> allow-alwaysquando uma solicitação oferecer aprovação persistente.
channels.signal.allowFrom, channels.signal.defaultTo ou dos campos correspondentes no nível da conta. As solicitações diretas de aprovação de execução na mesma conversa ainda podem suprimir a contingência local duplicada /approve sem aprovadores explícitos; aprovações em grupo sem aprovadores mantêm a contingência local visível.
Alvos de entrega (CLI/Cron)
- Mensagens diretas:
signal:+15551234567(ou E.164 sem prefixo). - Mensagens diretas por UUID:
uuid:<id>(ou UUID sem prefixo). - Grupos:
signal:group:<groupId>. - Nomes de usuário:
username:<name>(se forem compatíveis com sua conta do Signal).
Aliases
Configure aliases para nomes estáveis em alvos recorrentes do Signal. Os aliases são apenas configurações do lado do OpenClaw; eles não criam nem editam contatos do Signal.openclaw directory peers list --channel signal e openclaw directory groups list --channel signal listam os aliases configurados. O diretório do Signal é baseado na configuração; ele não consulta os contatos do Signal em tempo real nem modifica a conta do Signal.
Solução de problemas
Execute primeiro esta sequência:- Daemon acessível, mas sem respostas: verifique as configurações da conta/do daemon (
httpUrl,account) e o modo de recebimento. - Mensagens diretas ignoradas: o remetente aguarda aprovação de pareamento.
- Mensagens de grupo ignoradas: os controles de remetente/menção do grupo bloqueiam a entrega.
- Erros de validação da configuração após edições: execute
openclaw doctor --fix. - Signal ausente dos diagnósticos: confirme
channels.signal.enabled: true.
Notas de segurança
signal-cliarmazena as chaves da conta localmente (normalmente em~/.local/share/signal-cli/data/).- Faça backup do estado da conta do Signal antes de migrar ou reconstruir o servidor.
- Mantenha
channels.signal.dmPolicy: "pairing", a menos que queira explicitamente um acesso mais amplo às mensagens diretas. - A verificação por SMS é necessária apenas para fluxos de registro ou recuperação, mas perder o controle do número/da conta pode complicar um novo registro.
Referência de configuração (Signal)
Configuração completa: Configuração Opções do provedor:channels.signal.enabled: ativa/desativa a inicialização do canal.channels.signal.apiMode:auto | native | container(padrão: automático). Consulte Modo de contêiner.channels.signal.account: E.164 da conta do bot.channels.signal.accountUuid: UUID opcional da conta do bot para detecção nativa de @menções e proteção contra loops.channels.signal.cliPath: caminho parasignal-cli.channels.signal.configPath: diretóriosignal-cli --configopcional.channels.signal.httpUrl: URL completa do daemon (substitui host/porta).channels.signal.httpHost,channels.signal.httpPort: endereço de associação do daemon (padrão:127.0.0.1:8080).channels.signal.autoStart: inicia o daemon automaticamente (padrão: verdadeiro sehttpUrlnão estiver definido).channels.signal.startupTimeoutMs: tempo limite de espera da inicialização em ms (mín. 1000, limite 120000; padrão: 30000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: ignora downloads de anexos.channels.signal.ignoreStories: ignora stories do daemon.channels.signal.sendReadReceipts: encaminha confirmações de leitura.channels.signal.dmPolicy:pairing | allowlist | open | disabled(padrão: pareamento).channels.signal.allowFrom: lista de permissões de mensagens diretas (E.164 ouuuid:<id>).openexige"*". O Signal não possui nomes de usuário; use IDs de telefone/UUID.channels.signal.aliases: aliases do lado do OpenClaw para alvos de entrega de mensagens diretas ou grupos.channels.signal.groupPolicy:open | allowlist | disabled(padrão: lista de permissões).channels.signal.groupAllowFrom: lista de permissões de grupos; aceita IDs de grupo do Signal (brutos,group:<id>ousignal:group:<id>), números E.164 de remetentes ou valoresuuid:<id>.channels.signal.groups: substituições por grupo indexadas pelo ID do grupo do Signal (ou"*"). Campos compatíveis:requireMention,tools,toolsBySender.channels.signal.accounts.<id>.groups: versão por conta dechannels.signal.groupspara configurações com várias contas.channels.signal.accounts.<id>.aliases: aliases por conta, combinados com os aliases de nível superior.channels.signal.replyToMode: modo nativo de citação de resposta,off | first | all | batched(padrão:all).channels.signal.replyToModeByChatType.direct,channels.signal.replyToModeByChatType.group: substituições de citação de resposta nativa por tipo de conversa.channels.signal.accounts.<id>.replyToMode,channels.signal.accounts.<id>.replyToModeByChatType.direct,channels.signal.accounts.<id>.replyToModeByChatType.group: substituições de citação de resposta por conta.channels.signal.historyLimit: número máximo de mensagens do grupo a incluir como contexto (0 desativa).channels.signal.dmHistoryLimit: limite do histórico de mensagens diretas em interações do usuário. Substituições por usuário:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: tamanho das partes enviadas em caracteres (padrão: 4000).channels.signal.streaming.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 recebida/enviada em MB (padrão: 8).channels.signal.reactionLevel:off | ack | minimal | extensive(padrão:minimal). Consulte Reações.channels.signal.reactionNotifications:off | own | all | allowlist(padrão:own) — quando o agente é notificado sobre reações recebidas de outras pessoas.channels.signal.reactionAllowlist: remetentes cujas reações notificam o agente quandoreactionNotifications: "allowlist".channels.signal.streaming.block.enabled,channels.signal.streaming.block.coalesce: controles de streaming em modo de blocos compartilhados entre canais. Consulte Streaming.
agents.list[].groupChat.mentionPatterns(fallback em texto simples; as @menções nativas do Signal são detectadas nos metadados estruturados quando a identidade da conta do bot está configurada).messages.groupChat.mentionPatterns(fallback global).messages.responsePrefix.
Relacionados
- Visão geral dos canais - todos os canais compatíveis
- Pareamento - autenticação por mensagem direta e fluxo de pareamento
- Grupos - comportamento dos chats em grupo e controle por menções
- Roteamento de canais - roteamento de sessões para mensagens
- Segurança - modelo de acesso e reforço de segurança