Skip to content

Hooks: Add support for message:received event to enable channel-level automation #30553

@rhclaw

Description

@rhclaw

Problem

The current hook system only supports lifecycle events (/new, /reset, /stop, agent:bootstrap). There is no way to hook into incoming messages before they are routed (or dropped) by the gateway.

Use Case

When groupPolicy: allowlist is configured for Telegram, the gateway silently drops messages from unknown groups. There is no way to log the chat_id and group name of these unknown groups — making it hard to discover and add new groups to the allowlist.

A message:received hook event would fire before routing/policy enforcement, allowing a hook to:

  • Log the chat_id and group name to a file
  • Notify the admin of a new group request
  • Build an approval workflow for new groups

Proposed Solution

Add a message:received hook event (and optionally message:blocked / message:routed) that fires when the gateway receives an inbound message from any channel (Telegram, WhatsApp, etc.), before policy filtering.

Example HOOK.md metadata:

metadata: { "openclaw": { "events": ["message:received"] } }

Example handler payload:

{
  type: "message",
  action: "received",
  context: {
    channelId: "telegram",        // "telegram" | "whatsapp" | ...
    conversationId: "-5125811834", // chat_id (negative = group)
    metadata: {
      title: "Claus, Pip & Co",   // group name
      type: "group"               // "group" | "supergroup" | "private"
    }
  }
}

Workarounds Today

  • Temporarily set groupPolicy: open to see all groups (security tradeoff)
  • Use a second bot token as a shadow logger (brittle)
  • Manually retrieve the chat_id from web.telegram.org URL

All workarounds require manual intervention. A message:received hook would make this fully automatic.

Additional Context

  • Related config: channels.telegram.groupPolicy, channels.telegram.groups
  • Requested by a user running Telegram + WhatsApp channels with allowlist policies
  • The existing telegram-group-logger hook skeleton was built in anticipation of this feature but cannot function without gateway-level event support

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    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