Skip to content

Feature: Webchat / Control UI inline button support (buttons parameter, callback RPC, capabilities config) #46656

Description

@sys-fairy-eve

Feature Request

Summary

The message tool supports a buttons parameter for sending inline keyboard buttons, but this only works on Telegram today. Webchat (Control UI) clients silently drop the buttons payload — no rendering, no callback mechanism, and no capabilities config path exists for webchat.

This is a feature request to bring full inline button support to the webchat/Control UI channel, matching the existing Telegram implementation.


Problem

When an agent sends a message via the message tool with buttons, the gateway:

  1. Telegram — renders inline keyboard, handles callback_query, routes callback data to agent
  2. Webchat/Control UI — silently drops the buttons payload; no buttons rendered

The system prompt already generates the hint:

"Inline buttons not enabled for webchat. If you need them, ask to set webchat.capabilities.inlineButtons"

But webchat.capabilities.inlineButtons does not exist in the config schema — the hint is aspirational, not functional.

Additionally:

  • The chat.send WS method does not accept or relay a buttons field
  • No chat.callback WS RPC method exists for webchat clients to report button clicks
  • The built-in Control UI has no button rendering code for chat messages

Use Case

We run a multi-agent household with a content curation agent (Radar) that sends signal digests with action buttons (👍 Like / 👎 Skip / 📖 Read Later / 🔗 Open). This previously worked via Telegram inline keyboards. After migrating the primary interface to webchat (ClawDash), we lost all button interactivity.

Inline buttons are also useful for:


Proposed Solution

1. Capabilities Config

Add webchat.capabilities.inlineButtons to the config schema, matching the Telegram pattern:

{
  webchat: {
    capabilities: {
      inlineButtons: "all",  // "off" | "dm" | "group" | "all" | "allowlist"
    },
  },
}

2. WS Chat Event — buttons Field

When inlineButtons is enabled and a message includes buttons, include them in the chat WS event payload:

{
  "type": "event",
  "event": "chat",
  "payload": {
    "state": "final",
    "text": "Here are today's top signals:",
    "buttons": [
      [
        { "text": "👍 Like", "callback_data": "signal:like:abc123" },
        { "text": "👎 Skip", "callback_data": "signal:skip:abc123" }
      ],
      [
        { "text": "📖 Read Later", "callback_data": "signal:save:abc123", "style": "primary" }
      ]
    ]
  }
}

The buttons field should use the same schema as the Telegram message send --buttons parameter:

  • Array of rows, each row is an array of button objects
  • Each button: { text: string, callback_data: string, style?: "primary" | "success" | "danger" }
  • callback_data max length: 64 characters
  • Buttons should only appear on state: "final" events (not during streaming)

3. chat.callback WS RPC Method

Add a new WS RPC method for webchat clients to report button clicks:

// Client → Gateway
{
  "type": "req",
  "id": "42",
  "method": "chat.callback",
  "params": {
    "sessionKey": "agent:main:main",
    "callbackData": "signal:like:abc123",
    "messageId": "msg-1234"       // optional: which message the button was on
  }
}

// Gateway → Client (response)
{
  "type": "res",
  "id": "42",
  "ok": true,
  "payload": {
    "text": "Saved to reading list!",  // optional toast/alert text
    "action": "none"                    // "none" | "close" | "disable"
  }
}

Callback routing options (one or both):

  • Route to agent as text (like Telegram): inject callback_data: <value> as a user message into the session
  • Route to webhook (zero token spend): POST to a configurable webchat.callbackWebhookUrl, enabling n8n/automation workflows without triggering an agent turn

Webhook payload example:

{
  "event": "callback",
  "sessionKey": "agent:main:main",
  "callbackData": "signal:like:abc123",
  "messageId": "msg-1234",
  "timestamp": "2026-03-15T00:30:00.000Z"
}

4. Control UI Rendering

The built-in Control UI should render buttons below the message text:

  • Horizontal rows of buttons matching the row structure
  • Visual styles for primary, success, danger (and a default neutral style)
  • Click sends chat.callback RPC
  • Optional: disable buttons after first click, or show clicked state

Current Workarounds

Without gateway support, custom webchat clients must:

  1. Embed button metadata in the message text (e.g., HTML comments or a custom syntax)
  2. Parse and strip button data client-side
  3. POST callbacks directly to an external webhook, bypassing the gateway entirely

This works but is fragile, non-standard, and invisible to the built-in Control UI.


Related Issues


Environment

  • OpenClaw version: 2026.3.8 (3caab92)
  • Channel: webchat (custom ClawDash client + built-in Control UI)
  • OS: Ubuntu Linux (headless VPS)

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:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions