openclaw - ✅(Solved) Fix message() tool requires 'buttons' property for plain action=send — breaks all non-button sends [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#54385Fetched 2026-04-08 01:28:16
View on GitHub
Comments
0
Participants
1
Timeline
9
Reactions
0
Author
Participants
Timeline (top)
referenced ×5cross-referenced ×2closed ×1locked ×1

The message() tool fails with a validation error requiring a buttons property even when performing a simple action=send with just channel, target, and message. This blocks all programmatic message sending from agents and cron sessions that don't use inline buttons.

Error Message

The message() tool fails with a validation error requiring a buttons property even when performing a simple action=send with just channel, target, and message. This blocks all programmatic message sending from agents and cron sessions that don't use inline buttons.

Root Cause

The message() tool fails with a validation error requiring a buttons property even when performing a simple action=send with just channel, target, and message. This blocks all programmatic message sending from agents and cron sessions that don't use inline buttons.

Fix Action

Workaround

Use exec with curl to send messages directly via the channel API (e.g., Telegram Bot API):

BOT_TOKEN=$(python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['channels']['telegram']['botToken'])")
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d "{\"chat_id\":\"CHAT_ID\",\"text\":\"message here\"}"

This works but bypasses OpenClaw's channel routing, delivery tracking, and multi-channel abstraction — defeating the purpose of the message() tool.

PR fix notes

PR #54418: fix: make buttons schema optional in message tool

Description (problem / solution / changelog)

Summary

createMessageToolButtonsSchema() returns a Type.Array(...) schema without Type.Optional() wrapping. When the Telegram channel plugin contributes this as a property to the message tool's Type.Object schema, TypeBox treats it as required — adding buttons to the required array. This causes all plain action=send calls (without buttons) to fail with:

Validation failed for tool "message":
 - buttons: must have required property 'buttons'

Root Cause

In src/plugin-sdk/channel-actions.ts, createMessageToolButtonsSchema() returns:

Type.Array(Type.Array(Type.Object({...})))

When this is spread into Type.Object({ buttons: ... }), TypeBox infers non-Optional properties as required.

Fix

Wrap the return value in Type.Optional():

Type.Optional(Type.Array(Type.Array(Type.Object({...}))))

This matches the pattern already used by:

  • createMessageToolCardSchema() (same file — already returns Type.Optional())
  • Mattermost's channel plugin (wraps createMessageToolButtonsSchema() in its own Type.Optional())

Changes

  • src/plugin-sdk/channel-actions.ts — Wrap Type.Array in Type.Optional inside createMessageToolButtonsSchema()
  • src/agents/tools/message-tool.test.ts — Add test verifying buttons is not in the required array

Testing

  • message-tool.test.ts: 25/25 pass ✅
  • channels/plugins/contracts/: 223/223 pass ✅
  • plugin-sdk/: 249/249 pass ✅

Fixes #54385

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/.generated/plugin-sdk-api-baseline.json (modified, +1/-1)
  • docs/.generated/plugin-sdk-api-baseline.jsonl (modified, +1/-1)
  • src/agents/tools/message-tool.test.ts (modified, +18/-0)
  • src/plugin-sdk/channel-actions.ts (modified, +11/-9)

PR #54453: fix: make message tool buttons schema property optional

Description (problem / solution / changelog)

Summary

  • Problem: createMessageToolButtonsSchema() returns Type.Array(...) without Type.Optional(), so when a channel plugin (e.g. Telegram) contributes buttons to the message tool schema, Typebox marks it as a required property. This causes message() tool calls with action=send to fail validation if buttons is not provided — blocking all plain text message sends from agents and cron sessions.
  • Root cause: Inconsistency in src/plugin-sdk/channel-actions.tscreateMessageToolCardSchema() correctly wraps its return in Type.Optional(), but createMessageToolButtonsSchema() does not.
  • What changed: Wrapped the return value of createMessageToolButtonsSchema() in Type.Optional(), consistent with createMessageToolCardSchema().
  • What did NOT change: Button functionality when buttons are provided. The inner array schema (text, callback_data, style) is unchanged.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Tools / agent runtime

Test plan

  • message() tool with action=send + plain text (no buttons) should pass validation
  • message() tool with action=send + buttons should still work as before

Closes #54385

Changed files

  • docs/.generated/plugin-sdk-api-baseline.json (modified, +1/-1)
  • docs/.generated/plugin-sdk-api-baseline.jsonl (modified, +1/-1)
  • src/plugin-sdk/channel-actions.ts (modified, +11/-9)

Code Example

{
     "action": "send",
     "channel": "telegram",
     "target": "8423776809",
     "message": "Hello from the agent"
   }

---

Validation failed for tool "message":
     - buttons: must have required property 'buttons'

---

- "required": ["action", "buttons"]
+ "required": ["action"]

---

BOT_TOKEN=$(python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['channels']['telegram']['botToken'])")
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d "{\"chat_id\":\"CHAT_ID\",\"text\":\"message here\"}"
RAW_BUFFERClick to expand / collapse

Bug Report

Summary

The message() tool fails with a validation error requiring a buttons property even when performing a simple action=send with just channel, target, and message. This blocks all programmatic message sending from agents and cron sessions that don't use inline buttons.

Environment

  • OpenClaw: 2026.3.23-2 (7ffe7e4)
  • OS: macOS 15.3 (arm64)
  • Channel: Telegram (also likely affects other channels)

Steps to Reproduce

  1. From any agent session, call the message tool:
    {
      "action": "send",
      "channel": "telegram",
      "target": "8423776809",
      "message": "Hello from the agent"
    }
  2. Tool fails with:
    Validation failed for tool "message":
      - buttons: must have required property 'buttons'

Expected Behavior

action=send with channel, target, and message should send a plain text message. The buttons property should be optional — it's only needed when sending inline button components.

Actual Behavior

The tool schema marks buttons as a required property in the JSON Schema definition, causing validation failure before the tool even executes. This affects:

  • Agent sessions: Any agent trying to send a proactive Telegram/Discord/etc message
  • Cron sessions: Isolated cron jobs that need to deliver reports via message() tool (we had to work around this by using raw curl to the Telegram Bot API)
  • Heartbeat sessions: Any heartbeat that needs to alert on failures

Proposed Fix

In the tool schema definition for message, change buttons from required to optional:

- "required": ["action", "buttons"]
+ "required": ["action"]

The buttons property should remain available for agents that want to send interactive messages, but it must not be mandatory for plain text sends.

Workaround

Use exec with curl to send messages directly via the channel API (e.g., Telegram Bot API):

BOT_TOKEN=$(python3 -c "import json; c=json.load(open('$HOME/.openclaw/openclaw.json')); print(c['channels']['telegram']['botToken'])")
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d "{\"chat_id\":\"CHAT_ID\",\"text\":\"message here\"}"

This works but bypasses OpenClaw's channel routing, delivery tracking, and multi-channel abstraction — defeating the purpose of the message() tool.

Impact

  • Blocks all programmatic message sending via the message() tool
  • Forces agents and crons to use raw API calls as workarounds
  • Particularly painful for cron jobs that need to deliver reports to users

Labels

bug, tools, message, schema

extent analysis

Fix Plan

To fix the issue, we need to update the tool schema definition for message to make the buttons property optional. Here are the steps:

  • Update the message tool schema definition:
    - "required": ["action", "buttons"]
    + "required": ["action"]
  • Example of updated schema definition:
    {
      "type": "object",
      "properties": {
        "action": {"type": "string"},
        "channel": {"type": "string"},
        "target": {"type": "string"},
        "message": {"type": "string"},
        "buttons": {"type": "array", "items": {"type": "object"}}
      },
      "required": ["action"]
    }
  • After updating the schema, restart the OpenClaw service to apply the changes.

Verification

To verify that the fix worked, try sending a message using the message tool with only the action, channel, target, and message properties:

{
  "action": "send",
  "channel": "telegram",
  "target": "8423776809",
  "message": "Hello from the agent"
}

If the message is sent successfully, the fix is working as expected.

Extra Tips

  • Make sure to test the message tool with different scenarios, including sending messages with and without buttons, to ensure that the fix does not introduce any new issues.
  • Consider adding additional validation or error handling to the message tool to handle cases where the buttons property is provided but invalid.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix message() tool requires 'buttons' property for plain action=send — breaks all non-button sends [2 pull requests, 1 participants]