WhatsApp(Webチャンネル)

ステータス:WhatsApp Web(Baileys)経由で本番運用可能。Gatewayがリンクされたセッションを所有します。

クイックセットアップ

ステップ1:WhatsAppアクセスポリシーの設定

{
  channels: {
    whatsapp: {
      dmPolicy: "pairing",
      allowFrom: ["+15551234567"],
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15551234567"],
    },
  },
}

ステップ2:WhatsAppのリンク(QRコード)

openclaw channels login --channel whatsapp
特定のアカウントを指定する場合:
openclaw channels login --channel whatsapp --account work

ステップ3:Gatewayの起動

openclaw gateway

ステップ4:最初のペアリングリクエストの承認(ペアリングモード使用時)

openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
ペアリングリクエストは1時間後に期限切れになります。保留中リクエストの上限はチャンネルごとに3件です。

注意: OpenClawは可能な限り専用の番号でWhatsAppを運用することを推奨しています。(チャンネルメタデータとオンボーディングフローはその構成に最適化されていますが、個人番号での運用もサポートしています。)

デプロイパターン

専用番号(推奨)
最もシンプルな運用モードです:

- OpenClaw用の独立したWhatsApp IDを使用
- DM許可リストとルーティング境界がより明確
- セルフチャットの混乱が発生する確率が低い

最小ポリシーパターン:

```json5
{
  channels: {
    whatsapp: {
      dmPolicy: "allowlist",
      allowFrom: ["+15551234567"],
    },
  },
}
```
個人番号での代替構成
オンボーディングウィザードは個人番号モードをサポートし、セルフチャット対応の基本設定を書き込みます:

- `dmPolicy: "allowlist"`
- `allowFrom`に個人番号を含む
- `selfChatMode: true`

ランタイムでは、セルフチャット保護はリンクされた自身の番号と`allowFrom`に基づきます。
WhatsApp Webのみのチャンネルスコープ
現在のOpenClawチャンネルアーキテクチャでは、メッセージングプラットフォームチャンネルはWhatsApp Web(`Baileys`)ベースです。

組み込みチャットチャンネルレジストリに個別のTwilio WhatsAppメッセージングチャンネルはありません。

ランタイムモデル

  • GatewayがWhatsApp socketと再接続ループを所有します。
  • 送信には対象アカウントのアクティブなWhatsAppリスナーが必要です。
  • ステータスとブロードキャストチャットは無視されます(@status@broadcast)。
  • DMはDMセッションルール(session.dmScope。デフォルトmainでDMをAgentメインセッションに集約)を使用します。
  • グループセッションは隔離されます(agent:<agentId>:whatsapp:group:<jid>)。

アクセス制御とアクティベーション

DMポリシー

`channels.whatsapp.dmPolicy`でDMアクセスを制御します:

- `pairing`(デフォルト)
- `allowlist`
- `open`(`allowFrom`に`"*"`を含む必要あり)
- `disabled`

`allowFrom`はE.164形式の番号を受け付けます(内部で正規化)。

マルチアカウントオーバーライド:`channels.whatsapp.accounts.<id>.dmPolicy`(および`allowFrom`)は該当アカウントのチャンネルレベルデフォルトより優先されます。

ランタイム動作の詳細:

- ペアリング結果はチャンネルallow-storeに永続化され、設定された`allowFrom`とマージされます
- 許可リストが設定されていない場合、リンクされた自身の番号がデフォルトで許可されます
- 送信`fromMe` DMは自動ペアリングされません

グループポリシー + 許可リスト

グループアクセスは2層構造です:

1. **グループメンバーシップ許可リスト**(`channels.whatsapp.groups`)
   - `groups`を省略すると、すべてのグループが対象
   - `groups`がある場合、グループ許可リストとして機能(`"*"`可)

2. **グループ送信者ポリシー**(`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
   - `open`:送信者許可リストをバイパス
   - `allowlist`:送信者が`groupAllowFrom`(または`*`)と一致する必要あり
   - `disabled`:グループ受信をすべてブロック

送信者許可リストのフォールバック:

- `groupAllowFrom`が未設定の場合、ランタイムは利用可能な`allowFrom`にフォールバック
- 送信者許可リストはメンション/リプライアクティベーションより前に評価

注意:`channels.whatsapp`設定ブロックが全く存在しない場合、`channels.defaults.groupPolicy`が設定されていても、ランタイムグループポリシーは`allowlist`にフォールバックします(警告ログ付き)。

メンション + /activation

グループ返信はデフォルトでメンションが必要です。

メンション検出の対象:

- Bot IDへの明示的なWhatsAppメンション
- 設定されたメンション正規表現パターン(`agents.list[].groupChat.mentionPatterns`、フォールバック`messages.groupChat.mentionPatterns`)
- Botへの暗黙的なリプライ検出(リプライ送信者がBot IDと一致)

セキュリティに関する注意:

- 引用/リプライはメンションゲーティングを満たすだけであり、送信者認可を**付与しません**
- `groupPolicy: "allowlist"`の場合、許可リストにないユーザーが許可リスト上のユーザーのメッセージにリプライしてもブロックされます

セッションレベルのアクティベーションコマンド:

- `/activation mention`
- `/activation always`

`activation`はセッション状態を更新します(グローバル設定ではありません)。オーナー権限が必要です。

個人番号とセルフチャット動作

リンクされた自身の番号がallowFromにも含まれている場合、WhatsAppセルフチャット保護が有効になります:

  • セルフチャットターンの既読レシートをスキップ
  • 自身にpingするメンションJID自動トリガー動作を無視
  • messages.responsePrefixが未設定の場合、セルフチャット返信はデフォルトで[{identity.name}]または[openclaw]を使用

メッセージ正規化とコンテキスト

受信エンベロープ + リプライコンテキスト
受信WhatsAppメッセージは共有受信エンベロープにラップされます。

引用リプライが存在する場合、コンテキストは以下の形式で付加されます:

```text
[Replying to <sender> id:<stanzaId>]
<quoted body or media placeholder>
[/Replying]
```

利用可能な場合、リプライメタデータフィールド(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、送信者JID/E.164)も設定されます。
メディアプレースホルダーと位置情報/連絡先の抽出
メディアのみの受信メッセージは以下のプレースホルダーで正規化されます:

- `<media:image>`
- `<media:video>`
- `<media:audio>`
- `<media:document>`
- `<media:sticker>`

位置情報と連絡先ペイロードはルーティング前にテキストコンテキストに正規化されます。
保留中グループ履歴の注入
グループでは、未処理のメッセージをバッファしてBotがトリガーされた際にコンテキストとして注入できます。

- デフォルト上限:`50`
- 設定:`channels.whatsapp.historyLimit`
- フォールバック:`messages.groupChat.historyLimit`
- `0`で無効化

注入マーカー:

- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
既読レシート
受け付けた受信WhatsAppメッセージに対して、既読レシートはデフォルトで有効です。

グローバルに無効化:

```json5
{
  channels: {
    whatsapp: {
      sendReadReceipts: false,
    },
  },
}
```

アカウントごとのオーバーライド:

```json5
{
  channels: {
    whatsapp: {
      accounts: {
        work: {
          sendReadReceipts: false,
        },
      },
    },
  },
}
```

セルフチャットターンはグローバル有効時でも既読レシートをスキップします。

配信、チャンキング、メディア

テキストチャンキング
- デフォルトチャンク上限:`channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.chunkMode = "length" | "newline"`
- `newline`モードは段落境界(空行)を優先し、その後長さ基準のチャンキングにフォールバック
送信メディア動作
- 画像、動画、音声(PTTボイスメモ)、ドキュメントのペイロードをサポート
- `audio/ogg`はボイスメモ互換のため`audio/ogg; codecs=opus`に書き換え
- 動画送信時に`gifPlayback: true`でアニメーションGIF再生をサポート
- マルチメディア返信ペイロード送信時、キャプションは最初のメディアアイテムに適用
- メディアソースはHTTP(S)、`file://`、またはローカルパス
メディアサイズ制限とフォールバック動作
- 受信メディア保存上限:`channels.whatsapp.mediaMaxMb`(デフォルト`50`)
- 送信メディア送信上限:`channels.whatsapp.mediaMaxMb`(デフォルト`50`)
- アカウントごとのオーバーライド:`channels.whatsapp.accounts.<accountId>.mediaMaxMb`
- 画像は制限に収まるよう自動最適化(リサイズ/品質調整)
- メディア送信失敗時、最初のアイテムのフォールバックとして応答を無言でドロップする代わりにテキスト警告を送信

確認リアクション

WhatsAppはchannels.whatsapp.ackReactionによる受信時の即時確認リアクションをサポートしています。

{
  channels: {
    whatsapp: {
      ackReaction: {
        emoji: "👀",
        direct: true,
        group: "mentions", // always | mentions | never
      },
    },
  },
}

動作の説明:

  • 受信が受け付けられた直後に送信されます(返信の前)
  • 失敗はログに記録されますが、通常の返信配信をブロックしません
  • グループモードmentionsはメンションでトリガーされたターンでリアクションを送信します。グループアクティベーションalwaysはこのチェックをバイパスします
  • WhatsAppはchannels.whatsapp.ackReactionを使用します(レガシーのmessages.ackReactionはここでは適用されません)

マルチアカウントと認証情報

アカウント選択とデフォルト
- アカウントIDは`channels.whatsapp.accounts`から取得されます
- デフォルトアカウント選択:`default`が存在する場合はそれを使用、なければ最初の設定済みアカウントID(ソート順)
- アカウントIDはルックアップのため内部で正規化されます
認証情報パスとレガシー互換
- 現在の認証パス:`~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- バックアップファイル:`creds.json.bak`
- `~/.openclaw/credentials/`内のレガシーデフォルト認証はデフォルトアカウントフローで引き続き認識/移行されます
ログアウト動作
`openclaw channels logout --channel whatsapp [--account <id>]`で該当アカウントのWhatsApp認証状態をクリアします。

レガシー認証ディレクトリでは、`oauth.json`は保持されBaileys認証ファイルが削除されます。

ツール、アクション、設定書き込み

  • Agentツールとして WhatsAppリアクションアクション(react)をサポートしています。
  • アクションゲート:
    • channels.whatsapp.actions.reactions
    • channels.whatsapp.actions.polls
  • チャンネルから起動された設定書き込みはデフォルトで有効です(channels.whatsapp.configWrites=falseで無効化)。

トラブルシューティング

未リンク(QRコードが必要)
症状:チャンネルステータスが未リンクと表示される。

対処法:

```bash
openclaw channels login --channel whatsapp
openclaw channels status
```
リンク済みだが切断 / 再接続ループ
症状:リンク済みアカウントが繰り返し切断または再接続を試みる。

対処法:

```bash
openclaw doctor
openclaw logs --follow
```

必要に応じて`channels login`で再リンクしてください。
送信時にアクティブなリスナーがない
対象アカウントにアクティブなGatewayリスナーが存在しない場合、送信は即座に失敗します。

Gatewayが実行中であり、アカウントがリンクされていることを確認してください。
グループメッセージが予期せず無視される
以下の順序で確認してください:

- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- `groups`の許可リストエントリ
- メンションゲーティング(`requireMention` + メンションパターン)
- `openclaw.json`(JSON5)の重複キー:後のエントリが前のエントリをオーバーライドするため、スコープごとに`groupPolicy`は1つにしてください
Bunランタイムの警告
WhatsApp Gatewayランタイムにはnodeを使用してください。Bunは安定したWhatsApp/Telegram Gateway運用と互換性がないとフラグ付けされています。

設定リファレンスポインター

主なリファレンス:

WhatsAppの重要フィールド:

  • アクセス制御:dmPolicyallowFromgroupPolicygroupAllowFromgroups
  • 配信:textChunkLimitchunkModemediaMaxMbsendReadReceiptsackReaction
  • マルチアカウント:accounts.<id>.enabledaccounts.<id>.authDir、アカウントレベルオーバーライド
  • 運用:configWritesdebounceMsweb.enabledweb.heartbeatSecondsweb.reconnect.*
  • セッション動作:session.dmScopehistoryLimitdmHistoryLimitdms.<id>.historyLimit

関連項目