
【最新版】SignalでOpenClawを使う方法(signal-cli連携)
2026年3月18日
Signal
Signal(signal-cli)
ステータス:外部CLI連携です。Gateway は signal-cli と HTTP JSON-RPC + SSE(Server-Sent Events)で通信します。
前提条件(Prerequisites)
- サーバーに OpenClaw がインストールされていること(以下の Linux 手順は Ubuntu 24 でテスト)。
- Gateway が動くホストに
signal-cliが存在すること。 - (SMS登録パスの場合)検証SMSを1通受け取れる電話番号があること。
- 登録中に Signal の captcha(
signalcaptchas.org)を開くためのブラウザアクセスがあること。
クイックセットアップ(初心者向け)
- ボット専用のSignal番号を使う(推奨)。
signal-cliをインストール(JVMビルドを使う場合は Java が必要)。- セットアップ経路を選ぶ:
- パスA(QRリンク):
signal-cli link -n "OpenClaw"を実行し、SignalアプリでQRをスキャン。 - パスB(SMS登録): captcha + SMS検証で専用番号を登録。
- パスA(QRリンク):
- OpenClaw を設定して Gateway を再起動。
- 最初のDMを送り、ペアリングを承認:
openclaw pairing approve signal <CODE>
最小 config:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}フィールド参照
account:ボットの電話番号(E.164形式:+15551234567)cliPath:signal-cliのパス(PATHにあるならsignal-cli)dmPolicy:DMのアクセス制御(pairing推奨)allowFrom:DMを許可する送信者(電話番号 またはuuid:<id>)
これは何か(What it is)
- Signal チャネルは
signal-cli経由(libsignalの組み込みではありません)。 - 決定的ルーティング:返信は常に Signal に戻ります。
- DM はエージェントの main セッションを共有し、グループは分離されます(
agent:<agentId>:signal:group:<groupId>)。
Config writes
デフォルトでは、Signal は /config set|unset によってトリガーされる設定更新(commands.config: true が必要)を 書き込むことが許可されています。
無効化:
{
channels: { signal: { configWrites: false } },
}番号モデル(重要)
- Gateway は Signalデバイス(
signal-cli側のアカウント)に接続します。 - ボットを 自分の個人Signalアカウント で動かすと、ループ防止のため 自分自身のメッセージを無視します。
- 「自分がボットに送ってボットが返す」をやりたい場合は、ボット専用の別番号を使ってください。
セットアップ パスA:既存のSignalアカウントをリンク(QR)
signal-cliをインストール(JVMビルド or nativeビルド)。- ボットアカウントをリンク:
signal-cli link -n "OpenClaw"を実行し、SignalでQRをスキャン。 - Signal を設定して Gateway を起動。
例:
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}マルチアカウント対応:channels.signal.accounts にアカウント別設定と任意の name を入れます。共通パターンはgateway/configurationを参照してください。
セットアップ パスB:専用のボット番号を登録(SMS, Linux)
既存の Signal アカウントをリンクするのではなく、ボット専用番号がほしい場合に使います。
- SMS(または固定電話なら音声)を受け取れる番号を用意します。
- アカウント/セッションの衝突を避けるため、ボット専用番号を推奨します。
- Gateway ホストに
signal-cliをインストールします:
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 --versionJVM ビルド(signal-cli-${VERSION}.tar.gz)を使う場合は、先に JRE 25+ をインストールしてください。 なお upstream では「Signalサーバー側API変更により古いリリースが壊れることがある」とされているため、signal-cli は更新しておくことを推奨します。
- 番号を登録して検証します:
signal-cli -a +<BOT_PHONE_NUMBER> register
captcha が必要な場合:
https://signalcaptchas.org/registration/generate.htmlを開きます。- captcha を完了し、「Open Signal」のリンク先(
signalcaptcha://...)をコピーします。 - 可能なら、ブラウザと同じ外部IPからコマンドを実行します。
- captcha トークンはすぐ失効するため、登録コマンドをすぐ再実行します:
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>' signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
- OpenClaw を設定し、Gateway を再起動してチャネルを検証します:
# Gateway を user systemd service として動かしている場合: systemctl --user restart openclaw-gateway # 検証: openclaw doctor openclaw channels status --probe
- DM 送信者をペアリング(許可)します:
- ボット番号へ任意のメッセージを送る。
- サーバーで承認:
openclaw pairing approve signal <PAIRING_CODE> - 「不明な連絡先」扱いを避けるため、ボット番号をスマホの連絡先に保存しておく。
重要:signal-cli で電話番号アカウントを登録すると、その番号で使っているメインの Signal アプリセッションが de-auth される可能性があります。 そのため、ボット専用番号の利用、または既存環境を維持したい場合は QR リンク方式(パスA)を推奨します。
Upstream 参照:
signal-cliREADME:https://github.com/AsamK/signal-cli- Captcha フロー:https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
- リンク(Provisioning):https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)
外部デーモンモード(httpUrl)
JVMのコールドスタートが遅い、コンテナ初期化、CPU共有などで signal-cli を自分で管理したい場合、 デーモンを別プロセスで起動し、OpenClaw からそのURLへ接続できます。
{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}これにより OpenClaw 内部の自動spawnと起動待ちをスキップします。自動spawnで起動が遅い場合は、channels.signal.startupTimeoutMs を調整してください。
アクセス制御(DM + グループ)
DM
- デフォルト:
channels.signal.dmPolicy = "pairing" - 未知の送信者にはペアリングコードを返し、承認されるまでメッセージは無視します(コードは1時間で期限切れ)。
- 承認コマンド:
openclaw pairing list signal openclaw pairing approve signal <CODE>
- ペアリングは Signal DM のデフォルトのトークン交換です。詳細:Pairing
- 送信者が(
sourceUuid由来で)UUIDしか持たない場合、channels.signal.allowFromにはuuid:<id>として保存されます。
グループ
channels.signal.groupPolicy = open | allowlist | disabledchannels.signal.groupAllowFrom:allowlistのとき、グループ内で誰がトリガーできるかを制御します。channels.signal.groups["<group-id>" | "*"]:グループ単位の上書き(requireMention,tools,toolsBySender)。- マルチアカウントの場合、アカウント別の上書き:
channels.signal.accounts.<id>.groups - ランタイム注意:
channels.signalが完全に欠けている場合、グループチェックはgroupPolicy="allowlist"にフォールバックします(channels.defaults.groupPolicyが設定されていても同様)。
仕組み(How it works / behavior)
signal-cliはデーモンとして動作し、Gateway は SSE でイベントを読み取ります。- 受信メッセージは共通のチャネルエンベロープへ正規化されます。
- 返信は常に同じ番号または同じグループにルーティングされます。
メディア + 制限
- 送信テキストは
channels.signal.textChunkLimit(デフォルト 4000)で分割されます。 - 任意:改行(段落)優先分割 → 長さ分割にするには
channels.signal.chunkMode="newline"を設定します。 - 添付ファイル対応(
signal-cliから base64 で取得)。 - デフォルトのメディア上限:
channels.signal.mediaMaxMb(デフォルト 8)。 - メディア取得をスキップするには
channels.signal.ignoreAttachments。 - グループの履歴コンテキストは
channels.signal.historyLimit(またはchannels.signal.accounts.*.historyLimit)を使い、messages.groupChat.historyLimitにフォールバックします。無効化は0(デフォルト 50)。
Typing + Read receipts
- 入力中表示(Typing indicators): OpenClaw は
signal-cli sendTypingで typing シグナルを送信し、返信生成中は更新します。 - 既読(Read receipts):
channels.signal.sendReadReceiptsが true の場合、許可されたDMに対して既読を転送します。 - Signal-cli はグループの既読を公開していません。
リアクション(message ツール)
message action=reactでchannel=signalを使います。- ターゲット:送信者のE.164、またはUUID(ペアリング出力の
uuid:<id>。bare UUID も可)。 messageIdは、リアクション対象メッセージの Signal timestamp です。- グループのリアクションは
targetAuthorまたはtargetAuthorUuidが必要です。
例:
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=✅
設定:
channels.signal.actions.reactions:リアクションアクションの有効/無効(デフォルト true)channels.signal.reactionLevel:off | ack | minimal | extensiveoff/ack:エージェントリアクションを無効化(messageツールのreactはエラー)。minimal/extensive:エージェントリアクションを有効化し、ガイダンスレベルを設定。
- アカウント別の上書き:
channels.signal.accounts.<id>.actions.reactions、channels.signal.accounts.<id>.reactionLevel
配信ターゲット(CLI / cron)
- DM:
signal:+15551234567(またはE.164そのまま) - UUID DM:
uuid:<id>(または bare UUID) - グループ:
signal:group:<groupId> - ユーザー名:
username:<name>(あなたのSignalアカウントが対応している場合)
トラブルシューティング
まずはこのラダー(順番)を実行します:
openclaw status openclaw gateway status openclaw logs --follow openclaw doctor openclaw channels status --probe
必要なら DM のペアリング状態を確認します:
openclaw pairing list signal
よくある失敗:
- デーモンは到達しているが返信しない:
httpUrl/account設定と受信モードを確認。 - DM が無視される:送信者がペアリング承認待ち。
- グループが無視される:送信者allowlist / メンションゲートでブロック。
- 編集後に config のバリデーションエラー:
openclaw doctor --fixを実行。 - 診断に Signal が出ない:
channels.signal.enabled: trueを確認。
追加チェック:
openclaw pairing list signal pgrep -af signal-cli grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20
切り分けフロー:/channels/troubleshooting
セキュリティノート
signal-cliはアカウント鍵をローカルに保存します(通常~/.local/share/signal-cli/data/)。- サーバー移行/再構築の前に、Signalアカウント状態をバックアップしてください。
channels.signal.dmPolicy: "pairing"は、意図的に広いDMアクセスを許可したい場合を除き維持してください。- SMS検証は登録/復旧フローでのみ必要ですが、番号/アカウントのコントロールを失うと再登録が難しくなる可能性があります。
設定リファレンス(Signal)
フル設定:Configuration
Provider options:
channels.signal.enabled:チャネル起動の有効/無効channels.signal.account:ボットアカウント(E.164)channels.signal.cliPath:signal-cliのパスchannels.signal.httpUrl:デーモンの完全URL(httpHost/httpPortより優先)channels.signal.httpHost,channels.signal.httpPort:デーモンの bind(デフォルト127.0.0.1:8080)channels.signal.autoStart:デーモンを自動spawn(httpUrl未設定時のデフォルト true)channels.signal.startupTimeoutMs:起動待ちのタイムアウト(ms、上限 120000)channels.signal.receiveMode:on-start | manualchannels.signal.ignoreAttachments:添付ダウンロードをスキップchannels.signal.ignoreStories:デーモン由来のストーリーを無視channels.signal.sendReadReceipts:既読を転送channels.signal.dmPolicy:pairing | allowlist | open | disabled(デフォルト pairing)channels.signal.allowFrom:DM allowlist(E.164 またはuuid:<id>)。openには"*"が必要。channels.signal.groupPolicy:open | allowlist | disabled(デフォルト allowlist)channels.signal.groupAllowFrom:グループ送信者 allowlistchannels.signal.groups:グループ単位の上書き(キーは group id または"*")。対応フィールド:requireMention,tools,toolsBySenderchannels.signal.accounts.<id>.groups:マルチアカウント用の per-account groupschannels.signal.historyLimit:グループ履歴の最大(0で無効)channels.signal.dmHistoryLimit:DM 履歴(ユーザーターン数)。ユーザー別上書き:channels.signal.dms["<phone_or_uuid>"].historyLimitchannels.signal.textChunkLimit:送信テキストのチャンクサイズ(文字数)channels.signal.chunkMode:length(デフォルト)またはnewlinechannels.signal.mediaMaxMb:送受信メディア上限(MB)
関連するグローバルオプション:
agents.list[].groupChat.mentionPatterns(Signal はネイティブメンション非対応)messages.groupChat.mentionPatterns(グローバルフォールバック)messages.responsePrefix
参考
関連記事

AIエージェントのメモリスタックとは?2026年に重要度が上がる理由をやさしく解説
2026年4月8日
OpenClaw vs Hermes vs Claude、創業者はどれを選ぶべき?2026年版の実務比較
2026年4月8日