Signal
Signal integration via signal-cli (JSON-RPC + SSE): setup, configuration, and number model.
Status: External CLI integration. Gateway communicates with signal-cli via HTTP JSON-RPC + SSE.
Quick Setup for Beginners
1. Recommend using a <strong>separate Signal number</strong> as the bot number.
2. Install <code>signal-cli</code> (requires Java).
3. Link bot device and start daemon:
- <code>signal-cli link -n "OpenClaw"</code>
4. Configure OpenClaw and start gateway.
Minimal configuration:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}What It Is
- Connect to Signal via <code>signal-cli</code> (not embedded libsignal).
- Deterministic routing: replies always go back to Signal.
- DMs use agent's main session; group chats are isolated as '<code>'agent:'<agentId>':signal:group:'<groupId>''</code>'.
Config Writes
By default, allows Signal to write updates triggered by <code>/config set|unset</code> back to the config file (requires <code>commands.config: true</code>).
Disable:
{
channels: { signal: { configWrites: false } },
}Number Model (Important)
- Gateway connects to a <strong>Signal device</strong> (i.e., the account logged in by <code>signal-cli</code>).
- If you run the bot with <strong>your personal Signal account</strong>, it will ignore messages you send to avoid loops.
- If you want "I send a message to the bot, and the bot replies to me", please use a <strong>separate bot number</strong>.
Setup (Quick Path)
1. Install <code>signal-cli</code> (requires Java).
2. Link bot account:
- <code>signal-cli link -n "OpenClaw"</code> then scan QR code in Signal
3. Configure and start gateway.
Multi-account: use '<code>'channels.signal.accounts'</code>' to configure each account (optional '<code>'name'</code>'). For shared structure, see '<a href="/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts">'/gateway/configuration'</a>'.
External Daemon Mode (httpUrl)
If you want to manage <code>signal-cli</code> yourself (to avoid JVM cold start, container initialization, or startup overhead of shared CPU), you can run the daemon separately and let OpenClaw connect to it:
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}This skips the automatic pull-up and startup wait on the OpenClaw side. If startup is too slow during automatic pull-up, you can adjust <code>channels.signal.startupTimeoutMs</code>.
Access Control (DM + Group Chat)
DM:
- Default: <code>channels.signal.dmPolicy = "pairing"</code>.
- Unknown senders receive a pairing code, and messages are not processed until approved (expires in 1 hour).
- Approve:
- <code>openclaw pairing list signal</code>
- '<code>'openclaw pairing approve signal '<CODE>''</code>'
- Pairing is the default token exchange for Signal DMs. See '<a href="/start/pairing">'Pairing'</a>'.
- If the sender only has a UUID (from '<code>'sourceUuid'</code>'), it will be stored in '<code>'channels.signal.allowFrom'</code>' as '<code>'uuid:'<id>''</code>'.
Group chat:
- <code>channels.signal.groupPolicy = open | allowlist | disabled</code>.
- <code>channels.signal.groupAllowFrom</code> controls which senders can trigger when <code>allowlist</code>.
How It Works (Behavior)
- <code>signal-cli</code> runs as a daemon; gateway reads events via SSE.
- Inbound messages are normalized to a common channel envelope.
- Replies always go back to the same number or group.
Media and Limits
- Outbound text is split by <code>channels.signal.textChunkLimit</code> (default 4000).
- Optional priority split by blank lines: <code>channels.signal.chunkMode="newline"</code>.
- Supports attachments (provided by <code>signal-cli</code> as base64).
- Default media limit: <code>channels.signal.mediaMaxMb</code> (default 8MB).
- <code>channels.signal.ignoreAttachments</code> can skip media download.
- Group history context: <code>channels.signal.historyLimit</code> (or <code>channels.signal.accounts.*.historyLimit</code>), fallback <code>messages.groupChat.historyLimit</code>. Set to <code>0</code> to disable (default 50).
Typing and Read Receipts
- <strong>Typing</strong>: OpenClaw sends typing signals via <code>signal-cli sendTyping</code> and refreshes during reply execution.
- <strong>Read receipts</strong>: When <code>channels.signal.sendReadReceipts</code> is true, OpenClaw forwards read receipts for allowed DMs.
- signal-cli does not support group chat read receipts.
Reactions (Message Tool)
- Use message tool: <code>message action=react channel=signal</code>.
- Target can be E.164 or UUID (get '<code>'uuid:'<id>''</code>' from pairing output; bare UUID also works).
- <code>messageId</code> is the Signal timestamp of the message you want to react to.
- Group chat reactions need <code>targetAuthor</code> or <code>targetAuthorUuid</code>.
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 switches:
- <code>channels.signal.actions.reactions</code>: whether to enable reactions (default true).
- <code>channels.signal.reactionLevel</code>: <code>off | ack | minimal | extensive</code>
- <code>off</code>/<code>ack</code> disables agent reactions (message tool <code>react</code> will error)
- <code>minimal</code>/<code>extensive</code> enables agent reactions and sets guidance strength
- Per-account override: '<code>'channels.signal.accounts.'<id>'.actions.reactions'</code>', '<code>'channels.signal.accounts.'<id>'.reactionLevel'</code>'
Delivery Target (CLI/cron)
- DM: <code>signal:+15551234567</code> (or directly write E.164)
- UUID DM: '<code>'uuid:'<id>''</code>' (or bare UUID)
- Group chat: '<code>'signal:group:'<groupId>''</code>'
- Username: '<code>'username:'<name>''</code>' (if your Signal account supports it)
Signal Configuration Reference
For complete configuration reference, see '<a href="/gateway/configuration">'Configuration'</a>'.
Channel options:
- <code>channels.signal.enabled</code>
- <code>channels.signal.account</code> (E.164 of bot account)
- <code>channels.signal.cliPath</code>
- <code>channels.signal.httpUrl</code> (daemon URL)
- <code>channels.signal.httpHost</code>, <code>channels.signal.httpPort</code> (default 127.0.0.1:8080)
- <code>channels.signal.autoStart</code> (default true when httpUrl not set)
- <code>channels.signal.startupTimeoutMs</code> (startup wait, max 120000)
- <code>channels.signal.receiveMode</code> (<code>on-start | manual</code>)
- <code>channels.signal.ignoreAttachments</code>
- <code>channels.signal.ignoreStories</code>
- <code>channels.signal.sendReadReceipts</code>
- <code>channels.signal.dmPolicy</code> (<code>pairing | allowlist | open | disabled</code>, default pairing)
- '<code>'channels.signal.allowFrom'</code>' (DM allowlist: E.164 or '<code>'uuid:'<id>''</code>'; open needs '<code>'"*"'</code>')
- <code>channels.signal.groupPolicy</code> (default allowlist)
- <code>channels.signal.groupAllowFrom</code>
- <code>channels.signal.historyLimit</code> (0 to disable)
- '<code>'channels.signal.dmHistoryLimit'</code>' (DM history limit, by user turns; override per user '<code>'channels.signal.dms["'<phone_or_uuid>'"].historyLimit'</code>')
- <code>channels.signal.textChunkLimit</code>
- <code>channels.signal.chunkMode</code>
- <code>channels.signal.mediaMaxMb</code>
Related global options:
- <code>agents.list[].groupChat.mentionPatterns</code> (Signal has no native mentions)
- <code>messages.groupChat.mentionPatterns</code>
- <code>messages.responsePrefix</code>