openclaw message CLI: Send Messages & Channel Actions

Reference for the openclaw message command, covering target formats and channel selection for Discord, Slack, Telegram, and more. Essential for developers automating outbound messaging.

Read this when

  • Adding or modifying message CLI actions
  • Changing outbound channel behavior

openclaw message

One command handles outbound messaging and channel actions across Discord, Google Chat, iMessage, Matrix, Mattermost (plugin), Microsoft Teams, Signal, Slack, Telegram, and WhatsApp.

openclaw message <subcommand> [flags]

Channel selection

  • When multiple channels are set up, --channel <name> becomes mandatory; a single configured channel automatically serves as the default.
  • Acceptable inputs are discord|googlechat|imessage|matrix|mattermost|msteams|signal|slack|telegram|whatsapp (the Mattermost plugin is a prerequisite).
  • Targets prefixed with a channel, such as discord:channel:123, point to the correct plugin without needing an explicit --channel.

Target formats (-t, --target)

ChannelFormat
Discordchannel:<id>, user:<id>, <@id> mention, or a plain numeric id (interpreted as a channel id)
Google Chatspaces/<spaceId> or users/<userId>
iMessagehandle, chat_id:<id>, chat_guid:<guid>, or chat_identifier:<id>
Mattermost (plugin)channel:<id>, user:<id>, @username, or a plain id (interpreted as a channel)
Matrix@user:server, !room:server, or #alias:server
Microsoft Teamsconversation:<id> (19:...@thread.tacv2), a plain conversation id, or user:<aad-object-id>
Signal+E.164, group:<id>, uuid:<id>, username:<name>/u:<name>, or any of these with signal: as a prefix
Slackchannel:<id> or user:<id> (a plain id is interpreted as a channel)
Telegramchat id, @username, or a forum topic target: <chatId>:topic:<topicId> (or --thread-id <topicId>)
WhatsAppE.164, group JID (...@g.us), or Channel/Newsletter JID (...@newsletter)

Resolving channel names: on platforms with a directory (Discord/Slack/etc), entries like Help or #help come from the directory cache; a miss triggers a live lookup where the provider allows it.

Common flags

Each action takes these parameters: --channel <name>, --account <id>, --json, --dry-run, --verbose. When an action needs a destination, -t, --target <dest> is also accepted.

SecretRef resolution

Before executing, openclaw message resolves channel SecretRefs with the tightest possible scope:

  • channel-level when --channel is provided (or deduced from a prefixed target)
  • account-level when --account is additionally provided
  • all configured channels when neither is provided

Missing SecretRefs on unrelated channels don't interfere with a targeted action; a missing SecretRef on the chosen channel or account causes the action to fail closed.

Actions

Core

ActionChannelsRequiredNotes
sendDiscord, Google Chat, iMessage, Matrix, Mattermost (plugin), Microsoft Teams, Signal, Slack, Telegram, WhatsApp--target, plus one of --message/--media/--presentationRefer to Send further down.
pollDiscord, Matrix, Microsoft Teams, Telegram, WhatsApp--target, --poll-question, --poll-option (repeat)Check Poll further down.
reactDiscord, Matrix, Nextcloud Talk, Signal, Slack, Telegram, WhatsApp--message-id, --target--emoji, --remove (requires --emoji; leave it out to remove your own reactions where the platform allows it, see Reactions). On WhatsApp: --participant, --from-me. Signal group reactions depend on --target-author or --target-author-uuid. Nextcloud Talk only supports adding reactions; --remove produces an error.
reactionsDiscord, Matrix, Microsoft Teams, Slack--message-id, --target--limit.
readDiscord, Matrix, Microsoft Teams, Slack--target--limit, --message-id, --before, --after. For Discord: --around, --include-thread. For Slack: --message-id targets a particular timestamp, pair it with --thread-id to reply to a specific thread.
editDiscord, Matrix, Microsoft Teams, Slack, Telegram--message-id, --message, --targetTelegram forum threads rely on --thread-id.
deleteDiscord, Matrix, Microsoft Teams, Slack, Telegram--message-id, --target
pin / unpinDiscord, Matrix, Microsoft Teams, Slack--message-id, --targetunpin also takes --pinned-message-id (in Microsoft Teams, that is the pin/list-pins resource id, not the chat message id).
pins (list)Discord, Matrix, Microsoft Teams, Slack--target--limit.
permissionsDiscord, Matrix--targetOn Matrix, this works only when encryption is turned on and verification actions are permitted.
searchDiscord--guild-id, --query--channel-id, --channel-ids (repeat), --author-id, --author-ids (repeat), --limit.
member infoDiscord, Matrix, Microsoft Teams, Slack--user-id--guild-id (Discord).

Send

openclaw message send --channel discord \
  --target channel:123 --message "hi" --reply-to 456
  • --media <path-or-url>: attach image/audio/video/document (local path or URL).
  • --presentation <json>: shared payload with text, context, divider, chart, table, buttons, and select blocks, rendered per channel capability. See Message Presentation.
  • --delivery <json>: generic delivery preferences, for example {"pin": true}. --pin is shorthand for pinned delivery when the channel supports it.
  • --reply-to <id>, --thread-id <id> (Telegram forum topic; Slack thread timestamp, same field as --reply-to).
  • --force-document: preserve original image bytes on Slack, or send images/GIFs/videos as documents on Telegram and WhatsApp, to avoid channel compression.
  • --silent (Telegram, Discord): send without a notification.
  • --gif-playback (WhatsApp only): treat video media as GIF playback.

When a send is suppressed by a message hook, fails, or only partially succeeds, the command explains the outcome and exits nonzero. Partial delivery keeps any confirmed message ID. JSON failures include ok: false, deliveryStatus, and error; successful JSON responses retain their existing shape.

openclaw message send --channel discord \
  --target channel:123 --message "Choose:" \
  --presentation '{"blocks":[{"type":"buttons","buttons":[{"label":"Approve","value":"approve","style":"success"},{"label":"Decline","value":"decline","style":"danger"}]}]}'
openclaw message send --channel telegram --target @mychat --message "Choose:" \
  --presentation '{"blocks":[{"type":"buttons","buttons":[{"label":"Yes","value":"cmd:yes"},{"label":"No","value":"cmd:no"}]}]}'

Slack renders supported chart blocks natively; other channels receive the same data as readable text:

openclaw message send --channel slack --target channel:C123 \
  --presentation '{"blocks":[{"type":"chart","chartType":"bar","title":"Quarterly revenue","categories":["Q1","Q2"],"series":[{"name":"Revenue","values":[120,145]}],"xLabel":"Quarter"}]}'

Slack also renders explicit table blocks natively. Other channels receive the caption and every row as deterministic text:

openclaw message send --channel slack --target channel:C123 \
  --presentation '{"title":"Pipeline report","blocks":[{"type":"table","caption":"Open pipeline","headers":["Account","Stage","ARR"],"rows":[["Acme","Won",125000],["Globex","Review",82000]],"rowHeaderColumnIndex":0}]}'

Telegram Mini App buttons use webApp (web_app still parses for legacy JSON) and only render in private chats between a user and the bot:

openclaw message send --channel telegram --target 123456789 --message "Open app:" \
  --presentation '{"blocks":[{"type":"buttons","buttons":[{"label":"Launch","webApp":{"url":"https://example.com/app"}}]}]}'
openclaw message send --channel telegram --target @mychat \
  --media ./diagram.png --force-document
openclaw message send --channel msteams \
  --target conversation:19:abc@thread.tacv2 \
  --presentation '{"title":"Status update","blocks":[{"type":"text","text":"Build completed"}]}'

Poll

openclaw message poll --channel discord \
  --target channel:123 \
  --poll-question "Snack?" \
  --poll-option Pizza --poll-option Sushi \
  --poll-multi --poll-duration-hours 48
  • --poll-option <choice>: repeat 2-12 times.
  • --poll-multi: allow multiple selections.
  • Discord: --poll-duration-hours, --silent, --message.
  • Telegram: --poll-duration-seconds <n> (5-604800; up to seven days), --silent, --poll-anonymous / --poll-public, --thread-id.
openclaw message poll --channel telegram \
  --target @mychat \
  --poll-question "Lunch?" \
  --poll-option Pizza --poll-option Sushi \
  --poll-duration-seconds 120 --silent
openclaw message poll --channel msteams \
  --target conversation:19:abc@thread.tacv2 \
  --poll-question "Lunch?" \
  --poll-option Pizza --poll-option Sushi

Threads

  • thread create: Discord channel targeting. Mandatory fields: --thread-name, --target (channel id). Non-required fields: --message-id, --message, --auto-archive-min.
  • thread list: Discord channel targeting. Mandatory field: --guild-id. Non-required fields: --channel-id, --include-archived, --before, --limit.
  • thread reply: Discord channel targeting. Mandatory fields: --target (thread id), --message. Non-required fields: --media, --reply-to.

Emojis

  • emoji list: Discord (--guild-id), Slack (no extra flags).
  • emoji upload: Discord. Mandatory fields: --guild-id, --emoji-name, --media. Non-required field: --role-ids (repeat).

Stickers

  • sticker send: Discord. Mandatory fields: --target, --sticker-id (repeat). Non-required field: --message.
  • sticker upload: Discord. Mandatory fields: --guild-id, --sticker-name, --sticker-desc, --sticker-tags, --media.

Roles, channels, voice, events (Discord)

  • role info: --guild-id.
  • role add / role remove: --guild-id, --user-id, --role-id.
  • channel info: --target.
  • channel list: --guild-id.
  • voice status: --guild-id, --user-id.
  • event list: --guild-id.
  • event create: required --guild-id, --event-name, --start-time; optional --end-time, --desc, --channel-id, --location, --event-type, --image <url-or-path>.

Moderation (Discord)

  • timeout: --guild-id, --user-id; optional --duration-min or --until (omit both to clear the timeout), --reason.
  • kick: --guild-id, --user-id, --reason.
  • ban: --guild-id, --user-id, --delete-days, --reason.

Broadcast

openclaw message broadcast --targets <target...> [--channel all] [--message <text>] [--media <url>] [--dry-run]

A single payload can be delivered to several destinations at once. Pass a space-separated list to --targets. To reach every provider that is set up, use --channel all.

1,323 words · updated Aug 28, 2026