WhatsApp (Web-Kanal)

Status: Produktionsreif via WhatsApp Web (Baileys). Das Gateway verwaltet verknüpfte Session(s).

Schnelleinrichtung

Schritt 1: WhatsApp-Zugriffsrichtlinie konfigurieren

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

Schritt 2: WhatsApp verknüpfen (QR)

openclaw channels login --channel whatsapp
Für ein bestimmtes Konto:
openclaw channels login --channel whatsapp --account work

Schritt 3: Gateway starten

openclaw gateway

Schritt 4: Erste Pairing-Anfrage genehmigen (bei Pairing-Modus)

openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
Pairing-Anfragen laufen nach 1 Stunde ab. Ausstehende Anfragen sind auf 3 pro Kanal begrenzt.

Hinweis: OpenClaw empfiehlt, WhatsApp wenn möglich mit einer separaten Nummer zu betreiben. (Die Kanal-Metadaten und der Onboarding-Ablauf sind für dieses Setup optimiert, aber die Nutzung mit persönlicher Nummer wird ebenfalls unterstützt.)

Bereitstellungsmuster

Separate Nummer (empfohlen)
Dies ist der sauberste Betriebsmodus:

- separate WhatsApp-Identität für OpenClaw
- klarere DM-Allowlists und Routing-Grenzen
- geringere Wahrscheinlichkeit von Self-Chat-Verwirrung

Minimales Richtlinienmuster:

```json5
{
  channels: {
    whatsapp: {
      dmPolicy: "allowlist",
      allowFrom: ["+15551234567"],
    },
  },
}
```
Persönliche Nummer als Fallback
Das Onboarding unterstützt den Modus mit persönlicher Nummer und schreibt eine Self-Chat-freundliche Basiskonfiguration:

- `dmPolicy: "allowlist"`
- `allowFrom` enthält deine persönliche Nummer
- `selfChatMode: true`

Zur Laufzeit basieren Self-Chat-Schutzmaßnahmen auf der verknüpften eigenen Nummer und `allowFrom`.
Nur WhatsApp Web-Kanalumfang
Der Messaging-Plattform-Kanal basiert in der aktuellen OpenClaw-Kanalarchitektur auf WhatsApp Web (`Baileys`).

Es gibt keinen separaten Twilio-WhatsApp-Messaging-Kanal in der integrierten Chat-Kanal-Registry.

Laufzeitmodell

  • Das Gateway verwaltet den WhatsApp-Socket und die Reconnect-Schleife.
  • Ausgehende Nachrichten erfordern einen aktiven WhatsApp-Listener für das Zielkonto.
  • Status- und Broadcast-Chats werden ignoriert (@status, @broadcast).
  • Direkte Chats verwenden DM-Session-Regeln (session.dmScope; Standard main fasst DMs zur Agent-Hauptsession zusammen).
  • Gruppensessions sind isoliert (agent:<agentId>:whatsapp:group:<jid>).

Zugriffssteuerung und Aktivierung

DM-Richtlinie

`channels.whatsapp.dmPolicy` steuert den Direkt-Chat-Zugriff:

- `pairing` (Standard)
- `allowlist`
- `open` (erfordert, dass `allowFrom` `"*"` enthält)
- `disabled`

`allowFrom` akzeptiert Nummern im E.164-Format (intern normalisiert).

Multi-Account-Überschreibung: `channels.whatsapp.accounts.<id>.dmPolicy` (und `allowFrom`) haben für das jeweilige Konto Vorrang vor den Standardeinstellungen auf Kanalebene.

Laufzeit-Verhalten im Detail:

- Pairings werden im Kanal-Allow-Store gespeichert und mit dem konfigurierten `allowFrom` zusammengeführt
- wenn keine Allowlist konfiguriert ist, wird die verknüpfte eigene Nummer standardmäßig erlaubt
- ausgehende `fromMe`-DMs werden nie automatisch gepairt

Gruppenrichtlinie + Allowlists

Gruppenzugriff hat zwei Ebenen:

1. **Gruppenmitgliedschafts-Allowlist** (`channels.whatsapp.groups`)
   - wenn `groups` nicht angegeben ist, sind alle Gruppen berechtigt
   - wenn `groups` angegeben ist, fungiert es als Gruppen-Allowlist (`"*"` erlaubt)

2. **Gruppen-Absenderrichtlinie** (`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
   - `open`: Absender-Allowlist wird umgangen
   - `allowlist`: Absender muss `groupAllowFrom` (oder `*`) entsprechen
   - `disabled`: alle eingehenden Gruppennachrichten blockieren

Absender-Allowlist-Fallback:

- wenn `groupAllowFrom` nicht gesetzt ist, fällt die Laufzeit auf `allowFrom` zurück, wenn verfügbar
- Absender-Allowlists werden vor der Mention-/Reply-Aktivierung ausgewertet

Hinweis: Wenn kein `channels.whatsapp`-Block existiert, ist der Laufzeit-Gruppen-Richtlinien-Fallback `allowlist` (mit einer Warn-Logmeldung), auch wenn `channels.defaults.groupPolicy` gesetzt ist.

Mentions + /activation

Gruppenantworten erfordern standardmäßig eine Erwähnung.

Erwähnungserkennung umfasst:

- explizite WhatsApp-Erwähnungen der Bot-Identität
- konfigurierte Erwähnungsmuster (`agents.list[].groupChat.mentionPatterns`, Fallback `messages.groupChat.mentionPatterns`)
- implizite Reply-to-Bot-Erkennung (Antwort-Absender entspricht der Bot-Identität)

Sicherheitshinweis:

- Zitat/Antwort erfüllt nur das Mention-Gating; es gewährt **keine** Absenderautorisierung
- bei `groupPolicy: "allowlist"` werden nicht gelistete Absender auch dann blockiert, wenn sie auf die Nachricht eines gelisteten Benutzers antworten

Aktivierungsbefehl auf Session-Ebene:

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

`activation` aktualisiert den Session-Status (nicht die globale Konfiguration). Es ist auf den Owner beschränkt.

Persönliche Nummer und Self-Chat-Verhalten

Wenn die verknüpfte eigene Nummer auch in allowFrom enthalten ist, werden WhatsApp-Self-Chat-Schutzmaßnahmen aktiviert:

  • Lesebestätigungen für Self-Chat-Turns überspringen
  • Mention-JID-Auto-Trigger-Verhalten ignorieren, das dich sonst selbst anpingen würde
  • wenn messages.responsePrefix nicht gesetzt ist, verwenden Self-Chat-Antworten standardmäßig [{identity.name}] oder [openclaw]

Nachrichtennormalisierung und Kontext

Eingehende Hülle + Antwortkontext
Eingehende WhatsApp-Nachrichten werden in die gemeinsame eingehende Hülle verpackt.

Wenn eine zitierte Antwort existiert, wird der Kontext in dieser Form angehängt:

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

Antwort-Metadatenfelder werden ebenfalls befüllt, wenn verfügbar (`ReplyToId`, `ReplyToBody`, `ReplyToSender`, Absender-JID/E.164).
Medien-Platzhalter und Standort-/Kontaktextraktion
Reine Medien-Eingangsnachrichten werden mit Platzhaltern normalisiert wie:

- `<media:image>`
- `<media:video>`
- `<media:audio>`
- `<media:document>`
- `<media:sticker>`

Standort- und Kontakt-Payloads werden vor dem Routing in textuellen Kontext normalisiert.
Ausstehende Gruppenhistorie-Injektion
Für Gruppen können unverarbeitete Nachrichten gepuffert und als Kontext injiziert werden, wenn der Bot schließlich ausgelöst wird.

- Standardlimit: `50`
- Konfiguration: `channels.whatsapp.historyLimit`
- Fallback: `messages.groupChat.historyLimit`
- `0` deaktiviert

Injektionsmarkierungen:

- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
Lesebestätigungen
Lesebestätigungen sind standardmäßig für akzeptierte eingehende WhatsApp-Nachrichten aktiviert.

Global deaktivieren:

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

Pro-Konto-Überschreibung:

```json5
{
  channels: {
    whatsapp: {
      accounts: {
        work: {
          sendReadReceipts: false,
        },
      },
    },
  },
}
```

Self-Chat-Turns überspringen Lesebestätigungen, auch wenn sie global aktiviert sind.

Zustellung, Chunking und Medien

Text-Chunking
- Standard-Chunk-Limit: `channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.chunkMode = "length" | "newline"`
- `newline`-Modus bevorzugt Absatzgrenzen (Leerzeilen), fällt dann auf längensicheres Chunking zurück
Ausgehendes Medienverhalten
- unterstützt Bild-, Video-, Audio- (PTT-Sprachnachricht) und Dokument-Payloads
- `audio/ogg` wird zu `audio/ogg; codecs=opus` umgeschrieben für Sprachnachricht-Kompatibilität
- animierte GIF-Wiedergabe wird über `gifPlayback: true` bei Video-Sends unterstützt
- Bildunterschriften werden beim Senden von Multi-Medien-Antwort-Payloads auf das erste Medienelement angewendet
- Medienquellen können HTTP(S), `file://` oder lokale Pfade sein
Medien-Größenlimits und Fallback-Verhalten
- eingehende Medienspeicher-Obergrenze: `channels.whatsapp.mediaMaxMb` (Standard `50`)
- ausgehende Mediensende-Obergrenze: `channels.whatsapp.mediaMaxMb` (Standard `50`)
- Pro-Konto-Überschreibungen verwenden `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
- Bilder werden automatisch optimiert (Größenanpassung/Qualitätsdurchlauf), um Limits einzuhalten
- bei Fehler beim Mediensenden sendet der Fallback des ersten Elements eine Textwarnung, anstatt die Antwort stillschweigend zu verwerfen

Bestätigungsreaktionen

WhatsApp unterstützt sofortige Bestätigungsreaktionen beim eingehenden Empfang über channels.whatsapp.ackReaction.

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

Verhaltenshinweise:

  • wird sofort nach Akzeptanz des Eingangs gesendet (vor der Antwort)
  • Fehler werden protokolliert, blockieren aber nicht die normale Antwortzustellung
  • Gruppenmodus mentions reagiert bei durch Erwähnung ausgelösten Turns; Gruppenaktivierung always umgeht diese Prüfung
  • WhatsApp verwendet channels.whatsapp.ackReaction (das veraltete messages.ackReaction wird hier nicht verwendet)

Multi-Account und Zugangsdaten

Kontoauswahl und Standards
- Konto-IDs stammen aus `channels.whatsapp.accounts`
- Standard-Kontoauswahl: `default` falls vorhanden, sonst die erste konfigurierte Konto-ID (sortiert)
- Konto-IDs werden intern für die Suche normalisiert
Zugangsdatenpfade und Legacy-Kompatibilität
- aktueller Auth-Pfad: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- Backup-Datei: `creds.json.bak`
- Legacy-Standard-Auth in `~/.openclaw/credentials/` wird für Standard-Konto-Abläufe weiterhin erkannt/migriert
Abmeldeverhalten
`openclaw channels logout --channel whatsapp [--account <id>]` löscht den WhatsApp-Auth-Status für dieses Konto.

In Legacy-Auth-Verzeichnissen wird `oauth.json` beibehalten, während Baileys-Auth-Dateien entfernt werden.

Tools, Aktionen und Konfigurationsschreibvorgänge

  • Agent-Tool-Unterstützung umfasst die WhatsApp-Reaktionsaktion (react).
  • Aktions-Gates:
    • channels.whatsapp.actions.reactions
    • channels.whatsapp.actions.polls
  • Kanal-initiierte Konfigurationsschreibvorgänge sind standardmäßig aktiviert (deaktivieren mit channels.whatsapp.configWrites=false).

Fehlerbehebung

Nicht verknüpft (QR erforderlich)
Symptom: Kanalstatus meldet „nicht verknüpft".

Lösung:

```bash
openclaw channels login --channel whatsapp
openclaw channels status
```
Verknüpft, aber getrennt / Reconnect-Schleife
Symptom: Verknüpftes Konto mit wiederholten Verbindungsabbrüchen oder Reconnect-Versuchen.

Lösung:

```bash
openclaw doctor
openclaw logs --follow
```

Bei Bedarf mit `channels login` erneut verknüpfen.
Kein aktiver Listener beim Senden
Ausgehende Nachrichten schlagen sofort fehl, wenn kein aktiver Gateway-Listener für das Zielkonto existiert.

Stelle sicher, dass das Gateway läuft und das Konto verknüpft ist.
Gruppennachrichten unerwartet ignoriert
Prüfe in dieser Reihenfolge:

- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- `groups`-Allowlist-Einträge
- Mention-Gating (`requireMention` + Erwähnungsmuster)
- doppelte Schlüssel in `openclaw.json` (JSON5): spätere Einträge überschreiben frühere, daher nur eine einzelne `groupPolicy` pro Bereich verwenden
Bun-Laufzeitwarnung
Die WhatsApp-Gateway-Laufzeit sollte Node verwenden. Bun ist als inkompatibel für stabilen WhatsApp/Telegram-Gateway-Betrieb gekennzeichnet.

Konfigurationsreferenz

Primäre Referenz:

Wichtige WhatsApp-Felder:

  • Zugriff: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups
  • Zustellung: textChunkLimit, chunkMode, mediaMaxMb, sendReadReceipts, ackReaction
  • Multi-Account: accounts.<id>.enabled, accounts.<id>.authDir, kontoebene Überschreibungen
  • Betrieb: configWrites, debounceMs, web.enabled, web.heartbeatSeconds, web.reconnect.*
  • Session-Verhalten: session.dmScope, historyLimit, dmHistoryLimit, dms.<id>.historyLimit

Verwandte Dokumentation