Skip to content

Bug: WhatsApp messageReceived hook opt-in docs/schema/runtime mismatch #86390

@skocher

Description

@skocher

Summary

The WhatsApp message_received hook opt-in is inconsistent across docs, config schema, plugin manifest, and runtime.

In the current packages I checked, the documented config shape is rejected by config validation, while the schema-valid plugin config shape is not read by the WhatsApp runtime. The result is that operators cannot enable WhatsApp message_received hooks using a single supported, validated configuration path.

This is adjacent to, but narrower than, #78963. That issue asks for a first-class listen-only/hooks-only mode. This issue is specifically about the existing pluginHooks.messageReceived opt-in contract being internally inconsistent.

What I checked

Installed runtime:

  • openclaw --version: OpenClaw 2026.5.20 (e510042)
  • installed WhatsApp plugin: @openclaw/whatsapp@2026.5.20

Latest stable package checked without installing/updating:

  • npm pack openclaw@2026.5.22
  • npm pack @openclaw/whatsapp@2026.5.22

The mismatch appears unchanged in the 2026.5.22 tarballs.

Evidence

1. Official docs document channel/account config

docs/channels/whatsapp.md says to enable hooks under channels.whatsapp.pluginHooks.messageReceived:

{
  channels: {
    whatsapp: {
      pluginHooks: {
        messageReceived: true,
      },
    },
  },
}

It also documents account-scoped opt-in under channels.whatsapp.accounts.<accountId>.pluginHooks.messageReceived.

2. The WhatsApp plugin manifest exposes plugin config instead

@openclaw/whatsapp/openclaw.plugin.json exposes pluginHooks.messageReceived in the plugin configSchema:

{
  "configSchema": {
    "properties": {
      "pluginHooks": {
        "properties": {
          "messageReceived": { "type": "boolean" }
        }
      }
    }
  }
}

That corresponds to config like:

{
  "plugins": {
    "entries": {
      "whatsapp": {
        "config": {
          "pluginHooks": { "messageReceived": true }
        }
      }
    }
  }
}

3. Config validation rejects the documented channel-level key

Adding the docs shape under channels.whatsapp.pluginHooks fails validation on my install:

channels.whatsapp: invalid config: must NOT have additional properties

The schema-valid plugin config shape above is accepted.

4. Runtime reads only channel/account config

In @openclaw/whatsapp@2026.5.20 and the checked @openclaw/whatsapp@2026.5.22 tarball, the runtime still reads only params.cfg.channels?.whatsapp and account config:

function shouldEmitWhatsAppMessageReceivedHooks(params) {
  const channelConfig = params.cfg.channels?.whatsapp;
  return readWhatsAppMessageReceivedHookOptIn(
    params.accountId && channelConfig?.accounts ? channelConfig.accounts[params.accountId] : void 0
  ) ?? readWhatsAppMessageReceivedHookOptIn(channelConfig) ?? false;
}

It does not read params.cfg.plugins?.entries?.whatsapp?.config, which is the schema-valid location provided by the plugin manifest.

Expected behavior

There should be one documented, schema-valid, runtime-honored way to enable WhatsApp message_received hooks.

Either:

  1. make channels.whatsapp.pluginHooks.messageReceived and account-level pluginHooks valid in the channel schema, matching docs and runtime; or
  2. update runtime and docs to use plugins.entries.whatsapp.config.pluginHooks.messageReceived; or
  3. support both for compatibility, with docs clearly stating precedence.

Actual behavior

  • Docs point to channels.whatsapp.pluginHooks.messageReceived.
  • Config schema rejects that location.
  • Plugin manifest accepts plugins.entries.whatsapp.config.pluginHooks.messageReceived.
  • Runtime ignores that schema-valid plugin config location.

Impact

Operators cannot enable WhatsApp message_received hooks reliably without either invalid config or local runtime patching. This blocks hook-based archival/ETL plugins and makes it hard to build safe WhatsApp ingestion flows without patching installed package internals.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    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