Tin nhắn nhóm (WhatsApp web channel)

Mục tiêu: cho phép Clawd tham gia các nhóm WhatsApp, chỉ hoạt động khi được nhắc đến, và giữ thread đó tách biệt với Session DM cá nhân.

Lưu ý: agents.list[].groupChat.mentionPatterns giờ cũng được dùng bởi Telegram/Discord/Slack/iMessage; tài liệu này tập trung vào hành vi đặc thù của WhatsApp. Với thiết lập multi-agent, các bạn cần đặt agents.list[].groupChat.mentionPatterns cho từng Agent (hoặc dùng messages.groupChat.mentionPatterns làm fallback toàn cục).

Những gì đã được triển khai (2025-12-03)

  • Chế độ kích hoạt: mention (mặc định) hoặc always. Chế độ mention yêu cầu một ping (WhatsApp @-mentions thực qua mentionedJids, regex patterns, hoặc số E.164 của bot ở bất kỳ đâu trong text). Chế độ always đánh thức Agent ở mọi tin nhắn nhưng nó chỉ nên trả lời khi có thể thêm giá trị có ý nghĩa; nếu không nó trả về token im lặng NO_REPLY. Giá trị mặc định có thể đặt trong config (channels.whatsapp.groups) và ghi đè cho từng nhóm qua /activation. Khi channels.whatsapp.groups được đặt, nó cũng hoạt động như allowlist nhóm (thêm "*" để cho phép tất cả).
  • Group policy: channels.whatsapp.groupPolicy kiểm soát việc có chấp nhận tin nhắn nhóm không (open|disabled|allowlist). Chế độ allowlist dùng channels.whatsapp.groupAllowFrom (fallback: channels.whatsapp.allowFrom tường minh). Mặc định là allowlist (bị chặn cho đến khi các bạn thêm người gửi).
  • Per-group sessions: các session key có dạng agent:<agentId>:whatsapp:group:<jid> nên các lệnh như /verbose on hoặc /think high (gửi dưới dạng tin nhắn độc lập) được giới hạn trong nhóm đó; trạng thái DM cá nhân không bị ảnh hưởng. Heartbeats bị bỏ qua cho các thread nhóm.
  • Context injection: tin nhắn nhóm pending-only (mặc định 50) mà không kích hoạt một run sẽ được thêm tiền tố dưới [Chat messages since your last reply - for context], với dòng kích hoạt dưới [Current message - respond to this]. Các tin nhắn đã có trong Session không được inject lại.
  • Sender surfacing: mỗi batch nhóm giờ kết thúc với [from: Sender Name (+E164)] để Pi biết ai đang nói.
  • Ephemeral/view-once: mình unwrap chúng trước khi trích xuất text/mentions, nên các ping bên trong chúng vẫn kích hoạt.
  • Group system prompt: ở lượt đầu tiên của một group session (và bất cứ khi nào /activation thay đổi chế độ) mình inject một đoạn ngắn vào system prompt kiểu như 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. Nếu metadata không có sẵn, mình vẫn báo cho Agent biết đó là group chat.

Ví dụ config (WhatsApp)

Thêm block groupChat vào ~/.openclaw/openclaw.json để display-name pings hoạt động ngay cả khi WhatsApp bỏ dấu @ hiển thị trong text body:

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

Lưu ý:

  • Các regex không phân biệt chữ hoa chữ thường; chúng bao gồm display-name ping như @openclaw và số thô có hoặc không có +/khoảng trắng.
  • WhatsApp vẫn gửi canonical mentions qua mentionedJids khi ai đó tap vào contact, nên fallback số hiếm khi cần nhưng là một safety net hữu ích.

Lệnh Activation (chỉ owner)

Dùng lệnh group chat:

  • /activation mention
  • /activation always

Chỉ số owner (từ channels.whatsapp.allowFrom, hoặc E.164 của chính bot khi không đặt) mới có thể thay đổi điều này. Gửi /status dưới dạng tin nhắn độc lập trong nhóm để xem chế độ activation hiện tại.

Cách sử dụng

  1. Thêm tài khoản WhatsApp của các bạn (cái đang chạy OpenClaw) vào nhóm.
  2. Nói @openclaw … (hoặc bao gồm số). Chỉ những người gửi trong allowlist mới có thể kích hoạt nó trừ khi các bạn đặt groupPolicy: "open".
  3. Agent prompt sẽ bao gồm Context nhóm gần đây cộng với marker [from: …] ở cuối để nó có thể xưng hô đúng người.
  4. Các chỉ thị cấp Session (/verbose on, /think high, /new hoặc /reset, /compact) chỉ áp dụng cho Session của nhóm đó; gửi chúng dưới dạng tin nhắn độc lập để chúng được đăng ký. Session DM cá nhân của các bạn vẫn độc lập.

Testing / verification

  • Manual smoke:
    • Gửi một ping @openclaw trong nhóm và xác nhận một reply tham chiếu đến tên người gửi.
    • Gửi ping thứ hai và xác minh history block được bao gồm rồi xóa ở lượt tiếp theo.
  • Check gateway logs (chạy với --verbose) để xem các entry inbound web message hiển thị from: <groupJid> và suffix [from: …].

Những điểm cần lưu ý

  • Heartbeats cố ý bị bỏ qua cho các nhóm để tránh broadcasts ồn ào.
  • Echo suppression dùng combined batch string; nếu các bạn gửi text giống hệt hai lần mà không có mentions, chỉ lần đầu tiên sẽ nhận được response.
  • Các entry session store sẽ xuất hiện dưới dạng agent:<agentId>:whatsapp:group:<jid> trong session store (~/.openclaw/agents/<agentId>/sessions/sessions.json theo mặc định); một entry bị thiếu chỉ có nghĩa là nhóm chưa kích hoạt run nào.
  • Typing indicators trong nhóm tuân theo agents.defaults.typingMode (mặc định: message khi không được mention).