Signal(signal-cli)

ステータス:外部CLI統合。ゲートウェイはHTTP JSON-RPC + SSE経由で signal-cli と通信します。

前提条件

  • OpenClawがサーバーにインストールされていること(以下のLinuxフローはUbuntu 24でテスト済み)。
  • ゲートウェイが動作するホストで signal-cli が利用可能であること。
  • SMS登録パスで確認SMSを1通受信できる電話番号。
  • 登録時のSignal captcha(signalcaptchas.org)のためのブラウザアクセス。

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

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

最小設定:

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

フィールドリファレンス:

フィールド説明
accountE.164形式のBot電話番号(+15551234567
cliPathsignal-cli のパス(PATH 上にあれば signal-cli
dmPolicyDMアクセスポリシー(pairing 推奨)
allowFromDMを許可する電話番号または uuid:<id>

signal-cliとは

  • signal-cli 経由のSignalチャンネル(組み込みlibsignalではありません)。
  • 決定論的ルーティング:返信は常にSignalに戻ります。
  • DMはエージェントのメインセッションを共有し、グループは分離されます(agent:<agentId>:signal:group:<groupId>)。

設定書き込み

デフォルトでは、Signalは /config set|unset によってトリガーされる設定更新の書き込みが許可されています(commands.config: true が必要)。

以下で無効化できます:

{
  channels: { signal: { configWrites: false } },
}

番号モデル(重要)

  • ゲートウェイはSignalデバイスsignal-cli アカウント)に接続します。
  • 個人のSignalアカウントでBotを実行する場合、自分自身のメッセージは無視されます(ループ防止)。
  • 「Botにテキストして返信をもらう」には、専用のBot番号を使用してください。

セットアップパスA:既存のSignalアカウントをリンク(QR)

  1. signal-cli をインストールします(JVMまたはネイティブビルド)。
  2. Botアカウントをリンクします:
    • signal-cli link -n "OpenClaw" を実行し、SignalでQRをスキャンします。
  3. Signalを設定してゲートウェイを起動します。

例:

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

マルチアカウントサポート:アカウントごとの設定とオプションの name を使用して channels.signal.accounts を設定します。共有パターンについてはgateway/configurationを参照してください。

セットアップパスB:専用Bot番号を登録(SMS、Linux)

既存のSignalアプリアカウントをリンクするのではなく、専用のBot番号が必要な場合に使用します。

  1. SMSを受信できる番号を取得します(固定電話の場合は音声認証)。
    • アカウント/セッションの競合を避けるため、専用のBot番号を使用してください。
  2. ゲートウェイホストに 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+をインストールしてください。 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を設定し、ゲートウェイを再起動して、チャンネルを確認します:
# ゲートウェイをユーザーsystemdサービスとして実行している場合:
systemctl --user restart openclaw-gateway

# 確認:
openclaw doctor
openclaw channels status --probe
  1. DM送信者をペアリングします:
    • Bot番号にメッセージを送信します。
    • サーバーでコードを承認します:openclaw pairing approve signal <PAIRING_CODE>
    • 「不明な連絡先」を避けるため、Bot番号を電話の連絡先に保存します。

注意: signal-cli で電話番号アカウントを登録すると、その番号のメインSignalアプリセッションの認証が解除される場合があります。専用のBot番号を使用するか、既存の電話アプリ設定を維持する必要がある場合はQRリンクモードを使用してください。

アップストリームリファレンス:

  • signal-cli README:https://github.com/AsamK/signal-cli
  • captchaフロー:https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • リンクフロー:https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

外部デーモンモード(httpUrl)

signal-cli を自分で管理したい場合(JVMのコールドスタートが遅い、コンテナの初期化、共有CPUなど)、デーモンを別途実行してOpenClawをそこに向けます:

{
  channels: {
    signal: {
      httpUrl: "http://127.0.0.1:8080",
      autoStart: false,
    },
  },
}

これにより、自動起動とOpenClaw内の起動待機がスキップされます。自動起動時のスタートが遅い場合は、channels.signal.startupTimeoutMs を設定してください。

アクセス制御(DM + グループ)

DM:

  • デフォルト:channels.signal.dmPolicy = "pairing"
  • 不明な送信者にはペアリングコードが送られます。承認されるまでメッセージは無視されます(コードは1時間後に期限切れ)。
  • 以下の方法で承認します:
    • openclaw pairing list signal
    • openclaw pairing approve signal <CODE>
  • ペアリングはSignal DMのデフォルトのトークン交換です。詳細:ペアリング
  • UUIDのみの送信者(sourceUuid から)は channels.signal.allowFromuuid:<id> として保存されます。

グループ:

  • channels.signal.groupPolicy = open | allowlist | disabled
  • allowlist が設定されている場合、channels.signal.groupAllowFrom がグループ内でトリガーできる人を制御します。
  • channels.signal.groups["<group-id>" | "*"]requireMentiontoolstoolsBySender を使用してグループの動作をオーバーライドできます。
  • マルチアカウントセットアップでは、channels.signal.accounts.<id>.groups でアカウントごとのオーバーライドを使用します。
  • ランタイムの注意:channels.signal が完全に欠落している場合、ランタイムはグループチェックに対して groupPolicy="allowlist" にフォールバックします(channels.defaults.groupPolicy が設定されていても)。

動作の仕組み

  • signal-cli はデーモンとして実行され、ゲートウェイは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)。

タイピング + 既読レシート

  • タイピングインジケーター:OpenClawは signal-cli sendTyping 経由でタイピングシグナルを送信し、返信の実行中にリフレッシュします。
  • 既読レシートchannels.signal.sendReadReceipts がtrueの場合、OpenClawは許可されたDMの既読レシートを転送します。
  • signal-cliはグループの既読レシートを公開していません。

リアクション(messageツール)

  • channel=signalmessage action=react を使用します。
  • ターゲット:送信者のE.164またはUUID(ペアリング出力の uuid:<id> を使用。ベアUUIDも有効)。
  • messageId はリアクションするメッセージのSignalタイムスタンプです。
  • グループリアクションには 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>(またはベア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

よくある障害:

  • デーモンは到達可能だが返信がない:アカウント/デーモンの設定(httpUrlaccount)と受信モードを確認してください。
  • DMが無視される:送信者がペアリング承認待ちです。
  • グループメッセージが無視される:グループ送信者/メンションゲーティングが配信をブロックしています。
  • 編集後の設定バリデーションエラー: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アカウントの状態をバックアップしてください。
  • より広範なDMアクセスを明示的に望まない限り、channels.signal.dmPolicy: "pairing" を維持してください。
  • SMS認証は登録またはリカバリーフローでのみ必要ですが、番号/アカウントの制御を失うと再登録が複雑になる可能性があります。

設定リファレンス(Signal)

完全な設定:Configuration

プロバイダーオプション:

  • channels.signal.enabled:チャンネルの起動を有効/無効にします。
  • channels.signal.account:BotアカウントのE.164。
  • channels.signal.cliPathsignal-cli のパス。
  • channels.signal.httpUrl:完全なデーモンURL(host/portをオーバーライド)。
  • channels.signal.httpHostchannels.signal.httpPort:デーモンバインド(デフォルト127.0.0.1:8080)。
  • channels.signal.autoStart:デーモンの自動起動(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許可リスト(E.164または uuid:<id>)。open には "*" が必要です。Signalにはユーザー名がありません。電話/UUID IDを使用してください。
  • channels.signal.groupPolicyopen | allowlist | disabled(デフォルト:allowlist)。
  • channels.signal.groupAllowFrom:グループ送信者の許可リスト。
  • channels.signal.groups:SignalグループIDでキー付けされたグループごとのオーバーライド(または "*")。サポートフィールド:requireMentiontoolstoolsBySender
  • channels.signal.accounts.<id>.groups:マルチアカウントセットアップ用の channels.signal.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