Skip to content

Feature request: per-account and per-peer sendPolicy matching for shadow mode DM handling #66938

@primecoder-legonhill

Description

@primecoder-legonhill

Use Case

Multi-account WhatsApp setups need the ability to receive and process DMs on one account without responding (shadow mode), while allowing normal DM responses on a different account.

Concrete scenario:

  • Primary account receives DMs from contacts. The agent should read, learn from, and process these messages — but never send a reply back to the sender.
  • Secondary account receives DMs from the same or different contacts. The agent should respond normally.
  • Currently, the only architectural enforcement is sendPolicy, but it matches on channel and chatType — not on accountId or peer. Denying chatType: "direct" on WhatsApp kills DM responses on both accounts.

Why prompt-level enforcement is insufficient:

SOUL.md instructions like "output NO_REPLY for DMs on the primary account" are probabilistic. In observed production behavior, the model ignored an explicit NO_REPLY rule and responded directly to a DM on the primary account despite clear instructions not to. Prompt-level rules are guidance, not gates.

Current State

  • session.sendPolicy.rules[].match supports: channel, chatType, keyPrefix, rawKeyPrefix
  • WhatsApp session keys do not encode accountId (e.g. agent:main:whatsapp:direct:+1234567890 is the same structure for both primary and secondary accounts), so rawKeyPrefix cannot distinguish accounts
  • accountId is stored as session metadata but not exposed to sendPolicy matching
  • heartbeat.directPolicy: "block" exists but only applies to heartbeat-triggered turns, not message-triggered turns
  • No per-binding reply policy or delivery redirect mechanism exists

Proposed Solutions (any of these would work)

Option A: Add accountId to sendPolicy match (preferred)

{
  "session": {
    "sendPolicy": {
      "default": "allow",
      "rules": [
        {
          "action": "deny",
          "match": {
            "channel": "whatsapp",
            "chatType": "direct",
            "accountId": "default"
          }
        }
      ]
    }
  }
}

This would suppress outbound delivery for DMs on the default/primary WhatsApp account while allowing DMs on the secondary account. The agent still processes the inbound message (per the 2026.4.12 sendPolicy fix in #65461).

Option B: Add peer to sendPolicy match

{
  "action": "deny",
  "match": {
    "channel": "whatsapp",
    "chatType": "direct",
    "peer": "+1234567890"
  }
}

Per-number send suppression. More granular but more verbose for multi-contact scenarios.

Option C: Per-binding sendPolicy or replyPolicy

{
  "bindings": [
    {
      "type": "route",
      "agentId": "main",
      "match": { "channel": "whatsapp", "accountId": "default", "peer": { "kind": "direct" } },
      "sendPolicy": "deny"
    }
  ]
}

Binding-level delivery control. Cleanest for per-route shadow mode.

Option D: Delivery redirect

Route the agent's reply to a different destination (e.g. a specific group or webchat) instead of back to the original sender. Useful for "draft and forward for approval" workflows.

Environment

  • OpenClaw 2026.4.14
  • WhatsApp dual-account setup (default + secondary)
  • 6 agents with different channel bindings

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions