Gruppennachrichten (WhatsApp Web Channel)

Ziel: Clawd sitzt in WhatsApp-Gruppen, wacht nur auf wenn er gepingt wird, und hält diesen Thread getrennt von der persönlichen DM-Session.

Hinweis: agents.list[].groupChat.mentionPatterns wird jetzt auch von Telegram/Discord/Slack/iMessage verwendet; dieses Dokument konzentriert sich auf WhatsApp-spezifisches Verhalten. Bei Multi-Agent-Setups setzt du agents.list[].groupChat.mentionPatterns pro Agent (oder nutze messages.groupChat.mentionPatterns als globalen Fallback).

Was implementiert ist (03.12.2025)

  • Aktivierungsmodi: mention (Standard) oder always. mention erfordert einen Ping (echte WhatsApp @-Mentions via mentionedJids, Regex-Patterns oder die E.164-Nummer des Bots irgendwo im Text). always weckt den Agent bei jeder Nachricht, aber er antwortet nur wenn er echten Mehrwert bieten kann; sonst gibt er das stille Token NO_REPLY zurück. Standardwerte kannst du in der Config setzen (channels.whatsapp.groups) und pro Gruppe via /activation überschreiben. Wenn channels.whatsapp.groups gesetzt ist, fungiert es auch als Gruppen-Allowlist (füge "*" hinzu um alle zu erlauben).
  • Gruppenrichtlinie: channels.whatsapp.groupPolicy steuert ob Gruppennachrichten akzeptiert werden (open|disabled|allowlist). allowlist nutzt channels.whatsapp.groupAllowFrom (Fallback: explizites channels.whatsapp.allowFrom). Standard ist allowlist (blockiert bis du Absender hinzufügst).
  • Sessions pro Gruppe: Session-Keys sehen aus wie agent:<agentId>:whatsapp:group:<jid>, sodass Befehle wie /verbose on oder /think high (als eigenständige Nachrichten gesendet) nur für diese Gruppe gelten; der persönliche DM-Status bleibt unberührt. Heartbeats werden für Gruppen-Threads übersprungen.
  • Kontext-Injection: Nur ausstehende Gruppennachrichten (Standard 50), die keinen Run ausgelöst haben, werden unter [Chat messages since your last reply - for context] vorangestellt, mit der auslösenden Zeile unter [Current message - respond to this]. Nachrichten die bereits in der Session sind werden nicht erneut injiziert.
  • Absender-Anzeige: Jeder Gruppen-Batch endet jetzt mit [from: Absendername (+E164)], damit der Agent weiß wer spricht.
  • Ephemeral/View-once: Wir entpacken diese bevor wir Text/Mentions extrahieren, sodass Pings darin trotzdem triggern.
  • Gruppen-System-Prompt: Beim ersten Turn einer Gruppen-Session (und wenn /activation den Modus ändert) injizieren wir einen kurzen Hinweis in den System-Prompt wie 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. Falls Metadaten nicht verfügbar sind, teilen wir dem Agent trotzdem mit dass es ein Gruppenchat ist.

Config-Beispiel (WhatsApp)

Füge einen groupChat-Block zu ~/.openclaw/openclaw.json hinzu, damit Display-Name-Pings funktionieren auch wenn WhatsApp das visuelle @ im Text entfernt:

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

Hinweise:

  • Die Regexes sind case-insensitive; sie decken Display-Name-Pings wie @openclaw und die rohe Nummer mit oder ohne +/Leerzeichen ab.
  • WhatsApp sendet weiterhin kanonische Mentions via mentionedJids wenn jemand den Kontakt antippt, daher wird der Nummern-Fallback selten gebraucht, ist aber ein nützliches Sicherheitsnetz.

Aktivierungsbefehl (nur Owner)

Nutze den Gruppenchat-Befehl:

  • /activation mention
  • /activation always

Nur die Owner-Nummer (aus channels.whatsapp.allowFrom, oder die eigene E.164 des Bots wenn nicht gesetzt) kann das ändern. Sende /status als eigenständige Nachricht in der Gruppe um den aktuellen Aktivierungsmodus zu sehen.

So verwendest du es

  1. Füge deinen WhatsApp-Account (den auf dem OpenClaw läuft) zur Gruppe hinzu.
  2. Schreibe @openclaw … (oder füge die Nummer ein). Nur Absender auf der Allowlist können triggern, es sei denn du setzt groupPolicy: "open".
  3. Der Agent-Prompt enthält den aktuellen Gruppenkontext plus den abschließenden [from: …]-Marker, damit er die richtige Person ansprechen kann.
  4. Session-Level-Direktiven (/verbose on, /think high, /new oder /reset, /compact) gelten nur für die Session dieser Gruppe; sende sie als eigenständige Nachrichten damit sie registriert werden. Deine persönliche DM-Session bleibt unabhängig.

Testen / Verifizieren

  • Manueller Smoke-Test:
    • Sende einen @openclaw-Ping in der Gruppe und bestätige dass eine Antwort kommt die den Absendernamen referenziert.
    • Sende einen zweiten Ping und verifiziere dass der History-Block enthalten ist und beim nächsten Turn geleert wird.
  • Prüfe die Gateway-Logs (starte mit --verbose) um inbound web message-Einträge zu sehen die from: <groupJid> und das [from: …]-Suffix zeigen.

Bekannte Hinweise

  • Heartbeats werden für Gruppen absichtlich übersprungen um störende Broadcasts zu vermeiden.
  • Echo-Unterdrückung nutzt den kombinierten Batch-String; wenn du identischen Text zweimal ohne Mentions sendest, bekommt nur der erste eine Antwort.
  • Session-Store-Einträge erscheinen als agent:<agentId>:whatsapp:group:<jid> im Session-Store (~/.openclaw/agents/<agentId>/sessions/sessions.json standardmäßig); ein fehlender Eintrag bedeutet nur dass die Gruppe noch keinen Run ausgelöst hat.
  • Typing-Indikatoren in Gruppen folgen agents.defaults.typingMode (Standard: message wenn nicht erwähnt).