Групповые сообщения (веб-канал WhatsApp)

Цель: дать Clawd находиться в группах WhatsApp, просыпаться только при обращении и вести эту ветку отдельно от личной DM-сессии.

Примечание: agents.list[].groupChat.mentionPatterns теперь используется и в Telegram/Discord/Slack/iMessage; данный документ описывает поведение, специфичное для WhatsApp. Для мульти-агентных конфигураций задавайте agents.list[].groupChat.mentionPatterns для каждого агента (или используйте messages.groupChat.mentionPatterns как глобальный fallback).

Что реализовано (2025-12-03)

  • Режимы активации: mention (по умолчанию) или always. Режим mention требует обращения (реальные @-упоминания WhatsApp через mentionedJids, regex-шаблоны или E.164 бота где-либо в тексте). Режим always активирует агента на каждом сообщении, но он должен отвечать, только когда может внести значимый вклад; в противном случае возвращает маркер молчания NO_REPLY. Значения по умолчанию задаются в конфиге (channels.whatsapp.groups) и могут быть переопределены для каждой группы через /activation. Если channels.whatsapp.groups задан, он также действует как список разрешённых групп (добавьте "*", чтобы разрешить все).
  • Политика групп: channels.whatsapp.groupPolicy определяет, принимаются ли групповые сообщения (open|disabled|allowlist). allowlist использует channels.whatsapp.groupAllowFrom (fallback: явный channels.whatsapp.allowFrom). По умолчанию — allowlist (заблокировано, пока вы не добавите отправителей).
  • Сессии для каждой группы: ключи сессий имеют вид agent:<agentId>:whatsapp:group:<jid>, поэтому команды вроде /verbose on или /think high (отправленные как отдельные сообщения) ограничены данной группой; состояние личного DM не затрагивается. Heartbeat пропускаются для групповых потоков.
  • Инъекция контекста: ожидающие групповые сообщения (по умолчанию 50), которые не вызвали запуск, добавляются с префиксом [Chat messages since your last reply - for context], а вызвавшее сообщение — под [Current message - respond to this]. Сообщения, уже находящиеся в сессии, не инъектируются повторно.
  • Указание отправителя: каждый групповой пакет теперь заканчивается [from: Sender Name (+E164)], чтобы Pi знал, кто говорит.
  • Эфемерные/одноразовые: разворачиваются перед извлечением текста/упоминаний, поэтому обращения внутри них по-прежнему срабатывают.
  • Системный промпт группы: при первом повороте групповой сессии (и при каждом изменении /activation режима) внедряется короткое пояснение в системный промпт вида You are replying inside the WhatsApp group "<subject>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context. Если метаданные недоступны, агенту всё равно сообщается, что это групповой чат.

Пример конфигурации (WhatsApp)

Добавьте блок groupChat в ~/.openclaw/openclaw.json, чтобы обращения по отображаемому имени работали даже когда WhatsApp убирает визуальный @ из тела текста:

{
  channels: {
    whatsapp: {
      groups: {
        "*": { requireMention: true },
      },
    },
  },
  agents: {
    list: [
      {
        id: "main",
        groupChat: {
          historyLimit: 50,
          mentionPatterns: ["@?openclaw", "\\+?15555550123"],
        },
      },
    ],
  },
}

Примечания:

  • Регулярные выражения регистронезависимы; они покрывают обращение по отображаемому имени вроде @openclaw и номер с +/пробелами или без них.
  • WhatsApp всё равно отправляет канонические упоминания через mentionedJids при нажатии на контакт, поэтому fallback по номеру нужен редко, но полезен как страховка.

Команда активации (только для владельца)

Используйте команду в групповом чате:

  • /activation mention
  • /activation always

Менять может только владелец (из channels.whatsapp.allowFrom или E.164 самого бота, если не задано). Отправьте /status как отдельное сообщение в группе, чтобы увидеть текущий режим активации.

Как использовать

  1. Добавьте свой аккаунт WhatsApp (на котором работает OpenClaw) в группу.
  2. Напишите @openclaw … (или включите номер). Только одобренные отправители могут вызвать бота, если не установлено groupPolicy: "open".
  3. Промпт агента будет содержать недавний контекст группы плюс маркер [from: …], чтобы обращаться к нужному человеку.
  4. Директивы уровня сессии (/verbose on, /think high, /new или /reset, /compact) применяются только к сессии этой группы; отправляйте их как отдельные сообщения. Ваша личная DM-сессия остаётся независимой.

Тестирование / проверка

  • Ручной smoke-тест:
    • Отправьте @openclaw-обращение в группе и убедитесь, что ответ ссылается на имя отправителя.
    • Отправьте второе обращение и убедитесь, что блок истории включён, а затем очищен на следующем повороте.
  • Проверьте логи шлюза (запускайте с --verbose), чтобы увидеть записи inbound web message с from: <groupJid> и суффиксом [from: …].

Известные особенности

  • Heartbeat намеренно пропускаются для групп, чтобы избежать шумных рассылок.
  • Подавление эхо использует объединённую строку пакета; если вы отправите идентичный текст дважды без упоминаний, ответ будет только на первый.
  • Записи хранилища сессий будут отображаться как agent:<agentId>:whatsapp:group:<jid> в хранилище сессий (~/.openclaw/agents/<agentId>/sessions/sessions.json по умолчанию); отсутствие записи просто означает, что группа ещё не вызывала запуск.
  • Индикаторы набора в группах следуют agents.defaults.typingMode (по умолчанию: message, когда не упомянут).