mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:31:00 +00:00
WhatsApp: add group and direct system prompt support (#59553)
Merged via squash.
Prepared head SHA: 63e2b50e01
Co-authored-by: Bluetegu <1525690+Bluetegu@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
This commit is contained in:
@@ -408,6 +408,10 @@ The agent system prompt includes a group intro on the first turn of a new group
|
||||
- List chats: `imsg chats --limit 20`.
|
||||
- Group replies always go back to the same `chat_id`.
|
||||
|
||||
## WhatsApp system prompts
|
||||
|
||||
See [WhatsApp](/channels/whatsapp#system-prompts) for the canonical WhatsApp system prompt rules, including group and direct prompt resolution, wildcard behavior, and account override semantics.
|
||||
|
||||
## WhatsApp specifics
|
||||
|
||||
See [Group messages](/channels/group-messages) for WhatsApp-only behavior (history injection, mention handling details).
|
||||
|
||||
@@ -465,6 +465,75 @@ Behavior notes:
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## System prompts
|
||||
|
||||
WhatsApp supports Telegram-style system prompts for groups and direct chats via the `groups` and `direct` maps.
|
||||
|
||||
Resolution hierarchy for group messages:
|
||||
|
||||
The effective `groups` map is determined first: if the account defines its own `groups`, it fully replaces the root `groups` map (no deep merge). Prompt lookup then runs on the resulting single map:
|
||||
|
||||
1. **Group-specific system prompt** (`groups["<groupId>"].systemPrompt`): used if the specific group entry defines a `systemPrompt`.
|
||||
2. **Group wildcard system prompt** (`groups["*"].systemPrompt`): used when the specific group entry is absent or defines no `systemPrompt`.
|
||||
|
||||
Resolution hierarchy for direct messages:
|
||||
|
||||
The effective `direct` map is determined first: if the account defines its own `direct`, it fully replaces the root `direct` map (no deep merge). Prompt lookup then runs on the resulting single map:
|
||||
|
||||
1. **Direct-specific system prompt** (`direct["<peerId>"].systemPrompt`): used if the specific peer entry defines a `systemPrompt`.
|
||||
2. **Direct wildcard system prompt** (`direct["*"].systemPrompt`): used when the specific peer entry is absent or defines no `systemPrompt`.
|
||||
|
||||
Note: `dms` remains the lightweight per-DM history override bucket (`dms.<id>.historyLimit`); prompt overrides live under `direct`.
|
||||
|
||||
**Difference from Telegram multi-account behavior:** In Telegram, root `groups` is intentionally suppressed for all accounts in a multi-account setup — even accounts that define no `groups` of their own — to prevent a bot from receiving group messages for groups it does not belong to. WhatsApp does not apply this guard: root `groups` and root `direct` are always inherited by accounts that define no account-level override, regardless of how many accounts are configured. In a multi-account WhatsApp setup, if you want per-account group or direct prompts, define the full map under each account explicitly rather than relying on root-level defaults.
|
||||
|
||||
Important behavior:
|
||||
|
||||
- `channels.whatsapp.groups` is both a per-group config map and the chat-level group allowlist. At either the root or account scope, `groups["*"]` means "all groups are admitted" for that scope.
|
||||
- Only add a wildcard group `systemPrompt` when you already want that scope to admit all groups. If you still want only a fixed set of group IDs to be eligible, do not use `groups["*"]` for the prompt default. Instead, repeat the prompt on each explicitly allowlisted group entry.
|
||||
- Group admission and sender authorization are separate checks. `groups["*"]` widens the set of groups that can reach group handling, but it does not by itself authorize every sender in those groups. Sender access is still controlled separately by `channels.whatsapp.groupPolicy` and `channels.whatsapp.groupAllowFrom`.
|
||||
- `channels.whatsapp.direct` does not have the same side effect for DMs. `direct["*"]` only provides a default direct-chat config after a DM is already admitted by `dmPolicy` plus `allowFrom` or pairing-store rules.
|
||||
|
||||
Example:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
// Use only if all groups should be admitted at the root scope.
|
||||
// Applies to all accounts that do not define their own groups map.
|
||||
"*": { systemPrompt: "Default prompt for all groups." },
|
||||
},
|
||||
direct: {
|
||||
// Applies to all accounts that do not define their own direct map.
|
||||
"*": { systemPrompt: "Default prompt for all direct chats." },
|
||||
},
|
||||
accounts: {
|
||||
work: {
|
||||
groups: {
|
||||
// This account defines its own groups, so root groups are fully
|
||||
// replaced. To keep a wildcard, define "*" explicitly here too.
|
||||
"120363406415684625@g.us": {
|
||||
requireMention: false,
|
||||
systemPrompt: "Focus on project management.",
|
||||
},
|
||||
// Use only if all groups should be admitted in this account.
|
||||
"*": { systemPrompt: "Default prompt for work groups." },
|
||||
},
|
||||
direct: {
|
||||
// This account defines its own direct map, so root direct entries are
|
||||
// fully replaced. To keep a wildcard, define "*" explicitly here too.
|
||||
"+15551234567": { systemPrompt: "Prompt for a specific work direct chat." },
|
||||
"*": { systemPrompt: "Default prompt for work direct chats." },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration reference pointers
|
||||
|
||||
Primary reference:
|
||||
@@ -478,6 +547,7 @@ High-signal WhatsApp fields:
|
||||
- multi-account: `accounts.<id>.enabled`, `accounts.<id>.authDir`, account-level overrides
|
||||
- operations: `configWrites`, `debounceMs`, `web.enabled`, `web.heartbeatSeconds`, `web.reconnect.*`
|
||||
- session behavior: `session.dmScope`, `historyLimit`, `dmHistoryLimit`, `dms.<id>.historyLimit`
|
||||
- prompts: `groups.<id>.systemPrompt`, `groups["*"].systemPrompt`, `direct.<id>.systemPrompt`, `direct["*"].systemPrompt`
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
Reference in New Issue
Block a user