
OpenClaw Integration with Signal

By Sarah Jenkins


By Sarah Jenkins
Status: external CLI integration. Gateway talks to signal-cli over HTTP JSON-RPC + SSE.
signal-cli available on the host where the gateway runs.signalcaptchas.org) during registration.signal-cli (Java required if you use the JVM build).signal-cli link -n "OpenClaw" and scan with Signal.openclaw pairing approve signal <CODE>).Minimal config:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}Field reference:
| Field | Description |
|---|---|
account | Bot phone number in E.164 format (+15551234567) |
cliPath | Path to signal-cli (signal-cli if on PATH) |
dmPolicy | DM access policy (pairing recommended) |
allowFrom | Phone numbers or uuid:<id> values allowed to DM |
signal-cli (not embedded libsignal).agent:<agentId>:signal:group:<groupId>).By default, Signal is allowed to write config updates triggered by /config set|unset (requires commands.config: true).
Disable with:
{
channels: { signal: { configWrites: false } },
}signal-cli account).signal-cli (JVM or native build).signal-cli link -n "OpenClaw" then scan the QR in Signal.Example:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}Multi-account support: use channels.signal.accounts with per-account config and optional name.
Use this when you want a dedicated bot number instead of linking an existing Signal app account.
signal-cli on the gateway host: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 --versionIf you use the JVM build (signal-cli-${VERSION}.tar.gz), install JRE 25+ first.
Keep signal-cli updated; upstream notes that old releases can break as Signal server APIs change.
signal-cli -a +<BOT_PHONE_NUMBER> registerIf captcha is required:
https://signalcaptchas.org/registration/generate.html.signalcaptcha://... link target from "Open Signal".signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE># If you run the gateway as a user systemd service:
systemctl --user restart openclaw-gateway
# Then verify:
openclaw doctor
openclaw channels status --probeopenclaw pairing approve signal <PAIRING_CODE>.Important: registering a phone number account with signal-cli can de-authenticate the main Signal app session for that number. Prefer a dedicated bot number, or use QR link mode if you need to keep your existing phone app setup.
Upstream references:
signal-cli README: https://github.com/AsamK/signal-clihttps://github.com/AsamK/signal-cli/wiki/Registration-with-captchahttps://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)If you want to manage signal-cli yourself (slow JVM cold starts, container init, or shared CPUs), run the daemon separately and point OpenClaw at it:
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}This skips auto-spawn and the startup wait inside OpenClaw. For slow starts when auto-spawning, set channels.signal.startupTimeoutMs.
DMs:
channels.signal.dmPolicy = "pairing".openclaw pairing list signalopenclaw pairing approve signal <CODE>sourceUuid) are stored as uuid:<id> in channels.signal.allowFrom.Groups:
channels.signal.groupPolicy = open | allowlist | disabled.channels.signal.groupAllowFrom controls who can trigger in groups when allowlist is set.channels.signal.groups["<group-id>" | "*"] can override group behavior with requireMention, tools, and toolsBySender.channels.signal.accounts.<id>.groups for per-account overrides in multi-account setups.channels.signal is completely missing, runtime falls back to groupPolicy="allowlist" for group checks (even if channels.defaults.groupPolicy is set).signal-cli runs as a daemon; the gateway reads events via SSE.channels.signal.textChunkLimit (default 4000).channels.signal.chunkMode="newline" to split on blank lines (paragraph boundaries) before length chunking.signal-cli).channels.signal.mediaMaxMb (default 8).channels.signal.ignoreAttachments to skip downloading media.channels.signal.historyLimit (or channels.signal.accounts.*.historyLimit), falling back to messages.groupChat.historyLimit. Set 0 to disable (default 50).signal-cli sendTyping and refreshes them while a reply is running.channels.signal.sendReadReceipts is true, OpenClaw forwards read receipts for allowed DMs.message action=react with channel=signal.uuid:<id> from pairing output; bare UUID works too).messageId is the Signal timestamp for the message you’re reacting to.targetAuthor or targetAuthorUuid.Examples:
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=✅Config:
channels.signal.actions.reactions: enable/disable reaction actions (default true).channels.signal.reactionLevel: off | ack | minimal | extensive.off/ack disables agent reactions (message tool react will error).minimal/extensive enables agent reactions and sets the guidance level.channels.signal.accounts.<id>.actions.reactions, channels.signal.accounts.<id>.reactionLevel.signal:+15551234567 (or plain E.164).uuid:<id> (or bare UUID).signal:group:<groupId>.username:<name> (if supported by your Signal account).Run this ladder first:
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probeThen confirm DM pairing state if needed:
openclaw pairing list signalCommon failures:
httpUrl, account) and receive mode.openclaw doctor --fix.channels.signal.enabled: true.Extra checks:
openclaw pairing list signal
pgrep -af signal-cli
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20signal-cli stores account keys locally (typically ~/.local/share/signal-cli/data/).channels.signal.dmPolicy: "pairing" unless you explicitly want broader DM access.Provider options:
channels.signal.enabled: enable/disable channel startup.channels.signal.account: E.164 for the bot account.channels.signal.cliPath: path to signal-cli.channels.signal.httpUrl: full daemon URL (overrides host/port).channels.signal.httpHost, channels.signal.httpPort: daemon bind (default 127.0.0.1:8080).channels.signal.autoStart: auto-spawn daemon (default true if httpUrl unset).channels.signal.startupTimeoutMs: startup wait timeout in ms (cap 120000).channels.signal.receiveMode: on-start | manual.channels.signal.ignoreAttachments: skip attachment downloads.channels.signal.ignoreStories: ignore stories from the daemon.channels.signal.sendReadReceipts: forward read receipts.channels.signal.dmPolicy: pairing | allowlist | open | disabled (default: pairing).channels.signal.allowFrom: DM allowlist (E.164 or uuid:<id>). open requires "*". Signal has no usernames; use phone/UUID ids.channels.signal.groupPolicy: open | allowlist | disabled (default: allowlist).channels.signal.groupAllowFrom: group sender allowlist.channels.signal.groups: per-group overrides keyed by Signal group id (or "*"). Supported fields: requireMention, tools, toolsBySender.channels.signal.accounts.<id>.groups: per-account version of channels.signal.groups for multi-account setups.channels.signal.historyLimit: max group messages to include as context (0 disables).channels.signal.dmHistoryLimit: DM history limit in user turns. Per-user overrides: channels.signal.dms["<phone_or_uuid>"].historyLimit.channels.signal.textChunkLimit: outbound chunk size (chars).channels.signal.chunkMode: length (default) or newline to split on blank lines (paragraph boundaries) before length chunking.channels.signal.mediaMaxMb: inbound/outbound media cap (MB).Related global options:
agents.list[].groupChat.mentionPatterns (Signal does not support native mentions).messages.groupChat.mentionPatterns (global fallback).messages.responsePrefix.About the author

Sarah Jenkins is a seasoned OpenClaw developer with a strong focus on optimizing high-performance computing solutions. Her work primarily involves crafting efficient parallel algorithms and enhancing GPU acceleration for complex scientific simulations. Jenkins is renowned for her meticulous attention to detail and her ability to translate intricate theoretical concepts into practical, robust OpenClaw implementations.