Status: bundled plugin (bot token + WebSocket events). Channels, groups, and DMs are supported. Mattermost is a self-hostable team messaging platform; see the official site at mattermost.com for product details and downloads.Documentation Index
Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
Bundled plugin
Mattermost ships as a bundled plugin in current OpenClaw releases, so normal packaged builds do not need a separate install.
- npm registry
- Local checkout
Quick setup
Ensure plugin is available
Current packaged OpenClaw releases already bundle it. Older/custom installs can add it manually with the commands above.
Native slash commands
Native slash commands are opt-in. When enabled, OpenClaw registersoc_* slash commands via the Mattermost API and receives callback POSTs on the gateway HTTP server.
Behavior notes
Behavior notes
native: "auto"defaults to disabled for Mattermost. Setnative: trueto enable.- If
callbackUrlis omitted, OpenClaw derives one from gateway host/port +callbackPath. - For multi-account setups,
commandscan be set at the top level or underchannels.mattermost.accounts.<id>.commands(account values override top-level fields). - Command callbacks are validated with the per-command tokens returned by Mattermost when OpenClaw registers
oc_*commands. - Slash callbacks fail closed when registration failed, startup was partial, or the callback token does not match one of the registered commands.
Reachability requirement
Reachability requirement
The callback endpoint must be reachable from the Mattermost server.
- Do not set
callbackUrltolocalhostunless Mattermost runs on the same host/network namespace as OpenClaw. - Do not set
callbackUrlto your Mattermost base URL unless that URL reverse-proxies/api/channels/mattermost/commandto OpenClaw. - A quick check is
curl https://<gateway-host>/api/channels/mattermost/command; a GET should return405 Method Not Allowedfrom OpenClaw, not404.
Mattermost egress allowlist
Mattermost egress allowlist
If your callback targets private/tailnet/internal addresses, set Mattermost
ServiceSettings.AllowedUntrustedInternalConnections to include the callback host/domain.Use host/domain entries, not full URLs.- Good:
gateway.tailnet-name.ts.net - Bad:
https://gateway.tailnet-name.ts.net
Environment variables (default account)
Set these on the gateway host if you prefer env vars:MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Env vars apply only to the default account (
default). Other accounts must use config values.MATTERMOST_URL cannot be set from a workspace .env; see Workspace .env files.Chat modes
Mattermost responds to DMs automatically. Channel behavior is controlled bychatmode:
- oncall (default)
- onmessage
- onchar
Respond only when @mentioned in channels.
oncharstill responds to explicit @mentions.channels.mattermost.requireMentionis honored for legacy configs butchatmodeis preferred.
Threading and sessions
Usechannels.mattermost.replyToMode to control whether channel and group replies stay in the main channel or start a thread under the triggering post.
off(default): only reply in a thread when the inbound post is already in one.first: for top-level channel/group posts, start a thread under that post and route the conversation to a thread-scoped session.all: same behavior asfirstfor Mattermost today.- Direct messages ignore this setting and stay non-threaded.
- Thread-scoped sessions use the triggering post id as the thread root.
firstandallare currently equivalent because once Mattermost has a thread root, follow-up chunks and media continue in that same thread.
Access control (DMs)
- Default:
channels.mattermost.dmPolicy = "pairing"(unknown senders get a pairing code). - Approve via:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Public DMs:
channels.mattermost.dmPolicy="open"pluschannels.mattermost.allowFrom=["*"].
Channels (groups)
- Default:
channels.mattermost.groupPolicy = "allowlist"(mention-gated). - Allowlist senders with
channels.mattermost.groupAllowFrom(user IDs recommended). - Per-channel mention overrides live under
channels.mattermost.groups.<channelId>.requireMentionorchannels.mattermost.groups["*"].requireMentionfor a default. @usernamematching is mutable and only enabled whenchannels.mattermost.dangerouslyAllowNameMatching: true.- Open channels:
channels.mattermost.groupPolicy="open"(mention-gated). - Runtime note: if
channels.mattermostis completely missing, runtime falls back togroupPolicy="allowlist"for group checks (even ifchannels.defaults.groupPolicyis set).
Targets for outbound delivery
Use these target formats withopenclaw message send or cron/webhooks:
channel:<id>for a channeluser:<id>for a DM@usernamefor a DM (resolved via the Mattermost API)
DM channel retry
When OpenClaw sends to a Mattermost DM target and needs to resolve the direct channel first, it retries transient direct-channel creation failures by default. Usechannels.mattermost.dmChannelRetry to tune that behavior globally for the Mattermost plugin, or channels.mattermost.accounts.<id>.dmChannelRetry for one account.
- This applies only to DM channel creation (
/api/v4/channels/direct), not every Mattermost API call. - Retries apply to transient failures such as rate limits, 5xx responses, and network or timeout errors.
- 4xx client errors other than
429are treated as permanent and are not retried.
Preview streaming
Mattermost streams thinking, tool activity, and partial reply text into a single draft preview post that finalizes in place when the final answer is safe to send. The preview updates on the same post id instead of spamming the channel with per-chunk messages. Media/error finals cancel pending preview edits and use normal delivery instead of flushing a throwaway preview post. Enable viachannels.mattermost.streaming:
Streaming modes
Streaming modes
partialis the usual choice: one preview post that is edited as the reply grows, then finalized with the complete answer.blockuses append-style draft chunks inside the preview post.progressshows a status preview while generating and only posts the final answer at completion.offdisables preview streaming.
Streaming behavior notes
Streaming behavior notes
- If the stream cannot be finalized in place (for example the post was deleted mid-stream), OpenClaw falls back to sending a fresh final post so the reply is never lost.
- Reasoning-only payloads are suppressed from channel posts, including text that arrives as a
> Reasoning:blockquote. Set/reasoning onto see thinking in other surfaces; the Mattermost final post keeps the answer only. - See Streaming for the channel-mapping matrix.
Reactions (message tool)
- Use
message action=reactwithchannel=mattermost. messageIdis the Mattermost post id.emojiaccepts names likethumbsupor:+1:(colons are optional).- Set
remove=true(boolean) to remove a reaction. - Reaction add/remove events are forwarded as system events to the routed agent session.
channels.mattermost.actions.reactions: enable/disable reaction actions (default true).- Per-account override:
channels.mattermost.accounts.<id>.actions.reactions.
Interactive buttons (message tool)
Send messages with clickable buttons. When a user clicks a button, the agent receives the selection and can respond. Enable buttons by addinginlineButtons to the channel capabilities:
message action=send with a buttons parameter. Buttons are a 2D array (rows of buttons):
Display label.
Value sent back on click (used as the action ID).
Button style.
Buttons replaced with confirmation
All buttons are replaced with a confirmation line (e.g., ”✓ Yes selected by @user”).
Implementation notes
Implementation notes
- Button callbacks use HMAC-SHA256 verification (automatic, no config needed).
- Mattermost strips callback data from its API responses (security feature), so all buttons are removed on click — partial removal is not possible.
- Action IDs containing hyphens or underscores are sanitized automatically (Mattermost routing limitation).
Config and reachability
Config and reachability
channels.mattermost.capabilities: array of capability strings. Add"inlineButtons"to enable the buttons tool description in the agent system prompt.channels.mattermost.interactions.callbackBaseUrl: optional external base URL for button callbacks (for examplehttps://gateway.example.com). Use this when Mattermost cannot reach the gateway at its bind host directly.- In multi-account setups, you can also set the same field under
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - If
interactions.callbackBaseUrlis omitted, OpenClaw derives the callback URL fromgateway.customBindHost+gateway.port, then falls back tohttp://localhost:<port>. - Reachability rule: the button callback URL must be reachable from the Mattermost server.
localhostonly works when Mattermost and OpenClaw run on the same host/network namespace. - If your callback target is private/tailnet/internal, add its host/domain to Mattermost
ServiceSettings.AllowedUntrustedInternalConnections.
Direct API integration (external scripts)
External scripts and webhooks can post buttons directly via the Mattermost REST API instead of going through the agent’smessage tool. Use buildButtonAttachments() from the plugin when possible; if posting raw JSON, follow these rules:
Payload structure:
Derive the secret from the bot token
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)Serialize with sorted keys
Serialize with sorted keys and no spaces (the gateway uses
JSON.stringify with sorted keys, which produces compact output).Common HMAC pitfalls
Common HMAC pitfalls
- Python’s
json.dumpsadds spaces by default ({"key": "val"}). Useseparators=(",", ":")to match JavaScript’s compact output ({"key":"val"}). - Always sign all context fields (minus
_token). The gateway strips_tokenthen signs everything remaining. Signing a subset causes silent verification failure. - Use
sort_keys=True— the gateway sorts keys before signing, and Mattermost may reorder context fields when storing the payload. - Derive the secret from the bot token (deterministic), not random bytes. The secret must be the same across the process that creates buttons and the gateway that verifies.
Directory adapter
The Mattermost plugin includes a directory adapter that resolves channel and user names via the Mattermost API. This enables#channel-name and @username targets in openclaw message send and cron/webhook deliveries.
No configuration is needed — the adapter uses the bot token from the account config.
Multi-account
Mattermost supports multiple accounts underchannels.mattermost.accounts:
Troubleshooting
No replies in channels
No replies in channels
Ensure the bot is in the channel and mention it (oncall), use a trigger prefix (onchar), or set
chatmode: "onmessage".Auth or multi-account errors
Auth or multi-account errors
- Check the bot token, base URL, and whether the account is enabled.
- Multi-account issues: env vars only apply to the
defaultaccount.
Native slash commands fail
Native slash commands fail
Unauthorized: invalid command token.: OpenClaw did not accept the callback token. Typical causes:- slash command registration failed or only partially completed at startup
- the callback is hitting the wrong gateway/account
- Mattermost still has old commands pointing at a previous callback target
- the gateway restarted without reactivating slash commands
- If native slash commands stop working, check logs for
mattermost: failed to register slash commandsormattermost: native slash commands enabled but no commands could be registered. - If
callbackUrlis omitted and logs warn that the callback resolved tohttp://127.0.0.1:18789/..., that URL is probably only reachable when Mattermost runs on the same host/network namespace as OpenClaw. Set an explicit externally reachablecommands.callbackUrlinstead.
Buttons issues
Buttons issues
Related
- Channel Routing — session routing for messages
- Channels Overview — all supported channels
- Groups — group chat behavior and mention gating
- Pairing — DM authentication and pairing flow
- Security — access model and hardening