---
read_when:
    - Робота над поведінкою каналів WhatsApp/веб або маршрутизацією вхідних повідомлень
summary: Підтримка каналу WhatsApp, керування доступом, поведінка доставки та експлуатація
title: WhatsApp
x-i18n:
    generated_at: "2026-07-16T17:32:52Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: d9d6af1b32a428e0a35794fa4b5a8a861cb404a5b6848a265bf5d43f4cdad168
    source_path: channels/whatsapp.md
    workflow: 16
---

Статус: готово до промислової експлуатації через WhatsApp Web (Baileys). Gateway керує пов’язаними сеансами; окремого каналу Twilio WhatsApp немає.

## Установлення

`openclaw onboard` і `openclaw channels add --channel whatsapp` пропонують установити Plugin під час першого вибору; `openclaw channels login --channel whatsapp` пропонує такий самий процес установлення, якщо Plugin відсутній. Середовища розробки використовують локальний шлях до Plugin; стабільні та бета-версії спочатку встановлюють `@openclaw/whatsapp` із ClawHub, а в разі невдачі використовують npm. Середовище виконання WhatsApp постачається поза основним npm-пакетом OpenClaw, тому його залежності середовища виконання залишаються із зовнішнім Plugin. Установлення вручну:

```bash
openclaw plugins install clawhub:@openclaw/whatsapp
```

Використовуйте простий пакет npm (`@openclaw/whatsapp`) лише як резервний варіант реєстру; закріплюйте точну версію лише для відтворюваного встановлення.

<CardGroup cols={3}>
  <Card title="Сполучення" icon="link" href="/uk/channels/pairing">
    Типова політика особистих повідомлень для невідомих відправників — сполучення.
  </Card>
  <Card title="Усунення несправностей каналів" icon="wrench" href="/uk/channels/troubleshooting">
    Міжканальна діагностика та сценарії відновлення.
  </Card>
  <Card title="Конфігурація Gateway" icon="settings" href="/uk/gateway/configuration">
    Повні шаблони й приклади конфігурації каналів.
  </Card>
</CardGroup>

## Швидке налаштування

<Steps>
  <Step title="Налаштуйте політику доступу">

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

  </Step>

  <Step title="Пов’яжіть WhatsApp (QR-код)">

```bash
openclaw channels login --channel whatsapp
```

    Вхід можливий лише за QR-кодом. На віддалених хостах або хостах без графічного інтерфейсу перед початком входу забезпечте надійний спосіб доставити актуальний QR-код на телефон; QR-коди, відображені в терміналі, знімки екрана або вкладення в чаті можуть стати недійсними під час передавання.

    Для певного облікового запису:

```bash
openclaw channels login --channel whatsapp --account work
```

    Щоб підключити наявний або власний каталог автентифікації перед входом:

```bash
openclaw channels add --channel whatsapp --account work --auth-dir /path/to/wa-auth
openclaw channels login --channel whatsapp --account work
```

  </Step>

  <Step title="Запустіть Gateway">

```bash
openclaw gateway
```

  </Step>

  <Step title="Схваліть перший запит на сполучення (режим сполучення)">

```bash
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
```

    Термін дії запитів на сполучення спливає через 1 годину; кількість запитів в очікуванні обмежена до 3 на обліковий запис.

  </Step>
</Steps>

<Note>
Рекомендовано використовувати окремий номер WhatsApp (налаштування та метадані оптимізовано для нього), але конфігурації з особистим номером або чатом із самим собою також повністю підтримуються.
</Note>

## Схеми розгортання

<AccordionGroup>
  <Accordion title="Окремий номер (рекомендовано)">
    - окрема ідентичність WhatsApp для OpenClaw
    - чіткіші списки дозволених відправників особистих повідомлень і межі маршрутизації
    - нижча ймовірність плутанини з чатом із самим собою

    ```json5
    {
      channels: {
        whatsapp: {
          dmPolicy: "allowlist",
          allowFrom: ["+15551234567"],
        },
      },
    }
    ```

  </Accordion>

  <Accordion title="Резервний варіант з особистим номером">
    Початкове налаштування підтримує режим особистого номера та записує базову конфігурацію, придатну для чату із самим собою: `dmPolicy: "allowlist"`, `allowFrom`, що містить ваш власний номер, `selfChatMode: true`. Захист чату із самим собою під час виконання спирається на пов’язаний власний номер і `allowFrom`.
  </Accordion>
</AccordionGroup>

## Модель середовища виконання

- Gateway керує сокетом WhatsApp і циклом повторного підключення.
- Сторожовий процес незалежно відстежує два сигнали: активність необробленого транспорту WhatsApp Web та активність повідомлень застосунку. Тихий, але підключений сеанс не перезапускається лише через те, що останнім часом не надходили повідомлення; повторне підключення виконується примусово, тільки якщо транспортні кадри не надходять протягом фіксованого внутрішнього проміжку часу (користувач не може його налаштувати) або повідомлення застосунку не надходять довше ніж 4-кратний звичайний час очікування повідомлення. Відразу після повторного підключення нещодавно активного сеансу для першого проміжку використовується коротший звичайний час очікування повідомлення замість 4-кратного проміжку. OpenClaw може автоматично відповідати на офлайн-повідомлення, які Baileys доставляє на початку такого повторного підключення, у межах часу життя дедуплікації ідентифікаторів вхідних повідомлень; під час початкового запуску зберігається короткий захист від застарілої історії.
- Часові параметри сокета Baileys явно задаються в `web.whatsapp.*`: `keepAliveIntervalMs` (інтервал перевірки доступності застосунку), `connectTimeoutMs` (час очікування початкового рукостискання), `defaultQueryTimeoutMs` (очікування запитів Baileys, а також час очікування вихідного надсилання, присутності та вхідних підтверджень прочитання в OpenClaw).
- Для вихідного надсилання потрібен активний слухач WhatsApp для цільового облікового запису; інакше надсилання негайно завершується помилкою.
- До групових повідомлень додаються нативні метадані згадок для токенів `@+<digits>` і `@<digits>` (у тексті та підписах до медіафайлів), коли токен відповідає поточним метаданим учасника, зокрема в групах на основі LID.
- Чати статусів і трансляцій (`@status`, `@broadcast`) ігноруються.
- Прямі чати використовують правила сеансів особистих повідомлень (`session.dmScope`; типове значення `main` об’єднує особисті повідомлення в основному сеансі агента). Групові сеанси ізольовані для кожного JID (`agent:<agentId>:whatsapp:group:<jid>`).
- Канали/розсилки WhatsApp можуть бути явними цілями вихідного надсилання через власний JID `@newsletter`, використовуючи метадані сеансу каналу (`agent:<agentId>:whatsapp:channel:<jid>`), а не семантику особистих повідомлень.
- Транспорт WhatsApp Web враховує стандартні змінні середовища проксі на хості Gateway (`HTTPS_PROXY`, `HTTP_PROXY`, `NO_PROXY` та варіанти в нижньому регістрі). Надавайте перевагу налаштуванню проксі на рівні хоста, а не окремого каналу.
- Якщо ввімкнено `messages.removeAckAfterReply`, OpenClaw прибирає реакцію-підтвердження після доставки видимої відповіді.

## Виклик поточного запитувача через MeowCaller (експериментальна функція)

Plugin може надавати `whatsapp_call` у зверненнях агента, що надходять із WhatsApp. Він використовує [MeowCaller](https://github.com/purpshell/meowcaller), щоб здійснити голосовий виклик WhatsApp поточному авторизованому запитувачу та відтворити повідомлення TTS від OpenClaw після відповіді. Інструмент не має параметра номера призначення, тому запит не може переспрямувати виклик. Типово вимкнено.

<Warning>
MeowCaller є експериментальним, не має випуску з тегом і використовує окремо сполучений сеанс пов’язаного пристрою whatsmeow — він не може повторно використовувати облікові дані Baileys із Plugin. Сполучення додає ще один пов’язаний пристрій до того самого облікового запису WhatsApp; скануйте за допомогою ідентичності, яку використовує OpenClaw. У режимі особистого номера або чату із самим собою неможливо викликати самого себе; використовуйте окремий номер OpenClaw для виклику особистого номера.
</Warning>

<Steps>
  <Step title="Увімкніть експериментальні виклики">

    Додайте `actions.calls: true` до конфігурації каналу WhatsApp і перезапустіть Gateway:

```json
{
  "channels": {
    "whatsapp": {
      "actions": {
        "calls": true
      }
    }
  }
}
```

    Якщо значення відсутнє або дорівнює `false`, OpenClaw не надає інструмент `whatsapp_call`.

  </Step>

  <Step title="Установіть перевірений CLI MeowCaller">

    Адаптер очікує виконуваний файл `meowcaller` у `PATH` хоста Gateway. Поки [PR MeowCaller № 7](https://github.com/purpshell/meowcaller/pull/7) не об’єднано, зберіть перевірену гілку:

```bash
git clone --branch feat/send-only-notify https://github.com/steipete/meowcaller.git
cd meowcaller
git checkout 752050471fc2bf7a8cdfbf7dbd3cd4e865d85d3f
mkdir -p "$HOME/.local/bin"
go build -o "$HOME/.local/bin/meowcaller" ./cmd/meowcaller
```

    Переконайтеся, що `$HOME/.local/bin` входить до `PATH` служби Gateway. Ця ревізія має явні команди `pair` і `notify` лише для надсилання; `notify` не відкриває мікрофон, динамік, відеопристрій або діагностичне захоплення. Не замінюйте її командою `play` із прикладу CLI основного проєкту.

  </Step>

  <Step title="Сполучіть пов’язаний пристрій MeowCaller">

    Попросіть агента WhatsApp перевірити налаштування викликів (дія стану `whatsapp_call` повідомляє каталог стану для конкретного облікового запису та команду сполучення). Для типового облікового запису:

```bash
state_dir="$HOME/.openclaw/credentials/whatsapp-calls/default"
mkdir -p "$state_dir"
chmod 700 "$state_dir"
meowcaller pair --store "$state_dir/wa-voip.db"
```

    Запустіть це інтерактивно, відскануйте QR-код у **WhatsApp > Linked devices** і дочекайтеся `MeowCaller linked device ready`. Зберігайте `wa-voip.db` у таємниці — це сеанс MeowCaller. Нетипові облікові записи отримують власний шлях до сховища від дії стану; у Windows виконайте відповідну команду PowerShell.

  </Step>

  <Step title="Налаштуйте TTS і здійсніть виклик із WhatsApp">

    Налаштуйте [постачальника TTS](/uk/tools/tts), що підтримує телефонію, перезапустіть Gateway, а потім надішліть запит, наприклад `Call me and say the build finished.` Інструмент визначає відправника з довіреного вхідного контексту, синтезує тимчасовий приватний WAV-файл, запускає MeowCaller на обмежений проміжок виклику та після цього видаляє аудіофайл. OpenClaw явно передає сховище облікового запису, очікує нульового коду завершення після відповіді, відтворення та завершення виклику й вважає перевищення часу очікування або ненульовий код завершення невдалим викликом інструмента.

  </Step>
</Steps>

Обмеження: лише вихідні аудіовиклики один на один, без довільних номерів призначення, без спільної автентифікації зі з’єднанням чату, без викликів самого себе в режимі особистого номера або чату із самим собою, тривалість синтезованого аудіо обмежена 60 секундами, немає підтвердження чутності на телефоні понад завершення відповіді, відтворення та завершення виклику в MeowCaller, а OpenClaw зупиняє супровідний процес після обмеженого проміжку 115–175 секунд (що охоплює етапи підключення, відповіді, відтворення та завершення роботи MeowCaller).

## Запити на схвалення

WhatsApp може відображати запити на схвалення виконання та Plugin як реакції `👍`/`👎`, керовані конфігурацією пересилання схвалень верхнього рівня:

```json5
{
  approvals: {
    exec: {
      enabled: true,
      mode: "session",
    },
    plugin: {
      enabled: true,
      mode: "targets",
      targets: [{ channel: "whatsapp", to: "+15551234567" }],
    },
  },
}
```

`approvals.exec` і `approvals.plugin` незалежні; увімкнення WhatsApp як каналу лише пов’язує транспорт і нічого не надсилає, якщо відповідну групу схвалень не ввімкнено та не спрямовано туди. Режим сеансу доставляє нативні схвалення за допомогою емодзі лише для схвалень, що походять із WhatsApp. Режим цілей використовує спільний конвеєр пересилання для явних цілей і не створює окремого розгалуження особистих повідомлень для осіб, які схвалюють.

Для реакцій схвалення WhatsApp потрібні явно вказані особи, які схвалюють, у `allowFrom` (або `"*"`). `defaultTo` задає звичайні типові цілі повідомлень, а не список осіб, які схвалюють. Команди `/approve`, введені вручну, перед визначенням схвалення все одно проходять звичайний шлях авторизації відправника WhatsApp.

## Хуки Plugin і конфіденційність

Вхідні повідомлення WhatsApp можуть містити особистий вміст, номери телефонів, ідентифікатори груп, імена відправників і поля кореляції сеансів. WhatsApp не транслює вхідні дані хуків `message_received` до Plugin, якщо ви явно не погодилися:

```json5
{
  channels: {
    whatsapp: {
      pluginHooks: {
        messageReceived: true,
      },
    },
  },
}
```

Обмежте цю згоду одним обліковим записом у `channels.whatsapp.accounts.<id>.pluginHooks.messageReceived`. Вмикайте це лише для Plugin, яким довіряєте вхідний вміст та ідентифікатори WhatsApp.

## Керування доступом і активація

<Tabs>
  <Tab title="Політика особистих повідомлень">
    `channels.whatsapp.dmPolicy`:

    | Значення | Поведінка |
    | --- | --- |
    | `pairing` (типово) | Невідомі відправники запитують сполучення; власник схвалює |
    | `allowlist` | Допускаються лише відправники з `allowFrom` |
    | `open` | Вимагає, щоб `allowFrom` містив `"*"` |
    | `disabled` | Блокувати всі особисті повідомлення |

    `allowFrom` приймає номери у форматі E.164 (із внутрішньою нормалізацією). Це лише список керування доступом відправників особистих повідомлень — він не обмежує явне вихідне надсилання до групових JID або JID каналів `@newsletter`.

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

    Примітки щодо середовища виконання:

    - прив’язування зберігаються у сховищі дозволів каналу та об’єднуються з налаштованим `allowFrom`
    - запланована автоматизація та резервне визначення одержувача Heartbeat використовують явні цілі доставки або налаштований `allowFrom`; схвалення прив’язування приватних повідомлень не роблять їхніх учасників неявними одержувачами Cron/Heartbeat
    - якщо список дозволів не налаштовано, прив’язаний власний номер дозволено за замовчуванням
    - OpenClaw ніколи автоматично не прив’язує вихідні приватні повідомлення `fromMe` (повідомлення, які надсилаються самому собі з прив’язаного пристрою)

  </Tab>

  <Tab title="Політика груп і списки дозволів">
    Доступ до груп має два рівні:

    1. **Список дозволених груп** (`channels.whatsapp.groups`): якщо `groups` пропущено, усі групи доступні; якщо вказано, він діє як список дозволених груп (`"*"` дозволяє всі).
    2. **Політика щодо відправників у групах** (`channels.whatsapp.groupPolicy` + `groupAllowFrom`): `open` обходить список дозволених відправників, `allowlist` вимагає відповідності `groupAllowFrom` (або `*`), `disabled` блокує всі вхідні повідомлення з груп.

    Якщо `groupAllowFrom` не задано, перевірки відправників використовують як резервний `allowFrom`, коли він містить записи. Списки дозволених відправників перевіряються до активації згадкою або відповіддю.

    Якщо блок `channels.whatsapp` взагалі відсутній, середовище виконання використовує як резервний `groupPolicy: "allowlist"` (із попередженням у журналі), навіть якщо `channels.defaults.groupPolicy` має інше значення.

    <Note>
    Визначення належності до груп має запобіжник для одного облікового запису: якщо налаштовано лише один обліковий запис WhatsApp і його `accounts.<id>.groups` є явно порожнім об’єктом (`{}`), це вважається значенням «не задано», тож використовується коренева мапа `channels.whatsapp.groups`, а не мовчазне блокування всіх груп. Якщо налаштовано 2+ облікові записи, явно порожня мапа облікового запису залишається порожньою й резервна мапа не використовується — це дає змогу одному обліковому запису навмисно вимкнути всі групи, не впливаючи на інші.
    </Note>

  </Tab>

  <Tab title="Згадки та /activation">
    За замовчуванням для відповідей у групі потрібна згадка. Виявлення згадок охоплює:

    - явні згадки ідентичності бота у WhatsApp
    - налаштовані шаблони регулярних виразів для згадок (`agents.list[].groupChat.mentionPatterns`, резервний `messages.groupChat.mentionPatterns`)
    - транскрипції вхідних голосових нотаток для авторизованих групових повідомлень
    - неявне виявлення відповіді боту (відправник відповіді відповідає ідентичності бота)

    Безпека: цитування або відповідь лише задовольняє вимогу згадки — воно **не** надає авторизацію відправнику. З `groupPolicy: "allowlist"` відправники поза списком дозволів залишаються заблокованими, навіть коли відповідають на повідомлення користувача зі списку дозволів.

    Команда активації на рівні сеансу: `/activation mention` або `/activation always`. Вона оновлює стан сеансу (а не глобальну конфігурацію) і доступна лише власнику.

  </Tab>
</Tabs>

## Налаштовані прив’язування ACP

WhatsApp підтримує постійні прив’язування ACP через `bindings[]` верхнього рівня:

```json5
{
  bindings: [
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "whatsapp",
        accountId: "work",
        peer: { kind: "direct", id: "+15555550123" },
      },
    },
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "whatsapp",
        accountId: "work",
        peer: { kind: "group", id: "120363424282127706@g.us" },
      },
    },
  ],
}
```

Прямі чати зіставляються з номерами E.164, а групи — з груповими JID WhatsApp. Списки дозволених груп, політика щодо відправників і перевірка активації згадкою виконуються до того, як OpenClaw забезпечить існування прив’язаного сеансу ACP. Зіставлене прив’язування володіє маршрутом — групи трансляції не розподіляють цей хід між звичайними сеансами WhatsApp.

## Поведінка особистого номера та чату із собою

Коли прив’язаний власний номер також наявний у `allowFrom`, активуються запобіжники для чату із собою: пропускаються звіти про прочитання для ходів у чаті із собою, ігнорується автоматичне спрацювання за JID згадки, яке сповістило б вас самих, а відповіді за замовчуванням надсилаються до `[{identity.name}]` (або `[openclaw]`), коли `messages.responsePrefix` не задано.

## Нормалізація повідомлень і контекст

<AccordionGroup>
  <Accordion title="Вхідний конверт і контекст відповіді">
    Вхідні повідомлення загортаються у спільний вхідний конверт. Цитована відповідь додає контекст у такому вигляді:

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

    Метадані відповіді (`ReplyToId`, `ReplyToBody`, `ReplyToSender`, JID/E.164 відправника) заповнюються, коли доступні. Якщо цитованим об’єктом є медіафайл, доступний для завантаження, OpenClaw зберігає його через звичайне сховище вхідних медіафайлів і надає `MediaPath`/`MediaType`, щоб агент міг перевірити його безпосередньо, а не бачити лише `<media:image>`.

  </Accordion>

  <Accordion title="Заповнювачі медіафайлів і видобування розташування/контактів">
    Повідомлення, що містять лише медіафайли, нормалізуються до заповнювачів: `<media:image>`, `<media:video>`, `<media:audio>`, `<media:document>`, `<media:sticker>`.

    Авторизовані групові голосові нотатки транскрибуються до перевірки згадки, коли тіло містить лише `<media:audio>`, тому згадка бота в голосовій нотатці може спричинити відповідь. Якщо транскрипція все одно не згадує бота, вона залишається в історії групи, що очікує обробки, замість необробленого заповнювача.

    Дані про розташування відображаються як стислий текст із координатами. Мітки/коментарі розташування та дані контактів/vCard відображаються як огороджені ненадійні метадані, а не як вбудований текст запиту.

  </Accordion>

  <Accordion title="Вставлення історії групи, що очікує обробки">
    Необроблені групові повідомлення буферизуються та вставляються як контекст, коли бот нарешті активується.

    - обмеження за замовчуванням: `50`
    - конфігурація: `channels.whatsapp.historyLimit`, резервний `messages.groupChat.historyLimit`
    - `0` вимикає

    Маркери вставлення: `[Chat messages since your last reply - for context]` і `[Current message - respond to this]`.

  </Accordion>

  <Accordion title="Звіти про прочитання">
    За замовчуванням увімкнено для прийнятих вхідних повідомлень. Глобальне вимкнення:

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

    Перевизначення для окремого облікового запису: `channels.whatsapp.accounts.<id>.sendReadReceipts`. Для ходів у чаті із собою звіти про прочитання пропускаються, навіть якщо їх глобально ввімкнено.

  </Accordion>
</AccordionGroup>

## Доставка, поділ на фрагменти та медіафайли

<AccordionGroup>
  <Accordion title="Поділ тексту на фрагменти">
    - обмеження фрагмента за замовчуванням: `channels.whatsapp.textChunkLimit = 4000`
    - `channels.whatsapp.streaming.chunkMode = "length" | "newline"`; `newline` надає перевагу межам абзаців (порожнім рядкам), а потім переходить до безпечного поділу за довжиною

  </Accordion>

  <Accordion title="Поведінка вихідних медіафайлів">
    - підтримує корисні навантаження зображень, відео, аудіо (голосових нотаток PTT) і документів
    - аудіо надсилається як корисне навантаження Baileys `audio` з `ptt: true` і відображається як голосова нотатка push-to-talk; `audioAsVoice` зберігається в корисних навантаженнях відповіді, щоб виведення голосових нотаток TTS залишалося на цьому шляху незалежно від вихідного формату провайдера
    - власне аудіо Ogg/Opus надсилається як `audio/ogg; codecs=opus`; усе інше (зокрема вихідні дані Microsoft Edge TTS у форматі MP3/WebM) перед доставкою PTT перекодовується за допомогою `ffmpeg` у монофонічний Ogg/Opus із частотою 48 kHz
    - `/tts latest` надсилає останню відповідь асистента як одну голосову нотатку й запобігає повторному надсиланню тієї самої відповіді; `/tts chat on|off|default` керує автоматичним TTS для поточного чату
    - `gifPlayback: true` для відео вмикає відтворення анімованого GIF
    - `forceDocument`/`asDocument` спрямовує вихідні зображення, GIF і відео через корисне навантаження документа Baileys, щоб уникнути стиснення медіафайлів у WhatsApp, зберігаючи визначене ім’я файлу та тип MIME
    - підписи застосовуються до першого медіафайлу у відповіді з кількома медіафайлами, крім голосових нотаток PTT: аудіо надсилається першим без підпису, а потім підпис надсилається окремим текстовим повідомленням (клієнти WhatsApp відображають підписи голосових нотаток непослідовно)
    - джерелом медіафайлу може бути HTTP(S), `file://` або локальний шлях

  </Accordion>

  <Accordion title="Обмеження розміру медіафайлів і резервна поведінка">
    - обмеження збереження вхідних і надсилання вихідних даних: `channels.whatsapp.mediaMaxMb` (за замовчуванням `50`)
    - перевизначення для окремого облікового запису: `channels.whatsapp.accounts.<id>.mediaMaxMb`
    - зображення автоматично оптимізуються (зміна розміру/перебір якості), щоб відповідати обмеженням, якщо `forceDocument`/`asDocument` не вимагає доставки як документа
    - у разі помилки надсилання медіафайлу резервна поведінка для першого елемента надсилає текстове попередження, а не мовчки відкидає відповідь

  </Accordion>
</AccordionGroup>

## Цитування у відповідях

`channels.whatsapp.replyToMode` керує власним цитуванням у відповідях (вихідні відповіді помітно цитують вхідне повідомлення):

| Значення             | Поведінка                                                       |
| ----------------- | -------------------------------------------------------------- |
| `"off"` (за замовчуванням) | Ніколи не цитувати; надсилати як звичайне повідомлення                           |
| `"first"`         | Цитувати лише перший фрагмент вихідної відповіді                      |
| `"all"`           | Цитувати кожен фрагмент вихідної відповіді                               |
| `"batched"`       | Цитувати згруповані відповіді з черги; негайні відповіді залишати без цитування |

Перевизначення для окремого облікового запису: `channels.whatsapp.accounts.<id>.replyToMode`.

```json5
{ channels: { whatsapp: { replyToMode: "first" } } }
```

## Рівень реакцій

`channels.whatsapp.reactionLevel` визначає, наскільки широко агент використовує реакції емодзі:

| Рівень                 | Реакції-підтвердження | Реакції, ініційовані агентом  |
| --------------------- | ------------- | -------------------------- |
| `"off"`               | Ні            | Ні                         |
| `"ack"`               | Так           | Ні                         |
| `"minimal"` (за замовчуванням) | Так           | Так, консервативні настанови |
| `"extensive"`         | Так           | Так, заохочувальні настанови   |

Перевизначення для окремого облікового запису: `channels.whatsapp.accounts.<id>.reactionLevel`.

```json5
{ channels: { whatsapp: { reactionLevel: "ack" } } }
```

## Реакції-підтвердження

`channels.whatsapp.ackReaction` надсилає негайну реакцію після отримання вхідного повідомлення з урахуванням `reactionLevel` (не надсилається, коли `"off"`):

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

Примітки: надсилається одразу після прийняття вхідного повідомлення (до відповіді); якщо `ackReaction` наявний без `emoji`, WhatsApp використовує емодзі ідентичності спрямованого агента, а як резервний — "👀" (пропустіть `ackReaction` або задайте `emoji: ""`, щоб не надсилати підтвердження); помилки реєструються в журналі, але не блокують доставку відповіді; груповий режим `mentions` реагує лише на ходи, активовані згадкою, а групова активація `always` обходить цю перевірку; WhatsApp використовує лише `channels.whatsapp.ackReaction` (застарілий `messages.ackReaction` тут не застосовується).

## Реакції на стан життєвого циклу

Задайте `messages.statusReactions.enabled: true`, щоб WhatsApp замінював реакцію-підтвердження протягом ходу, а не залишав статичний емодзі отримання, циклічно переходячи між такими станами, як очікування в черзі, обмірковування, активність інструментів, Compaction, завершення та помилка:

```json5
{
  messages: {
    statusReactions: {
      enabled: true,
      emojis: {
        deploy: "🛫",
        build: "🏗️",
        concierge: "💁",
      },
    },
  },
}
```

Примітки: `channels.whatsapp.ackReaction` і надалі визначає доступність для прямих повідомлень і груп; стан очікування в черзі використовує той самий ефективний емодзі, що й звичайні реакції-підтвердження; WhatsApp має одне місце для реакції бота на повідомлення, тому оновлення життєвого циклу замінюють поточну реакцію на місці; `messages.removeAckAfterReply: true` прибирає остаточну реакцію стану після налаштованого періоду утримання для завершення/помилки; категорії емодзі інструментів охоплюють `tool`, `coding`, `web`, `deploy`, `build` і `concierge`.

## Кілька облікових записів і облікові дані

<AccordionGroup>
  <Accordion title="Вибір облікового запису та типові значення">
    Ідентифікатори облікових записів беруться з `channels.whatsapp.accounts`. Типово вибирається обліковий запис `default`, якщо він наявний; інакше — перший налаштований ідентифікатор облікового запису (за алфавітним сортуванням). Ідентифікатори облікових записів внутрішньо нормалізуються для пошуку.
  </Accordion>

  <Accordion title="Шляхи до облікових даних і сумісність із застарілими версіями">
    - поточний шлях автентифікації: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json` (резервна копія: `creds.json.bak`)
    - застаріла типова автентифікація в `~/.openclaw/credentials/` усе ще розпізнається та мігрується для сценаріїв із типовим обліковим записом

  </Accordion>

  <Accordion title="Поведінка під час виходу">
    `openclaw channels logout --channel whatsapp [--account <id>]` очищає стан автентифікації WhatsApp для цього облікового запису. Коли gateway доступний, вихід спочатку зупиняє активний слухач для цього облікового запису, тому пов’язаний сеанс припиняє отримувати повідомлення ще до наступного перезапуску. `openclaw channels remove --channel whatsapp` також зупиняє активний слухач перед вимкненням або видаленням конфігурації облікового запису.

    У застарілих каталогах автентифікації `oauth.json` зберігається, а файли автентифікації Baileys видаляються.

  </Accordion>
</AccordionGroup>

## Інструменти, дії та запис конфігурації

- Підтримка інструментів агента охоплює дію реакції WhatsApp (`react`).
- Обмежувачі дій: `channels.whatsapp.actions.reactions`, `channels.whatsapp.actions.polls` (типове значення для наявних дій — `true`), `channels.whatsapp.actions.calls` (типове значення — `false`, див. MeowCaller вище).
- Запис конфігурації, ініційований каналом, типово ввімкнено; вимкніть його через `channels.whatsapp.configWrites: false`.

## Усунення несправностей

<AccordionGroup>
  <Accordion title="Не пов’язано (потрібен QR-код)">
    Ознака: стан каналу повідомляє, що зв’язок не встановлено.

```bash
openclaw channels login --channel whatsapp
openclaw channels status
```

  </Accordion>

  <Accordion title="Пов’язано, але від’єднано / цикл повторного підключення">
    Ознака: пов’язаний обліковий запис із повторюваними від’єднаннями або спробами повторного підключення.

    Неактивні облікові записи можуть залишатися підключеними довше за звичайний тайм-аут повідомлень; сторожовий процес перезапускає з’єднання лише тоді, коли припиняється активність транспорту WhatsApp Web, закривається сокет або активність на рівні застосунку відсутня довше за збільшене захисне вікно (див. «Модель середовища виконання» вище).

    Якщо журнали містять повторювані `status=408 Request Time-out Connection was lost`, налаштуйте часові параметри сокета Baileys у `web.whatsapp`. Спочатку зменште `keepAliveIntervalMs` до значення, нижчого за тайм-аут бездіяльності вашої мережі, і збільште `connectTimeoutMs` для повільних з’єднань або з’єднань із втратами:

    ```json5
    {
      web: {
        whatsapp: {
          keepAliveIntervalMs: 15000,
          connectTimeoutMs: 60000,
          defaultQueryTimeoutMs: 60000,
        },
      },
    }
    ```

    Виправлення:

    ```bash
    openclaw channels status --probe
    openclaw doctor
    openclaw logs --follow
    openclaw gateway status
    ```

    Якщо цикл зберігається після виправлення підключення хоста та часових параметрів, створіть резервну копію каталогу автентифікації облікового запису й повторно встановіть зв’язок:

    ```bash
    cp -a ~/.openclaw/credentials/whatsapp/<accountId> \
      ~/.openclaw/credentials/whatsapp/<accountId>.bak
    openclaw channels logout --channel whatsapp --account <accountId>
    openclaw channels login --channel whatsapp --account <accountId>
    ```

    Якщо `~/.openclaw/logs/whatsapp-health.log` повідомляє `Gateway inactive`, але `openclaw gateway status` і `openclaw channels status --probe` обидва показують справний стан, виконайте `openclaw doctor`. У Linux doctor попереджає про застарілі записи crontab, що викликають виведений з експлуатації скрипт `~/.openclaw/bin/ensure-whatsapp.sh`; видаліть ці записи за допомогою `crontab -e` — у cron може бути відсутнє середовище користувацької шини systemd, через що старий скрипт неправильно повідомляє про стан gateway.

  </Accordion>

  <Accordion title="Час очікування входу за QR-кодом спливає за проксі-сервером">
    Ознака: `openclaw channels login --channel whatsapp` завершується помилкою до показу придатного для використання QR-коду з `status=408 Request Time-out` або від’єднанням TLS-сокета.

    Вхід у WhatsApp Web використовує стандартне проксі-середовище хоста gateway (`HTTPS_PROXY`, `HTTP_PROXY`, варіанти в нижньому регістрі, `NO_PROXY`). Переконайтеся, що процес gateway успадковує змінні середовища проксі та що `NO_PROXY` не відповідає `mmg.whatsapp.net`.

  </Accordion>

  <Accordion title="Немає активного слухача під час надсилання">
    Вихідне надсилання негайно завершується помилкою, якщо для цільового облікового запису немає активного слухача gateway. Переконайтеся, що gateway запущено, а обліковий запис пов’язано.
  </Accordion>

  <Accordion title="Відповідь є в транскрипті, але відсутня у WhatsApp">
    Рядки транскрипту фіксують те, що згенерував агент; доставку у WhatsApp перевіряють окремо. OpenClaw вважає автоматичну відповідь надісланою лише після того, як Baileys поверне ідентифікатор вихідного повідомлення принаймні для одного видимого надсилання тексту або медіафайлу.

    Реакції-підтвердження є незалежними квитанціями, що надсилаються до відповіді, — успішна реакція не доводить, що подальшу текстову або медіавідповідь було прийнято. Перевірте журнали gateway на наявність `auto-reply delivery failed` або `auto-reply was not accepted by WhatsApp provider`.

  </Accordion>

  <Accordion title="Повідомлення групи неочікувано ігноруються">
    Перевірте в такому порядку: `groupPolicy`, `groupAllowFrom`/`allowFrom`, записи списку дозволів `groups`, обмеження за згадкою (`requireMention` + шаблони згадок) і дублікати ключів у `openclaw.json` (у JSON5 пізніші записи перевизначають попередні — залишайте лише один `groupPolicy` для кожної області).

    Якщо наявний `channels.whatsapp.groups`, WhatsApp усе ще може бачити повідомлення з інших груп, але OpenClaw відкидає їх до маршрутизації сеансу. Додайте JID групи до `channels.whatsapp.groups` або додайте `groups["*"]`, щоб дозволити всі групи, зберігши авторизацію відправників через `groupPolicy`/`groupAllowFrom`.

  </Accordion>

  <Accordion title="Попередження середовища виконання Bun">
    Для gateway OpenClaw потрібен Node. Bun не надає API `node:sqlite`, який використовує канонічне сховище стану, а doctor мігрує застарілі служби Bun на Node.
  </Accordion>
</AccordionGroup>

## Системні підказки

WhatsApp підтримує системні підказки в стилі Telegram для груп і прямих чатів через мапи `groups` та `direct`.

Визначення для групових повідомлень: спочатку визначається ефективна мапа `groups` — якщо обліковий запис узагалі визначає власний ключ `groups`, він повністю замінює кореневу мапу `groups` (без глибокого злиття). Потім пошук підказки виконується в цій єдиній отриманій мапі:

1. **Підказка для конкретної групи** (`groups["<groupId>"].systemPrompt`): використовується, коли запис групи існує **і** визначено його ключ `systemPrompt`. Порожній рядок (`""`) пригнічує шаблон і не застосовує жодної підказки.
2. **Групова підказка-шаблон** (`groups["*"].systemPrompt`): використовується, коли запис конкретної групи відсутній або існує без ключа `systemPrompt`.

Визначення для прямих повідомлень виконується за тією самою схемою для мапи `direct` і `direct["*"]`.

<Note>
`dms` залишається полегшеним контейнером перевизначення історії для кожного приватного повідомлення (`dms.<id>.historyLimit`). Перевизначення підказок розміщуються в `direct`.
</Note>

<Note>
Поведінка «обліковий запис замінює корінь» для визначення підказок є звичайним неглибоким перевизначенням: будь-який ключ `groups`/`direct` облікового запису, включно з явно заданим порожнім об’єктом, замінює кореневу мапу. Це відрізняється від описаної вище перевірки списку дозволів членства в групах, яка має захисний механізм для одного облікового запису на випадок випадково порожнього `groups: {}`.
</Note>

**Відмінність від Telegram:** Telegram пригнічує кореневий `groups` для кожного облікового запису в конфігурації з кількома обліковими записами (навіть для облікових записів без власного `groups`), щоб бот не отримував групові повідомлення з груп, до яких він не належить. WhatsApp не застосовує цей захист — кореневі `groups`/`direct` успадковуються будь-яким обліковим записом без власного перевизначення незалежно від кількості облікових записів. У конфігурації WhatsApp із кількома обліковими записами явно визначте повну мапу для кожного облікового запису, якщо потрібні окремі підказки для кожного з них.

Важливі аспекти поведінки:

- `channels.whatsapp.groups` є одночасно мапою конфігурації для кожної групи та списком дозволів груп на рівні чату. На кореневому рівні або рівні облікового запису `groups["*"]` означає «дозволено всі групи» для цієї області.
- Додавайте шаблон `systemPrompt` лише тоді, коли вже потрібно дозволити всі групи в цій області. Щоб дозволити лише фіксований набір ідентифікаторів груп, повторіть підказку в кожному явно дозволеному записі замість використання `groups["*"]`.
- Допуск груп і авторизація відправників є окремими перевірками. `groups["*"]` розширює перелік груп, що потрапляють до обробки груп; він не авторизує кожного відправника в цих групах — це й надалі контролюється через `groupPolicy`/`groupAllowFrom`.
- `channels.whatsapp.direct` не має аналогічного побічного ефекту для приватних повідомлень: `direct["*"]` лише надає типову конфігурацію після того, як приватне повідомлення вже допущено через `dmPolicy` разом із `allowFrom` або правилами сховища пов’язування.

Приклад:

```json5
{
  channels: {
    whatsapp: {
      groups: {
        // Використовуйте лише тоді, коли на кореневому рівні потрібно дозволити всі групи.
        // Застосовується до всіх облікових записів, які не визначають власну мапу groups.
        "*": { systemPrompt: "Типова підказка для всіх груп." },
      },
      direct: {
        // Застосовується до всіх облікових записів, які не визначають власну мапу direct.
        "*": { systemPrompt: "Типова підказка для всіх прямих чатів." },
      },
      accounts: {
        work: {
          groups: {
            // Цей обліковий запис визначає власну мапу groups, тому кореневу мапу groups повністю
            // замінено. Щоб зберегти шаблон, явно визначте "*" також тут.
            "120363406415684625@g.us": {
              requireMention: false,
              systemPrompt: "Зосереджуйтеся на керуванні проєктами.",
            },
            // Використовуйте лише тоді, коли в цьому обліковому записі потрібно дозволити всі групи.
            "*": { systemPrompt: "Типова підказка для робочих груп." },
          },
          direct: {
            // Цей обліковий запис визначає власну мапу direct, тому кореневі записи direct
            // повністю замінено. Щоб зберегти шаблон, явно визначте "*" також тут.
            "+15551234567": { systemPrompt: "Підказка для конкретного робочого прямого чату." },
            "*": { systemPrompt: "Типова підказка для робочих прямих чатів." },
          },
        },
      },
    },
  },
}
```

## Посилання на довідник конфігурації

Основний довідник: [Довідник конфігурації — WhatsApp](/uk/gateway/config-channels#whatsapp)

| Область          | Поля                                                                                                           |
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
| Доступ           | `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`                                             |
| Доставка         | `textChunkLimit`, `streaming.chunkMode`, `mediaMaxMb`, `sendReadReceipts`, `ackReaction`, `reactionLevel`      |
| Кілька облікових записів | `accounts.<id>.enabled`, `accounts.<id>.authDir` та інші перевизначення для кожного облікового запису                              |
| Операції         | `configWrites`, `debounceMs`, `web.enabled`, `web.heartbeatSeconds`, `web.reconnect.*`, `web.whatsapp.*`       |
| Поведінка сеансу | `session.dmScope`, `historyLimit`, `dmHistoryLimit`, `dms.<id>.historyLimit`                                   |
| Підказки         | `groups.<id>.systemPrompt`, `groups["*"].systemPrompt`, `direct.<id>.systemPrompt`, `direct["*"].systemPrompt` |

## Пов’язані матеріали

- [Пов’язування](/uk/channels/pairing)
- [Групи](/uk/channels/groups)
- [Безпека](/uk/gateway/security)
- [Маршрутизація каналів](/uk/channels/channel-routing)
- [Маршрутизація між кількома агентами](/uk/concepts/multi-agent)
- [Усунення несправностей](/uk/channels/troubleshooting)
