OpenClawSkills
GitHub
Channels β€’ TutorialHeader.readTime

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.

Tutorial.step

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:

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

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>'.

Tutorial.step

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:

Json5
{
  channels: { signal: { configWrites: false } },
}
Tutorial.step

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>.

Tutorial.step

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>'.

Tutorial.step

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:

Json5
{
  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>.

Tutorial.step

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>.

Tutorial.step

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.

Tutorial.step

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).

Tutorial.step

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.

Tutorial.step

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:

Terminal
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>'

Tutorial.step

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)

Tutorial.step

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>