Signal
Estado: integración de CLI externa. Gateway se comunica con signal-cli a través de HTTP — ya sea demonio nativo (JSON-RPC + SSE) o contenedor bbernhard/signal-cli-rest-api (REST + WebSocket).
Requisitos previos
Sección titulada «Requisitos previos»- OpenClaw instalado en su servidor (el flujo de Linux a continuación se probó en Ubuntu 24).
- Una de:
signal-clidisponible en el host (modo nativo), o- contenedor Docker
bbernhard/signal-cli-rest-api(modo contenedor).
- Un número de teléfono que pueda recibir un SMS de verificación (para la ruta de registro por SMS).
- Acceso al navegador para el captcha de Signal (
signalcaptchas.org) durante el registro.
Configuración rápida (principiante)
Sección titulada «Configuración rápida (principiante)»- Use un número de Signal separado para el bot (recomendado).
- Instale
signal-cli(se requiere Java si usa la compilación JVM). - Elija una ruta de configuración:
- Ruta A (enlace QR):
signal-cli link -n "OpenClaw"y escanee con Signal. - Ruta B (registro por SMS): registre un número dedicado con captcha + verificación por SMS.
- Ruta A (enlace QR):
- Configure OpenClaw y reinicie el gateway.
- Envíe el primer MD y apruebe el emparejamiento (
openclaw pairing approve signal <CODE>).
Configuración mínima:
{ channels: { signal: { enabled: true, account: "+15551234567", cliPath: "signal-cli", dmPolicy: "pairing", allowFrom: ["+15557654321"], }, },}Referencia de campos:
| Campo | Descripción |
|---|---|
account | Número de teléfono del bot en formato E.164 (+15551234567) |
cliPath | Ruta a signal-cli (signal-cli si está en PATH) |
configPath | directorio de configuración de signal-cli pasado como --config |
dmPolicy | política de acceso a DM (pairing recomendado) |
allowFrom | Números de teléfono o valores uuid:<id> permitidos para enviar DM |
- Canal de Signal a través de
signal-cli(no libsignal integrado). - Enrutamiento determinista: las respuestas siempre vuelven a Signal.
- Los DMs comparten la sesión principal del agente; los grupos están aislados (
agent:<agentId>:signal:group:<groupId>).
Escrituras de configuración
Sección titulada «Escrituras de configuración»De forma predeterminada, se permite a Signal escribir actualizaciones de configuración activadas por /config set|unset (requiere commands.config: true).
Desactivar con:
{ channels: { signal: { configWrites: false } },}El modelo de número (importante)
Sección titulada «El modelo de número (importante)»- La puerta de enlace se conecta a un dispositivo Signal (la cuenta
signal-cli). - Si ejecuta el bot en su cuenta personal de Signal, ignorará sus propios mensajes (protección contra bucles).
- Para “Le envío un mensaje al bot y responde”, use un número de bot separado.
Ruta de configuración A: vincular cuenta de Signal existente (QR)
Sección titulada «Ruta de configuración A: vincular cuenta de Signal existente (QR)»- Instale
signal-cli(construcción JVM o nativa). - Vincular una cuenta de bot:
signal-cli link -n "OpenClaw"y luego escanee el QR en Signal.
- Configure Signal e inicie la puerta de enlace.
Ejemplo:
{ channels: { signal: { enabled: true, account: "+15551234567", cliPath: "signal-cli", dmPolicy: "pairing", allowFrom: ["+15557654321"], }, },}Soporte multicuenta: use channels.signal.accounts con configuración por cuenta y name opcional. Consulte gateway/configuration para el patrón compartido.
Ruta de configuración B: registrar número de bot dedicado (SMS, Linux)
Sección titulada «Ruta de configuración B: registrar número de bot dedicado (SMS, Linux)»Use esto cuando desee un número de bot dedicado en lugar de vincular una cuenta de aplicación de Signal existente.
- Obtenga un número que pueda recibir SMS (o verificación por voz para líneas fijas).
- Use un número de bot dedicado para evitar conflictos de cuenta/sesión.
- Instale
signal-clien el host de la puerta de enlace:
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 /optsudo ln -sf /opt/signal-cli /usr/local/bin/signal-cli --versionSi usa la compilación JVM (signal-cli-${VERSION}.tar.gz), instale JRE 25+ primero.
Mantenga signal-cli actualizado; los desarrolladores originales señalan que las versiones antiguas pueden romperse a medida que cambian las API del servidor de Signal.
- Registre y verifique el número:
signal-cli -a +<BOT_PHONE_NUMBER> registerSi se requiere captcha:
- Abra
https://signalcaptchas.org/registration/generate.html. - Complete el captcha, copie el destino del enlace
signalcaptcha://...de “Abrir Signal”. - Ejecuta desde la misma IP externa que la sesión del navegador cuando sea posible.
- Ejecuta el registro de nuevo inmediatamente (los tokens de captcha caducan rápido):
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>- Configura OpenClaw, reinicia el gateway, verifica el canal:
# If you run the gateway as a user systemd service:systemctl --user restart openclaw-gateway.service
# Then verify:openclaw doctoropenclaw channels status --probe- Empareja tu remitente de MD:
- Envía cualquier mensaje al número del bot.
- Aprueba el código en el servidor:
openclaw pairing approve signal <PAIRING_CODE>. - Guarda el número del bot como un contacto en tu teléfono para evitar “Contacto desconocido”.
Referencias de origen:
signal-cliREADME:https://github.com/AsamK/signal-cli- Flujo de Captcha:
https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha - Flujo de enlace:
https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)
Modo de demonio externo (httpUrl)
Sección titulada «Modo de demonio externo (httpUrl)»Si quieres gestionar signal-cli tú mismo (arranques en frío lentos de JVM, init de contenedor o CPUs compartidas), ejecuta el demonio por separado y apunta OpenClaw a él:
{ channels: { signal: { httpUrl: "http://127.0.0.1:8080", autoStart: false, }, },}Esto omite la generación automática y la espera de inicio dentro de OpenClaw. Para inicios lentos al generarse automáticamente, establece channels.signal.startupTimeoutMs.
Modo contenedor (bbernhard/signal-cli-rest-api)
Sección titulada «Modo contenedor (bbernhard/signal-cli-rest-api)»En lugar de ejecutar signal-cli de forma nativa, puede usar el contenedor Docker bbernhard/signal-cli-rest-api. Esto envuelve signal-cli detrás de una API REST y una interfaz WebSocket.
Requisitos:
- El contenedor debe ejecutarse con
MODE=json-rpcpara recibir mensajes en tiempo real. - Registra o vincula tu cuenta de Signal dentro del contenedor antes de conectar OpenClaw.
Servicio docker-compose.yml de ejemplo:
signal-cli: image: bbernhard/signal-cli-rest-api:latest environment: MODE: json-rpc ports: - "8080:8080" volumes: - signal-cli-data:/home/.local/share/signal-cliConfiguración de OpenClaw:
{ channels: { signal: { enabled: true, account: "+15551234567", httpUrl: "http://signal-cli:8080", autoStart: false, apiMode: "container", // or "auto" to detect automatically }, },}El campo apiMode controla qué protocolo usa OpenClaw:
| Valor | Comportamiento |
|---|---|
"auto" | (Predeterminado) Sondea ambos transportes; el streaming valida la recepción del WebSocket del contenedor |
"native" | Fuerza signal-cli nativo (JSON-RPC en /api/v1/rpc, SSE en /api/v1/events) |
"container" | Fuerza el contenedor bbernhard (REST en /v2/send, WebSocket en /v1/receive/{account}) |
Cuando apiMode es "auto", OpenClaw almacena en caché el modo detectado durante 30 segundos para evitar sondeos repetidos. La recepción del contenedor solo se selecciona para streaming después de que /v1/receive/{account} actualice a WebSocket, lo cual requiere MODE=json-rpc.
El modo contenedor soporta las mismas operaciones del canal Signal que el modo nativo donde el contenedor expone las APIs correspondientes: envíos, recepciones, archivos adjuntos, indicadores de escritura, confirmaciones de lectura/visto, reacciones, grupos y texto con estilo. OpenClaw traduce sus llamadas RPC nativas de Signal en las cargas REST del contenedor, incluyendo group.{base64(internal_id)} de IDs de grupo y text_mode: "styled" para texto formateado.
Notas operativas:
- Use
autoStart: falsecon el modo contenedor. OpenClaw no debe iniciar un demonio nativo cuando se seleccionaapiMode: "container". - Use
MODE=json-rpcpara recibir.MODE=normalpuede hacer que/v1/aboutparezca saludable, pero/v1/receive/{account}no actualiza a WebSocket, por lo que OpenClaw no seleccionará el streaming de recepción del contenedor en el modoauto. - Establezca
apiMode: "container"cuando sepa quehttpUrlapunta a la API REST de bbernhard. EstablezcaapiMode: "native"cuando sepa que apunta al JSON-RPC/SSE nativo designal-cli. Use"auto"cuando el despliegue pueda variar. - Las descargas de adjuntos del contenedor respetan los mismos límites de bytes de medios que el modo nativo. Las respuestas sobredimensionadas se rechazan antes de ser totalmente almacenadas en el búfer cuando el servidor envía
Content-Length, y mientras se transmite en streaming de otro modo.
Control de acceso (MDs + grupos)
Sección titulada «Control de acceso (MDs + grupos)»MDs:
- Predeterminado:
channels.signal.dmPolicy = "pairing". - Los remitentes desconocidos reciben un código de vinculación; los mensajes se ignoran hasta que sean aprobados (los códigos caducan después de 1 hora).
- Aprobar vía:
openclaw pairing list signalopenclaw pairing approve signal <CODE>
- El emparejamiento (pairing) es el intercambio de tokens predeterminado para los MD de Signal. Detalles: Emparejamiento
- Los remitentes solo con UUID (de
sourceUuid) se almacenan comouuid:<id>enchannels.signal.allowFrom.
Grupos:
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFromcontrola qué grupos o remitentes pueden activar respuestas de grupo cuando se estableceallowlist; las entradas pueden ser IDs de grupos de Signal (sin procesar,group:<id>osignal:group:<id>), números de teléfono de los remitentes, valoresuuid:<id>o*.channels.signal.groups["<group-id>" | "*"]puede anular el comportamiento del grupo conrequireMention,toolsytoolsBySender.- Use
channels.signal.accounts.<id>.groupspara anulaciones por cuenta en configuraciones multicuenta. - Permitir un grupo de Signal a través de
groupAllowFromno desactiva por sí solo el filtrado de menciones. Una entradachannels.signal.groups["<group-id>"]configurada específicamente procesa cada mensaje de grupo a menos que se establezcarequireMention=true. - Nota de tiempo de ejecución: si
channels.signalfalta por completo, el tiempo de ejecución recurre agroupPolicy="allowlist"para las comprobaciones de grupo (incluso sichannels.defaults.groupPolicyestá establecido).
Cómo funciona (comportamiento)
Sección titulada «Cómo funciona (comportamiento)»- Modo nativo:
signal-clise ejecuta como demonio; la puerta de enlace lee eventos a través de SSE. - Modo contenedor: la puerta de enlace envía a través de la API REST y recibe a través de WebSocket.
- Los mensajes entrantes se normalizan en el sobre del canal compartido.
- Las respuestas siempre se enrutan de vuelta al mismo número o grupo.
Medios + límites
Sección titulada «Medios + límites»- El texto saliente se divide en partes de
channels.signal.textChunkLimit(predeterminado 4000). - División opcional por nuevas líneas: establezca
channels.signal.chunkMode="newline"para dividir en líneas en blanco (límites de párrafo) antes de la división por longitud. - Se admiten archivos adjuntos (base64 obtenidos de
signal-cli). - Los archivos adjuntos de notas de voz usan el nombre de archivo
signal-clicomo alternativa MIME cuando faltacontentType, por lo que la transcripción de audio aún puede clasificar las notas de voz AAC. - Límite predeterminado de medios:
channels.signal.mediaMaxMb(predeterminado 8). - Use
channels.signal.ignoreAttachmentspara omitir la descarga de medios. - El contexto del historial del grupo usa
channels.signal.historyLimit(ochannels.signal.accounts.*.historyLimit), recurriendo amessages.groupChat.historyLimit. Establezca0para deshabilitar (por defecto 50).
Indicadores de escritura + confirmaciones de lectura
Sección titulada «Indicadores de escritura + confirmaciones de lectura»- Indicadores de escritura: OpenClaw envía señales de escritura a través de
signal-cli sendTypingy las actualiza mientras se ejecuta una respuesta. - Confirmaciones de lectura: cuando
channels.signal.sendReadReceiptses verdadero, OpenClaw reenvía las confirmaciones de lectura para los MD permitidos. - Signal-cli no expone confirmaciones de lectura para grupos.
Reacciones (herramienta de mensaje)
Sección titulada «Reacciones (herramienta de mensaje)»- Use
message action=reactconchannel=signal. - Objetivos: E.164 o UUID del remitente (use
uuid:<id>de la salida del emparejamiento; también funciona el UUID simple). messageIdes la marca de tiempo de Signal para el mensaje al que está reaccionando.- Las reacciones de grupo requieren
targetAuthorotargetAuthorUuid.
Ejemplos:
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=truemessage action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅Configuración:
channels.signal.actions.reactions: habilitar/deshabilitar acciones de reacción (por defecto verdadero).channels.signal.reactionLevel:off | ack | minimal | extensive.off/ackdeshabilita las reacciones del agente (la herramienta de mensajereactdará error).minimal/extensivehabilita las reacciones del agente y establece el nivel de orientación.
- Invalidaciones por cuenta:
channels.signal.accounts.<id>.actions.reactions,channels.signal.accounts.<id>.reactionLevel.
Reacciones de aprobación
Sección titulada «Reacciones de aprobación»Las solicitudes de aprobación de ejecución y complementos de Signal usan los bloques de enrutamiento de nivel superior approvals.exec y
approvals.plugin. Signal no tiene un
bloque channels.signal.execApprovals.
👍aprueba una vez.👎deniega.- Use
/approve <id> allow-alwayscuando una solicitud ofrezca aprobación persistente.
La resolución de reacciones de aprobación requiere aprobadores de Signal explícitos de
channels.signal.allowFrom, channels.signal.defaultTo, o los campos de nivel de cuenta correspondientes.
Las solicitudes de aprobación de ejecución directa en el mismo chat aún pueden suprimir el respaldo local /approve duplicado
sin aprobadores explícitos; las aprobaciones de grupo sin aprobadores mantienen visible el respaldo local.
Destinos de entrega (CLI/cron)
Sección titulada «Destinos de entrega (CLI/cron)»- MD:
signal:+15551234567(o E.164 simple). - MD UUID:
uuid:<id>(o UUID simple). - Grupos:
signal:group:<groupId>. - Nombres de usuario:
username:<name>(si su cuenta de Signal lo admite).
Solución de problemas
Sección titulada «Solución de problemas»Ejecute primero esta escala:
openclaw statusopenclaw gateway statusopenclaw logs --followopenclaw doctoropenclaw channels status --probeLuego confirme el estado de emparejamiento de MD si es necesario:
openclaw pairing list signalFallos comunes:
- Demonio accesible pero sin respuestas: verifique la configuración de la cuenta/demonio (
httpUrl,account) y el modo de recepción. - MD ignorados: el remitente está pendiente de aprobación de emparejamiento.
- Mensajes de grupo ignorados: el bloqueo de remitente/mención del grupo impide la entrega.
- Errores de validación de configuración después de ediciones: ejecute
openclaw doctor --fix. - Signal no aparece en el diagnóstico: confirme
channels.signal.enabled: true.
Verificaciones adicionales:
openclaw pairing list signalpgrep -af signal-cligrep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20Para el flujo de triaje: /channels/troubleshooting.
Notas de seguridad
Sección titulada «Notas de seguridad»signal-clialmacena las claves de la cuenta localmente (típicamente en~/.local/share/signal-cli/data/).- Haz una copia de seguridad del estado de la cuenta de Signal antes de migrar o reconstruir el servidor.
- Mantén
channels.signal.dmPolicy: "pairing"a menos que explícitamente desees un acceso a DM más amplio. - La verificación por SMS solo es necesaria para los flujos de registro o recuperación, pero perder el control del número/cuenta puede complicar el nuevo registro.
Referencia de configuración (Signal)
Sección titulada «Referencia de configuración (Signal)»Configuración completa: Configuration
Opciones del proveedor:
channels.signal.enabled: habilitar/deshabilitar el inicio del canal.channels.signal.apiMode:auto | native | container(predeterminado: auto). Consulta Container mode.channels.signal.account: E.164 para la cuenta del bot.channels.signal.cliPath: ruta asignal-cli.channels.signal.configPath: directoriosignal-cli --configopcional.channels.signal.httpUrl: URL completa del demonio (anula host/puerto).channels.signal.httpHost,channels.signal.httpPort: enlace del demonio (predeterminado 127.0.0.1:8080).channels.signal.autoStart: iniciar automáticamente el demonio (predeterminado verdadero sihttpUrlno está establecido).channels.signal.startupTimeoutMs: tiempo de espera de inicio en ms (máximo 120000).channels.signal.receiveMode:on-start | manual.channels.signal.ignoreAttachments: omitir la descarga de archivos adjuntos.channels.signal.ignoreStories: ignorar historias del demonio.channels.signal.sendReadReceipts: reenviar confirmaciones de lectura.channels.signal.dmPolicy:pairing | allowlist | open | disabled(predeterminado: pairing).channels.signal.allowFrom: lista blanca de DM (E.164 ouuid:<id>).openrequiere"*". Signal no tiene nombres de usuario; usa ids de teléfono/UUID.channels.signal.groupPolicy:open | allowlist | disabled(predeterminado: allowlist).channels.signal.groupAllowFrom: lista de permitidos de grupos; acepta IDs de grupos de Signal (crudos,group:<id>osignal:group:<id>), números E.164 del remitente o valoresuuid:<id>.channels.signal.groups: anulaciones por grupo claveadas por ID de grupo de Signal (o"*"). Campos admitidos:requireMention,tools,toolsBySender.channels.signal.accounts.<id>.groups: versión por cuenta dechannels.signal.groupspara configuraciones de múltiples cuentas.channels.signal.historyLimit: máximo de mensajes de grupo a incluir como contexto (0 lo desactiva).channels.signal.dmHistoryLimit: límite de historial de MD en turnos de usuario. Anulaciones por usuario:channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: tamaño del fragmento de salida (caracteres).channels.signal.chunkMode:length(predeterminado) onewlinepara dividir en líneas en blanco (límites de párrafo) antes de la fragmentación por longitud.channels.signal.mediaMaxMb: límite de medios entrantes/salientes (MB).
Opciones globales relacionadas:
agents.list[].groupChat.mentionPatterns(Signal no admite menciones nativas).messages.groupChat.mentionPatterns(respaldo global).messages.responsePrefix.
Relacionado
Sección titulada «Relacionado»- Resumen de canales — todos los canales compatibles
- Emparejamiento — autenticación de MD y flujo de emparejamiento
- Grupos — comportamiento del chat grupal y filtrado de menciones
- Enrutamiento de canales — enrutamiento de sesiones para mensajes
- Seguridad — modelo de acceso y fortalecimiento