openclaw message CLI: Send Messages & Channel Actions
Reference for the openclaw message command, covering message sending and channel actions across multiple platforms. Essential for users managing multi-channel communication from the CLI.
Read this when
- Adding or modifying message CLI actions
- Changing outbound channel behavior
openclaw message
A unified command to send messages and perform 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; if only one channel exists, that channel is used by default. - Acceptable values:
discord|googlechat|imessage|matrix|mattermost|msteams|signal|slack|telegram|whatsapp(the plugin is required for Mattermost). - Targets prefixed with a channel, like
discord:channel:123, identify the owning plugin without needing an explicit--channel.
Target formats (-t, --target)
| Channel | Format |
|---|---|
| Discord | channel:<id>, user:<id>, <@id> mention, or a plain numeric id (interpreted as a channel id) |
| Google Chat | spaces/<spaceId> or users/<userId> |
| iMessage | handle, chat_id:<id>, chat_guid:<guid>, or chat_identifier:<id> |
| Mattermost (plugin) | channel:<id>, user:<id>, @username, or a bare id (interpreted as a channel) |
| Matrix | @user:server, !room:server, or #alias:server |
| Microsoft Teams | conversation:<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 a signal: prefix |
| Slack | channel:<id> or user:<id> (a bare id is interpreted as a channel) |
| Telegram | chat id, @username, or a forum topic target: <chatId>:topic:<topicId> (or --thread-id <topicId>) |
E.164, group JID (...@g.us), or Channel/Newsletter JID (...@newsletter) |
Channel name resolution: for providers that maintain a directory (Discord, Slack, and others), names
such as Help or #help are looked up from the directory cache, with a fallback to a live
directory query when the cache does not contain the entry and the provider supports it.
Common flags
All actions accept these parameters: --channel <name>, --account <id>, --json,
--dry-run, --verbose. Actions that require a destination also accept
-t, --target <dest>.
SecretRef resolution
openclaw message resolves channel SecretRefs before executing the action,
applying the narrowest possible scope:
- channel scope when
--channelis provided (or inferred from a prefixed target) - account scope when
--accountis also provided - all configured channels when neither is provided
Unresolved SecretRefs on unrelated channels never block a targeted action; an unresolved SecretRef on the chosen channel or account causes the action to fail immediately.
Actions
Core
| Action | Channels | Required | Notes |
|---|---|---|---|
send | Discord, Google Chat, iMessage, Matrix, Mattermost (plugin), Microsoft Teams, Signal, Slack, Telegram, WhatsApp | --target, plus one of --message/--media/--presentation | Refer to the Send section below. |
poll | Discord, Matrix, Microsoft Teams, Telegram, WhatsApp | --target, --poll-question, --poll-option (repeat) | Check the Poll section below. |
react | Discord, Matrix, Nextcloud Talk, Signal, Slack, Telegram, WhatsApp | --message-id, --target | --emoji, --remove (requires --emoji; leave it out to clear your own reactions where the platform allows, see Reactions). On WhatsApp: --participant, --from-me. For Signal group reactions you need --target-author or --target-author-uuid. Nextcloud Talk can only add reactions; --remove results in an error. |
reactions | Discord, Matrix, Microsoft Teams, Slack | --message-id, --target | --limit. |
read | Discord, Matrix, Microsoft Teams, Slack | --target | --limit, --message-id, --before, --after. For Discord: --around, --include-thread. In Slack: --message-id reads a particular timestamp; pair it with --thread-id to reply directly in a thread. |
edit | Discord, Matrix, Microsoft Teams, Slack, Telegram | --message-id, --message, --target | Telegram forum threads make use of --thread-id. |
delete | Discord, Matrix, Microsoft Teams, Slack, Telegram | --message-id, --target | |
pin / unpin | Discord, Matrix, Microsoft Teams, Slack | --message-id, --target | unpin also supports --pinned-message-id (in Microsoft Teams this is the resource ID for pin/list-pins, not the chat message ID). |
pins (list) | Discord, Matrix, Microsoft Teams, Slack | --target | --limit. |
permissions | Discord, Matrix | --target | On Matrix this works only when encryption is active and verification actions are permitted. |
search | Discord | --guild-id, --query | --channel-id, --channel-ids (repeat), --author-id, --author-ids (repeat), --limit. |
member info | Discord, 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 an image, audio, video, or document by providing either a local path or a URL.--presentation <json>: a combined payload withtext,context,divider,chart,table,buttons, andselectblocks, adapted for each channel's capabilities. Refer to Message Presentation.--delivery <json>: general delivery preferences, such as{"pin": true}. When the channel supports it,--pinacts as a shortcut for pinned delivery.--reply-to <id>,--thread-id <id>(Telegram forum topic; Slack thread timestamp, using the same field as--reply-to).--force-document(Telegram, WhatsApp): send images, GIFs, or videos as documents to bypass channel compression.--silent(Telegram, Discord): suppress the notification for this message.--gif-playback(WhatsApp only): treat video media as a GIF animation.
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; on all other channels the same data is presented 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. On other channels the caption and each row are displayed 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 legacy JSON) and only appear 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 the action 2 to 12 times.--poll-multi: permit multiple selections.- Discord:
--poll-duration-hours,--silent,--message. - Telegram:
--poll-duration-seconds <n>(range 5 to 600),--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 channels. Mandatory fields:--thread-name,--target(channel id). Optional fields:--message-id,--message,--auto-archive-min.thread list: Discord channels. Mandatory field:--guild-id. Optional fields:--channel-id,--include-archived,--before,--limit.thread reply: Discord channels. Mandatory fields:--target(thread id),--message. Optional fields:--media,--reply-to.
Emojis
emoji list: Discord (--guild-id), Slack (no additional flags).emoji upload: Discord. Mandatory fields:--guild-id,--emoji-name,--media. Optional field:--role-ids(repeat).
Stickers
sticker send: Discord. Mandatory fields:--target,--sticker-id(repeat). Optional 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:--guild-id,--event-name, and--start-timeare mandatory;--end-time,--desc,--channel-id,--location,--event-type, and--image <url-or-path>are not.
Moderation (Discord)
timeout:--guild-idand--user-id; optionally--duration-minor--until(leaving both out removes the timeout),--reason.kick:--guild-id,--user-id, and--reason.ban:--guild-id,--user-id,--delete-days, and--reason.
Broadcast
openclaw message broadcast --targets <target...> [--channel all] [--message <text>] [--media <url>] [--dry-run]
A single message is delivered to several destinations. --targets expects a list separated by spaces. To send to all configured providers, use --channel all.