SignalでOpenClawを使う(signal-cli連携)

【最新版】SignalでOpenClawを使う方法(signal-cli連携)

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)を開くためのブラウザアクセスがあること。

クイックセットアップ(初心者向け)

  1. ボット専用のSignal番号を使う(推奨)。
  2. signal-cli をインストール(JVMビルドを使う場合は Java が必要)。
  3. セットアップ経路を選ぶ:
    • パスA(QRリンク): signal-cli link -n "OpenClaw" を実行し、SignalアプリでQRをスキャン。
    • パスB(SMS登録): captcha + SMS検証で専用番号を登録。
  4. OpenClaw を設定して Gateway を再起動。
  5. 最初のDMを送り、ペアリングを承認:openclaw pairing approve signal <CODE>

最小 config:

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

フィールド参照

  • account:ボットの電話番号(E.164形式:+15551234567
  • cliPathsignal-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)

  1. signal-cli をインストール(JVMビルド or nativeビルド)。
  2. ボットアカウントをリンク:signal-cli link -n "OpenClaw" を実行し、SignalでQRをスキャン。
  3. 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 アカウントをリンクするのではなく、ボット専用番号がほしい場合に使います。

  1. SMS(または固定電話なら音声)を受け取れる番号を用意します。
    • アカウント/セッションの衝突を避けるため、ボット専用番号を推奨します。
  2. 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 --version

JVM ビルド(signal-cli-${VERSION}.tar.gz)を使う場合は、先に JRE 25+ をインストールしてください。 なお upstream では「Signalサーバー側API変更により古いリリースが壊れることがある」とされているため、signal-cli は更新しておくことを推奨します。

  1. 番号を登録して検証します:
signal-cli -a +<BOT_PHONE_NUMBER> register

captcha が必要な場合:

  1. https://signalcaptchas.org/registration/generate.html を開きます。
  2. captcha を完了し、「Open Signal」のリンク先(signalcaptcha://...)をコピーします。
  3. 可能なら、ブラウザと同じ外部IPからコマンドを実行します。
  4. captcha トークンはすぐ失効するため、登録コマンドをすぐ再実行します:
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. OpenClaw を設定し、Gateway を再起動してチャネルを検証します:
# Gateway を user systemd service として動かしている場合:
systemctl --user restart openclaw-gateway

# 検証:
openclaw doctor
openclaw channels status --probe
  1. DM 送信者をペアリング(許可)します:
    • ボット番号へ任意のメッセージを送る。
    • サーバーで承認:openclaw pairing approve signal <PAIRING_CODE>
    • 「不明な連絡先」扱いを避けるため、ボット番号をスマホの連絡先に保存しておく。

重要:signal-cli で電話番号アカウントを登録すると、その番号で使っているメインの Signal アプリセッションが de-auth される可能性があります。 そのため、ボット専用番号の利用、または既存環境を維持したい場合は QR リンク方式(パスA)を推奨します。

Upstream 参照:

外部デーモンモード(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 | disabled
  • channels.signal.groupAllowFromallowlist のとき、グループ内で誰がトリガーできるかを制御します。
  • 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=reactchannel=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.reactionLeveloff | ack | minimal | extensive
    • off/ack:エージェントリアクションを無効化(messageツールの react はエラー)。
    • minimal/extensive:エージェントリアクションを有効化し、ガイダンスレベルを設定。
  • アカウント別の上書き:channels.signal.accounts.<id>.actions.reactionschannels.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.cliPathsignal-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.receiveModeon-start | manual
  • channels.signal.ignoreAttachments:添付ダウンロードをスキップ
  • channels.signal.ignoreStories:デーモン由来のストーリーを無視
  • channels.signal.sendReadReceipts:既読を転送
  • channels.signal.dmPolicypairing | allowlist | open | disabled(デフォルト pairing)
  • channels.signal.allowFrom:DM allowlist(E.164 または uuid:<id>)。open には "*" が必要。
  • channels.signal.groupPolicyopen | allowlist | disabled(デフォルト allowlist)
  • channels.signal.groupAllowFrom:グループ送信者 allowlist
  • channels.signal.groups:グループ単位の上書き(キーは group id または "*")。対応フィールド:requireMention, tools, toolsBySender
  • channels.signal.accounts.<id>.groups:マルチアカウント用の per-account groups
  • channels.signal.historyLimit:グループ履歴の最大(0で無効)
  • channels.signal.dmHistoryLimit:DM 履歴(ユーザーターン数)。ユーザー別上書き:channels.signal.dms["<phone_or_uuid>"].historyLimit
  • channels.signal.textChunkLimit:送信テキストのチャンクサイズ(文字数)
  • channels.signal.chunkModelength(デフォルト)または newline
  • channels.signal.mediaMaxMb:送受信メディア上限(MB)

関連するグローバルオプション:

  • agents.list[].groupChat.mentionPatterns(Signal はネイティブメンション非対応)
  • messages.groupChat.mentionPatterns(グローバルフォールバック)
  • messages.responsePrefix

参考

BizClaw 導入支援

OpenClaw の構築を
まるごと代行します

Mac mini のセットアップから Slack・iMessage 連携まで、届いた日から使える状態でお届けします。

サービスを見る

関連記事

Read article
AIエージェントのメモリスタックとは?2026年に重要度が上がる理由をやさしく解説

AIエージェントのメモリスタックとは?2026年に重要度が上がる理由をやさしく解説

Read article
OpenClaw vs Hermes vs Claude、創業者はどれを選ぶべき?2026年版の実務比較

OpenClaw vs Hermes vs Claude、創業者はどれを選ぶべき?2026年版の実務比較

Read article
X公式MCPサーバーとは?AIエージェント運用で何が変わるのかを実務目線で解説

X公式MCPサーバーとは?AIエージェント運用で何が変わるのかを実務目線で解説