WhatsApp (Web-канал)

Статус: готов к продуктивному использованию через WhatsApp Web (Baileys). Шлюз владеет привязанными сессиями.

Быстрая настройка

Шаг 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: Запустите шлюз

openclaw gateway

Шаг 4: Подтвердите первый запрос спаривания (при использовании режима спаривания)

openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
Запросы спаривания истекают через 1 час. Максимум 3 ожидающих запроса на канал.

Примечание: OpenClaw рекомендует запускать WhatsApp на отдельном номере, когда это возможно. (Метаданные канала и процесс настройки оптимизированы для такой конфигурации, но использование личного номера тоже поддерживается.)

Паттерны развёртывания

Выделенный номер (рекомендуется)
Наиболее чистый режим работы:

- отдельная идентичность WhatsApp для OpenClaw
- более ясные списки доступа ЛС и границы маршрутизации
- меньше шансов на путаницу с самочатом

Минимальный паттерн политики:

```json5
{
  channels: {
    whatsapp: {
      dmPolicy: "allowlist",
      allowFrom: ["+15551234567"],
    },
  },
}
```
Запасной вариант с личным номером
Настройка поддерживает режим личного номера и записывает базовую конфигурацию для самочата:

- `dmPolicy: "allowlist"`
- `allowFrom` включает ваш личный номер
- `selfChatMode: true`

В runtime защита самочата привязана к привязанному номеру и `allowFrom`.
Область действия канала WhatsApp Web
Канал мессенджера реализован через WhatsApp Web (`Baileys`) в текущей архитектуре каналов OpenClaw.

Отдельного канала Twilio WhatsApp во встроенном реестре каналов нет.

Модель выполнения

  • Шлюз владеет сокетом WhatsApp и циклом переподключения.
  • Исходящая отправка требует активного слушателя WhatsApp для целевого аккаунта.
  • Статусные и широковещательные чаты игнорируются (@status, @broadcast).
  • Прямые чаты используют правила ЛС-сессий (session.dmScope; по умолчанию main объединяет ЛС в основную сессию агента).
  • Групповые сессии изолированы (agent:<agentId>:whatsapp:group:<jid>).

Контроль доступа и активация

Политика ЛС

`channels.whatsapp.dmPolicy` управляет доступом к прямым чатам:

- `pairing` (по умолчанию)
- `allowlist`
- `open` (требуется `allowFrom` с `"*"`)
- `disabled`

`allowFrom` принимает номера в формате E.164 (нормализуются внутренне).

Переопределение для мульти-аккаунтов: `channels.whatsapp.accounts.<id>.dmPolicy` (и `allowFrom`) имеют приоритет над значениями по умолчанию на уровне канала для данного аккаунта.

Детали поведения в runtime:

- спаривания сохраняются в хранилище разрешений канала и объединяются с настроенным `allowFrom`
- если список доступа не настроен, привязанный собственный номер разрешён по умолчанию
- исходящие ЛС `fromMe` никогда не спариваются автоматически

Групповая политика + списки доступа

Доступ к группам имеет два уровня:

1. **Список доступа по членству в группе** (`channels.whatsapp.groups`)
   - если `groups` не задан, все группы допускаются
   - если `groups` задан, действует как список доступа групп (`"*"` допускается)

2. **Политика отправителей в группах** (`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
   - `open`: список доступа отправителей обходится
   - `allowlist`: отправитель должен совпадать с `groupAllowFrom` (или `*`)
   - `disabled`: блокировать все входящие от групп

Fallback списка доступа отправителей:

- если `groupAllowFrom` не задан, runtime использует fallback к `allowFrom` при наличии
- списки доступа отправителей проверяются до проверки активации по упоминанию/ответу

Примечание: если блок `channels.whatsapp` вообще отсутствует, runtime-fallback для групповой политики — `allowlist` (с предупреждением в логах), даже если задан `channels.defaults.groupPolicy`.

Упоминания + /activation

Ответы в группах требуют упоминания по умолчанию.

Обнаружение упоминания включает:

- явные упоминания WhatsApp с идентичностью бота
- настроенные regex-паттерны упоминания (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`)
- неявное обнаружение ответа боту (отправитель ответа совпадает с идентичностью бота)

Примечание по безопасности:

- цитата/ответ удовлетворяет только гейтинг по упоминанию; это **не** даёт авторизацию отправителя
- при `groupPolicy: "allowlist"` неавторизованные отправители всё равно блокируются, даже если они отвечают на сообщение авторизованного пользователя

Команда активации на уровне сессии:

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

`activation` обновляет состояние сессии (не глобальную конфигурацию). Ограничена для владельца.

Поведение самочата с личным номером

Когда привязанный собственный номер присутствует в allowFrom, активируются защиты самочата WhatsApp:

  • пропуск подтверждений прочтения для поворотов самочата
  • игнорирование автосрабатывания по mention-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>`

Данные геолокации и контактов нормализуются в текстовый контекст перед маршрутизацией.
Инъекция ожидающей групповой истории
Для групп необработанные сообщения могут буферизоваться и инъецироваться как контекст при активации бота.

- лимит по умолчанию: `50`
- конфиг: `channels.whatsapp.historyLimit`
- fallback: `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` предпочитает границы абзацев (пустые строки), затем использует fallback к разбивке по длине
Исходящее поведение медиа
- поддерживаются изображения, видео, аудио (PTT-голосовая заметка) и документы
- `audio/ogg` переписывается на `audio/ogg; codecs=opus` для совместимости с голосовыми заметками
- воспроизведение анимированных GIF поддерживается через `gifPlayback: true` при отправке видео
- подписи применяются к первому медиа-элементу при отправке мульти-медийных ответов
- источник медиа: HTTP(S), `file://` или локальные пути
Ограничения размера медиа и поведение при ошибке
- лимит входящего медиа: `channels.whatsapp.mediaMaxMb` (по умолчанию `50`)
- лимит исходящего медиа: `channels.whatsapp.mediaMaxMb` (по умолчанию `50`)
- переопределение для аккаунтов: `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
- изображения автоматически оптимизируются (перебор размера/качества) для соответствия лимитам
- при ошибке отправки медиа, fallback первого элемента отправляет текстовое предупреждение вместо беззвучного отбрасывания ответа

Реакции подтверждения

WhatsApp поддерживает мгновенные реакции подтверждения при получении входящего сообщения через channels.whatsapp.ackReaction.

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

Заметки о поведении:

  • отправляется сразу после принятия входящего (до ответа)
  • ошибки логируются, но не блокируют нормальную доставку ответа
  • групповой режим mentions реагирует на повороты с упоминанием; групповая активация always обходит эту проверку
  • WhatsApp использует channels.whatsapp.ackReaction (устаревший messages.ackReaction здесь не используется)

Мульти-аккаунт и учётные данные

Выбор аккаунта и значения по умолчанию
- идентификаторы аккаунтов берутся из `channels.whatsapp.accounts`
- выбор аккаунта по умолчанию: `default`, если присутствует, иначе первый настроенный ID аккаунта (отсортировано)
- идентификаторы аккаунтов нормализуются внутренне для поиска
Пути учётных данных и совместимость с устаревшими версиями
- текущий путь аутентификации: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- файл резервной копии: `creds.json.bak`
- устаревшая аутентификация по умолчанию в `~/.openclaw/credentials/` по-прежнему распознаётся/мигрируется для потоков аккаунта по умолчанию
Поведение выхода
`openclaw channels logout --channel whatsapp [--account <id>]` очищает состояние аутентификации WhatsApp для данного аккаунта.

В устаревших каталогах аутентификации `oauth.json` сохраняется, а файлы аутентификации Baileys удаляются.

Инструменты, действия и запись конфигурации

  • Инструменты агента включают действие реакции 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`.
Нет активного слушателя при отправке
Исходящие отправки завершаются ошибкой, если нет активного слушателя шлюза для целевого аккаунта.

Убедитесь, что шлюз запущен и аккаунт привязан.
Групповые сообщения неожиданно игнорируются
Проверьте в следующем порядке:

- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- записи списка доступа `groups`
- гейтинг по упоминанию (`requireMention` + паттерны упоминания)
- дублирующиеся ключи в `openclaw.json` (JSON5): поздние записи переопределяют ранние, поэтому держите один `groupPolicy` на область видимости
Предупреждение о среде выполнения Bun
Среда выполнения шлюза WhatsApp должна использовать Node. Bun отмечен как несовместимый для стабильной работы шлюза WhatsApp/Telegram.

Указатели на справочник конфигурации

Основной справочник:

Ключевые поля WhatsApp:

  • доступ: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups
  • доставка: textChunkLimit, chunkMode, mediaMaxMb, sendReadReceipts, ackReaction
  • мульти-аккаунт: accounts.<id>.enabled, accounts.<id>.authDir, переопределения на уровне аккаунта
  • эксплуатация: configWrites, debounceMs, web.enabled, web.heartbeatSeconds, web.reconnect.*
  • поведение сессий: session.dmScope, historyLimit, dmHistoryLimit, dms.<id>.historyLimit

Связанное