Mainstream messaging

Signal

Statut : intégration CLI externe. Gateway communique avec signal-cli via HTTP JSON-RPC + SSE.

Prérequis

  • OpenClaw installé sur votre serveur (flux Linux ci-dessous testé sur Ubuntu 24).
  • signal-cli disponible sur l’hôte où le gateway s’exécute.
  • Un numéro de téléphone pouvant recevoir un SMS de vérification (pour le parcours d’enregistrement par SMS).
  • Accès au navigateur pour le captcha Signal (signalcaptchas.org) pendant l’enregistrement.

Configuration rapide (débutant)

  1. Utilisez un numéro Signal distinct pour le bot (recommandé).
  2. Installez signal-cli (Java requis si vous utilisez la version JVM).
  3. Choisissez un parcours de configuration :
    • Parcours A (lien QR) : signal-cli link -n "OpenClaw" et scannez avec Signal.
    • Parcours B (enregistrement SMS) : enregistrez un numéro dédié avec captcha + vérification SMS.
  4. Configurez OpenClaw et redémarrez le gateway.
  5. Envoyez un premier MP et approuvez l’appairage (openclaw pairing approve signal <CODE>).

Configuration minimale :

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

Référence des champs :

Champ Description
account Numéro de téléphone du bot au format E.164 (+15551234567)
cliPath Chemin vers signal-cli (signal-cli si dans le PATH)
dmPolicy Politique d’accès aux MP (pairing recommandé)
allowFrom Numéros de téléphone ou valeurs uuid:<id> autorisés en MP

Ce que c’est

  • Canal Signal via signal-cli (pas libsignal intégré).
  • Routage déterministe : les réponses reviennent toujours vers Signal.
  • Les MP partagent la session principale de l’agent ; les groupes sont isolés (agent:<agentId>:signal:group:<groupId>).

Écritures de configuration

Par défaut, Signal est autorisé à écrire les mises à jour de configuration déclenchées par /config set|unset (nécessite commands.config: true).

Désactiver avec :

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

Le modèle de numéro (important)

  • Le gateway se connecte à un appareil Signal (le compte signal-cli).
  • Si vous exécutez le bot sur votre compte Signal personnel, il ignorera vos propres messages (protection contre les boucles).
  • Pour « j’envoie un SMS au bot et il répond », utilisez un numéro de bot distinct.

Parcours de configuration A : lier un compte Signal existant (QR)

  1. Installez signal-cli (version JVM ou native).
  2. Liez un compte bot :
    • signal-cli link -n "OpenClaw" puis scannez le QR dans Signal.
  3. Configurez Signal et démarrez le gateway.

Exemple :

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

Prise en charge multicomptes : utilisez channels.signal.accounts avec une configuration par compte et un name facultatif. Consultez gateway/configuration pour le modèle partagé.

Parcours de configuration B : enregistrer un numéro de bot dédié (SMS, Linux)

Utilisez ceci lorsque vous voulez un numéro de bot dédié au lieu de lier un compte d’application Signal existant.

  1. Obtenez un numéro pouvant recevoir des SMS (ou une vérification vocale pour les lignes fixes).
    • Utilisez un numéro de bot dédié pour éviter les conflits de compte/session.
  2. Installez signal-cli sur l’hôte du 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

Si vous utilisez la version JVM (signal-cli-${VERSION}.tar.gz), installez d’abord JRE 25+. Maintenez signal-cli à jour ; l’amont indique que les anciennes versions peuvent cesser de fonctionner lorsque les API serveur de Signal changent.

  1. Enregistrez et vérifiez le numéro :
signal-cli -a +&lt;BOT_PHONE_NUMBER&gt; register

Si un captcha est requis :

  1. Ouvrez https://signalcaptchas.org/registration/generate.html.
  2. Terminez le captcha, copiez la cible du lien signalcaptcha://... depuis « Open Signal ».
  3. Exécutez depuis la même IP externe que la session du navigateur lorsque possible.
  4. Relancez immédiatement l’enregistrement (les jetons captcha expirent rapidement) :
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. Configurez OpenClaw, redémarrez le gateway, vérifiez le canal :
# If you run the gateway as a user systemd service:
systemctl --user restart openclaw-gateway.service

# Then verify:
openclaw doctor
openclaw channels status --probe
  1. Appairez votre expéditeur de MP :
    • Envoyez n’importe quel message au numéro du bot.
    • Approuvez le code sur le serveur : openclaw pairing approve signal &lt;PAIRING_CODE&gt;.
    • Enregistrez le numéro du bot comme contact sur votre téléphone pour éviter « Contact inconnu ».

Références amont :

  • README de signal-cli : https://github.com/AsamK/signal-cli
  • Flux captcha : https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • Flux de liaison : https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

Mode démon externe (httpUrl)

Si vous voulez gérer signal-cli vous-même (démarrages à froid JVM lents, initialisation de conteneur ou CPU partagés), exécutez le démon séparément et pointez OpenClaw vers celui-ci :

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

Cela évite le lancement automatique et l’attente de démarrage dans OpenClaw. Pour les démarrages lents lors du lancement automatique, définissez channels.signal.startupTimeoutMs.

Contrôle d’accès (MP + groupes)

MP :

  • Par défaut : channels.signal.dmPolicy = "pairing".
  • Les expéditeurs inconnus reçoivent un code d’appairage ; les messages sont ignorés jusqu’à approbation (les codes expirent après 1 heure).
  • Approuver via :
    • openclaw pairing list signal
    • openclaw pairing approve signal &lt;CODE&gt;
  • L’appairage est l’échange de jeton par défaut pour les MP Signal. Détails : Appairage
  • Les expéditeurs UUID uniquement (depuis sourceUuid) sont stockés comme uuid:<id> dans channels.signal.allowFrom.

Groupes :

  • channels.signal.groupPolicy = open | allowlist | disabled.
  • channels.signal.groupAllowFrom contrôle quels groupes ou expéditeurs peuvent déclencher des réponses de groupe lorsque allowlist est défini ; les entrées peuvent être des ID de groupe Signal (bruts, group:<id> ou signal:group:<id>), des numéros de téléphone d’expéditeur, des valeurs uuid:<id> ou *.
  • channels.signal.groups["<group-id>" | "*"] peut remplacer le comportement de groupe avec requireMention, tools et toolsBySender.
  • Utilisez channels.signal.accounts.<id>.groups pour les remplacements par compte dans les configurations multicomptes.
  • L’autorisation d’un groupe Signal via groupAllowFrom ne désactive pas à elle seule le filtrage par mention. Une entrée channels.signal.groups["<group-id>"] configurée spécifiquement traite chaque message de groupe sauf si requireMention=true est défini.
  • Note d’exécution : si channels.signal est complètement absent, l’exécution revient à groupPolicy="allowlist" pour les vérifications de groupe (même si channels.defaults.groupPolicy est défini).

Fonctionnement (comportement)

  • signal-cli s’exécute comme démon ; le gateway lit les événements via SSE.
  • Les messages entrants sont normalisés dans l’enveloppe de canal partagée.
  • Les réponses reviennent toujours vers le même numéro ou groupe.

Médias + limites

  • Le texte sortant est découpé selon channels.signal.textChunkLimit (4000 par défaut).
  • Découpage facultatif par nouvelle ligne : définissez channels.signal.chunkMode="newline" pour découper sur les lignes vides (limites de paragraphe) avant le découpage par longueur.
  • Pièces jointes prises en charge (base64 récupéré depuis signal-cli).
  • Les pièces jointes de note vocale utilisent le nom de fichier signal-cli comme solution de secours MIME lorsque contentType est absent, afin que la transcription audio puisse toujours classer les mémos vocaux AAC.
  • Limite média par défaut : channels.signal.mediaMaxMb (8 par défaut).
  • Utilisez channels.signal.ignoreAttachments pour éviter le téléchargement des médias.
  • Le contexte d’historique de groupe utilise channels.signal.historyLimit (ou channels.signal.accounts.*.historyLimit), avec repli sur messages.groupChat.historyLimit. Définissez 0 pour désactiver (50 par défaut).

Saisie + confirmations de lecture

  • Indicateurs de saisie : OpenClaw envoie des signaux de saisie via signal-cli sendTyping et les actualise pendant qu’une réponse est en cours.
  • Confirmations de lecture : lorsque channels.signal.sendReadReceipts est true, OpenClaw transmet les confirmations de lecture pour les MP autorisés.
  • Signal-cli n’expose pas les confirmations de lecture pour les groupes.

Réactions (outil de message)

  • Utilisez message action=react avec channel=signal.
  • Cibles : expéditeur E.164 ou UUID (utilisez uuid:<id> depuis la sortie d’appairage ; l’UUID nu fonctionne aussi).
  • messageId est l’horodatage Signal du message auquel vous réagissez.
  • Les réactions de groupe nécessitent targetAuthor ou targetAuthorUuid.

Exemples :

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=✅

Configuration :

  • channels.signal.actions.reactions : activer/désactiver les actions de réaction (true par défaut).
  • channels.signal.reactionLevel : off | ack | minimal | extensive.
    • off/ack désactive les réactions de l’agent (l’outil de message react renverra une erreur).
    • minimal/extensive active les réactions de l’agent et définit le niveau de guidage.
  • Remplacements par compte : channels.signal.accounts.<id>.actions.reactions, channels.signal.accounts.<id>.reactionLevel.

Cibles de livraison (CLI/cron)

  • MP : signal:+15551234567 (ou E.164 simple).
  • MP UUID : uuid:<id> (ou UUID nu).
  • Groupes : signal:group:<groupId>.
  • Noms d’utilisateur : username:<name> (si pris en charge par votre compte Signal).

Dépannage

Exécutez d’abord cette séquence :

openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe

Puis confirmez l’état d’appairage des MP si nécessaire :

openclaw pairing list signal

Échecs courants :

  • Démon joignable mais aucune réponse : vérifiez les paramètres de compte/démon (httpUrl, account) et le mode de réception.
  • MP ignorés : l’expéditeur est en attente d’approbation d’appairage.
  • Messages de groupe ignorés : le filtrage par expéditeur/mention de groupe bloque la livraison.
  • Erreurs de validation de configuration après modifications : exécutez openclaw doctor --fix.
  • Signal absent des diagnostics : confirmez channels.signal.enabled: true.

Vérifications supplémentaires :

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

Pour le flux de triage : /channels/troubleshooting.

Notes de sécurité

  • signal-cli stocke les clés de compte localement (généralement ~/.local/share/signal-cli/data/).
  • Sauvegardez l’état du compte Signal avant une migration ou reconstruction de serveur.
  • Conservez channels.signal.dmPolicy: "pairing" sauf si vous voulez explicitement un accès MP plus large.
  • La vérification SMS n’est nécessaire que pour les flux d’enregistrement ou de récupération, mais perdre le contrôle du numéro/compte peut compliquer le réenregistrement.

Référence de configuration (Signal)

Configuration complète : Configuration

Options du fournisseur :

  • channels.signal.enabled : active/désactive le démarrage du canal.
  • channels.signal.account : E.164 pour le compte du bot.
  • channels.signal.cliPath : chemin vers signal-cli.
  • channels.signal.httpUrl : URL complète du daemon (remplace host/port).
  • channels.signal.httpHost, channels.signal.httpPort : liaison du daemon (par défaut 127.0.0.1:8080).
  • channels.signal.autoStart : lance automatiquement le daemon (par défaut true si httpUrl n’est pas défini).
  • channels.signal.startupTimeoutMs : délai d’attente du démarrage en ms (plafond 120000).
  • channels.signal.receiveMode : on-start | manual.
  • channels.signal.ignoreAttachments : ignore les téléchargements de pièces jointes.
  • channels.signal.ignoreStories : ignore les stories du daemon.
  • channels.signal.sendReadReceipts : transmet les accusés de lecture.
  • channels.signal.dmPolicy : pairing | allowlist | open | disabled (par défaut : pairing).
  • channels.signal.allowFrom : liste d’autorisation des messages privés (E.164 ou uuid:<id>). open nécessite "*". Signal n’a pas de noms d’utilisateur ; utilisez des identifiants téléphone/UUID.
  • channels.signal.groupPolicy : open | allowlist | disabled (par défaut : allowlist).
  • channels.signal.groupAllowFrom : liste d’autorisation des groupes ; accepte les IDs de groupe Signal (bruts, group:<id> ou signal:group:<id>), les numéros E.164 d’expéditeur ou les valeurs uuid:<id>.
  • channels.signal.groups : remplacements par groupe indexés par ID de groupe Signal (ou "*"). Champs pris en charge : requireMention, tools, toolsBySender.
  • channels.signal.accounts.<id>.groups : version par compte de channels.signal.groups pour les configurations multi-comptes.
  • channels.signal.historyLimit : nombre maximal de messages de groupe à inclure comme contexte (0 désactive).
  • channels.signal.dmHistoryLimit : limite d’historique des messages privés en tours utilisateur. Remplacements par utilisateur : channels.signal.dms["<phone_or_uuid>"].historyLimit.
  • channels.signal.textChunkLimit : taille des fragments sortants (caractères).
  • channels.signal.chunkMode : length (par défaut) ou newline pour fractionner sur les lignes vides (limites de paragraphe) avant le fractionnement par longueur.
  • channels.signal.mediaMaxMb : plafond des médias entrants/sortants (Mo).

Options globales associées :

  • agents.list[].groupChat.mentionPatterns (Signal ne prend pas en charge les mentions natives).
  • messages.groupChat.mentionPatterns (solution de repli globale).
  • messages.responsePrefix.

Associé