Skip to content

message() tool requires 'buttons' property for plain action=send — breaks all non-button sends #54385

Description

@adzendo

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions