消息平台
Mattermost
Status:可下载插件(bot token + WebSocket 事件)。支持频道、群组和私信。Mattermost 是一个可自托管的团队消息平台;产品详情和下载请参见官方网站 mattermost.com。
安装
在配置渠道之前安装 Mattermost:
npm registry
openclaw plugins install @openclaw/mattermost本地检出
openclaw plugins install ./path/to/local/mattermost-plugin详情:插件
快速设置
确保插件可用
当前打包的 OpenClaw 版本已经内置它。较旧版本/自定义安装可以用上面的命令手动添加。
创建 Mattermost bot
创建一个 Mattermost bot 账号并复制 bot token。
复制基础 URL
复制 Mattermost base URL(例如 https://chat.example.com)。
配置 OpenClaw 并启动 Gateway 网关
最小配置:
{ channels: { mattermost: { enabled: true, botToken: "mm-token", baseUrl: "https://chat.example.com", dmPolicy: "pairing", }, },}原生斜杠命令
原生斜杠命令是选择启用的。启用后,OpenClaw 会通过 Mattermost API 注册 oc_* 斜杠命令,并在 Gateway 网关 HTTP 服务器上接收回调 POST。
{ channels: { mattermost: { commands: { native: true, nativeSkills: true, callbackPath: "/api/channels/mattermost/command", // Use when Mattermost cannot reach the gateway directly (reverse proxy/public URL). callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, }, },}行为说明
- 对于 Mattermost,
native: "auto"默认禁用。设置native: true以启用。 - 如果省略
callbackUrl,OpenClaw 会根据 Gateway 网关 host/port +callbackPath推导一个。 - 对于多账号设置,
commands可以设在顶层,也可以设在channels.mattermost.accounts.<id>.commands下(账号值会覆盖顶层字段)。 - 命令回调会使用 Mattermost 在 OpenClaw 注册
oc_*命令时返回的每条命令 token 进行验证。 - OpenClaw 会在接受每个回调前刷新当前 Mattermost 命令注册,因此已删除或重新生成的斜杠命令的过期 token 无需重启 Gateway 网关也会停止被接受。
- 如果 Mattermost API 无法确认该命令仍是当前命令,回调验证会失败关闭;失败的验证会被短暂缓存,并发查找会被合并,新的查找启动会按命令限速,以限制重放压力。
- 当注册失败、启动不完整,或回调 token 与解析出的命令注册 token 不匹配时,斜杠回调会失败关闭(对一个命令有效的 token 不能到达另一个命令的上游验证)。
可达性要求
回调端点必须能从 Mattermost 服务器访问。
- 不要将
callbackUrl设置为localhost,除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中。 - 不要将
callbackUrl设置为你的 Mattermost base URL,除非该 URL 将/api/channels/mattermost/command反向代理到 OpenClaw。 - 快速检查方式是
curl https://<gateway-host>/api/channels/mattermost/command;GET 应返回 OpenClaw 的405 Method Not Allowed,而不是404。
Mattermost 出站 allowlist
如果你的回调目标是私有/tailnet/内部地址,请将 Mattermost ServiceSettings.AllowedUntrustedInternalConnections 设置为包含回调主机/域名。
使用主机/域名条目,而不是完整 URL。
- 正确:
gateway.tailnet-name.ts.net - 错误:
https://gateway.tailnet-name.ts.net
环境变量(默认账号)
如果你偏好环境变量,请在 Gateway 网关主机上设置这些:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
聊天模式
Mattermost 会自动响应私信。频道行为由 chatmode 控制:
oncall(默认)
仅在频道中被 @提及时响应。
onmessage
响应每条频道消息。
onchar
当消息以触发前缀开头时响应。
配置示例:
{ channels: { mattermost: { chatmode: "onchar", oncharPrefixes: [">", "!"], }, },}说明:
onchar仍会响应显式 @提及。- 旧版配置会继续遵循
channels.mattermost.requireMention,但推荐使用chatmode。
线程和会话
使用 channels.mattermost.replyToMode 控制频道和群组回复是留在主频道中,还是在触发帖下启动线程。
off(默认):仅当入站帖已经在线程中时,才在线程中回复。first:对于顶层频道/群组帖,在该帖下启动线程,并将对话路由到线程作用域的会话。all:目前在 Mattermost 中行为与first相同。- 直接消息会忽略此设置并保持非线程化。
配置示例:
{ channels: { mattermost: { replyToMode: "all", }, },}说明:
- 线程作用域的会话使用触发帖 id 作为线程根。
first和all目前等价,因为一旦 Mattermost 有了线程根,后续分块和媒体会继续在同一线程中发送。
访问控制(私信)
- 默认:
channels.mattermost.dmPolicy = "pairing"(未知发送者会收到配对码)。 - 通过以下命令批准:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- 公开私信:
channels.mattermost.dmPolicy="open"加channels.mattermost.allowFrom=["*"]。 channels.mattermost.allowFrom接受accessGroup:<name>条目。参见访问组。
频道(群组)
- 默认:
channels.mattermost.groupPolicy = "allowlist"(需要提及)。 - 使用
channels.mattermost.groupAllowFrom对发送者进行 allowlist(推荐使用用户 ID)。 channels.mattermost.groupAllowFrom接受accessGroup:<name>条目。参见访问组。- 每个频道的提及覆盖项位于
channels.mattermost.groups.<channelId>.requireMention下,默认值可用channels.mattermost.groups["*"].requireMention。 @username匹配是可变的,并且仅在channels.mattermost.dangerouslyAllowNameMatching: true时启用。- 开放频道:
channels.mattermost.groupPolicy="open"(需要提及)。 - 运行时说明:如果完全缺少
channels.mattermost,运行时会回退到groupPolicy="allowlist"进行群组检查(即使已设置channels.defaults.groupPolicy)。
示例:
{ channels: { mattermost: { groupPolicy: "open", groups: { "*": { requireMention: true }, "team-channel-id": { requireMention: false }, }, }, },}出站投递目标
将这些目标格式用于 openclaw message send 或 cron/webhooks:
channel:<id>表示频道user:<id>表示私信@username表示私信(通过 Mattermost API 解析)
私信频道重试
当 OpenClaw 发送到 Mattermost 私信目标且需要先解析直接频道时,它默认会重试短暂性的直接频道创建失败。
使用 channels.mattermost.dmChannelRetry 为 Mattermost 插件全局调整该行为,或使用 channels.mattermost.accounts.<id>.dmChannelRetry 为某个账号调整。
{ channels: { mattermost: { dmChannelRetry: { maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 10000, timeoutMs: 30000, }, }, },}说明:
- 这仅适用于私信频道创建(
/api/v4/channels/direct),不是每个 Mattermost API 调用。 - 重试适用于短暂性失败,例如限速、5xx 响应以及网络或超时错误。
- 除
429之外的 4xx 客户端错误会被视为永久错误,不会重试。
预览流式传输
Mattermost 会将思考、工具活动和部分回复文本流式传输到单个草稿预览帖中,并在最终答案可安全发送时就地完成。预览会在同一个帖 id 上更新,而不是用逐块消息刷屏频道。媒体/错误最终消息会取消待处理的预览编辑,并使用正常投递,而不是刷新一个一次性预览帖。
通过 channels.mattermost.streaming 启用:
{ channels: { mattermost: { streaming: "partial", // off | partial | block | progress }, },}流式传输模式
partial是常用选择:一个预览帖会随着回复增长而被编辑,然后用完整答案最终完成。block在预览帖内使用追加式草稿分块。progress在生成时显示状态预览,并且只在完成时发布最终答案。off禁用预览流式传输。
流式传输行为说明
- 如果流无法就地完成(例如帖在流式传输中途被删除),OpenClaw 会回退到发送新的最终帖,确保回复不会丢失。
- 仅推理载荷会从频道帖中抑制,包括作为
> Reasoning:blockquote 到达的文本。设置/reasoning on可在其他表面查看思考;Mattermost 最终帖只保留答案。 - 有关频道映射矩阵,请参见流式传输。
表情回应(消息工具)
- 使用
message action=react并设置channel=mattermost。 messageId是 Mattermost 帖 id。emoji接受类似thumbsup或:+1:的名称(冒号可选)。- 设置
remove=true(布尔值)以移除表情回应。 - 添加/移除表情回应事件会作为系统事件转发到被路由的 agent 会话。
示例:
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsupmessage action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup remove=true配置:
channels.mattermost.actions.reactions:启用/禁用表情回应操作(默认 true)。- 每账号覆盖:
channels.mattermost.accounts.<id>.actions.reactions。
交互式按钮(消息工具)
发送带可点击按钮的消息。当用户点击按钮时,agent 会收到选择并可以响应。
通过向渠道能力添加 inlineButtons 来启用按钮:
{ channels: { mattermost: { capabilities: ["inlineButtons"], }, },}将 message action=send 与 buttons 参数一起使用。按钮是二维数组(按钮行):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]按钮字段:
textstringrequired显示标签。
callback_datastringrequired点击时回传的值(用作操作 ID)。
style"default" | "primary" | "danger"按钮样式。
当用户点击按钮时:
按钮被替换为确认信息
所有按钮都会被替换为一行确认信息(例如,“✓ Yes selected by @user”)。
智能体接收选择
智能体会以入站消息形式接收该选择并作出响应。
实现说明
- 按钮回调使用 HMAC-SHA256 验证(自动完成,无需配置)。
- Mattermost 会从其 API 响应中剥离回调数据(安全功能),因此点击后会移除所有按钮,无法部分移除。
- 包含连字符或下划线的操作 ID 会自动清理(Mattermost 路由限制)。
配置和可达性
channels.mattermost.capabilities:能力字符串数组。添加"inlineButtons"可在智能体系统提示中启用按钮工具说明。channels.mattermost.interactions.callbackBaseUrl:可选的外部基础 URL,用于按钮回调(例如https://gateway.example.com)。当 Mattermost 无法直接通过 Gateway 网关的绑定主机访问它时使用此项。- 在多账号设置中,你也可以在
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl下设置相同字段。 - 如果省略
interactions.callbackBaseUrl,OpenClaw 会从gateway.customBindHost+gateway.port派生回调 URL,然后回退到http://localhost:<port>。 - 可达性规则:按钮回调 URL 必须可从 Mattermost 服务器访问。只有当 Mattermost 和 OpenClaw 在同一主机/网络命名空间中运行时,
localhost才有效。 - 如果你的回调目标是私有/tailnet/内部目标,请将其主机/域名添加到 Mattermost
ServiceSettings.AllowedUntrustedInternalConnections。
直接 API 集成(外部脚本)
外部脚本和 webhook 可以通过 Mattermost REST API 直接发布按钮,而不必经过智能体的 message 工具。尽可能使用插件中的 buildButtonAttachments();如果发布原始 JSON,请遵循这些规则:
载荷结构:
{ channel_id: "<channelId>", message: "Choose an option:", props: { attachments: [ { actions: [ { id: "mybutton01", // alphanumeric only - see below type: "button", // required, or clicks are silently ignored name: "Approve", // display label style: "primary", // optional: "default", "primary", "danger" integration: { url: "https://gateway.example.com/mattermost/interactions/default", context: { action_id: "mybutton01", // must match button id (for name lookup) action: "approve", // ... any custom fields ... _token: "<hmac>", // see HMAC section below }, }, }, ], }, ], },}HMAC 令牌生成
Gateway 网关使用 HMAC-SHA256 验证按钮点击。外部脚本必须生成与 Gateway 网关验证逻辑匹配的令牌:
从机器人令牌派生密钥
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
构建上下文对象
使用除 _token 之外的所有字段构建上下文对象。
使用排序后的键序列化
使用排序后的键且无空格进行序列化(Gateway 网关使用带排序键的 JSON.stringify,会生成紧凑输出)。
签名载荷
HMAC-SHA256(key=secret, data=serializedContext)
添加令牌
将生成的十六进制摘要作为 _token 添加到上下文中。
Python 示例:
secret = hmac.new( b"openclaw-mattermost-interactions", bot_token.encode(), hashlib.sha256).hexdigest() ctx = {"action_id": "mybutton01", "action": "approve"}payload = json.dumps(ctx, sort_keys=True, separators=(",", ":"))token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() context = {**ctx, "_token": token}常见 HMAC 陷阱
- Python 的
json.dumps默认会添加空格({"key": "val"})。使用separators=(",", ":")以匹配 JavaScript 的紧凑输出({"key":"val"})。 - 始终签名所有上下文字段(不含
_token)。Gateway 网关会移除_token,然后签名剩余所有内容。只签名子集会导致静默验证失败。 - 使用
sort_keys=True,Gateway 网关会在签名前对键排序,而 Mattermost 在存储载荷时可能会重新排列上下文字段。 - 从机器人令牌派生密钥(确定性),不要使用随机字节。创建按钮的进程和执行验证的 Gateway 网关必须使用相同密钥。
目录适配器
Mattermost 插件包含一个目录适配器,会通过 Mattermost API 解析渠道和用户名。这会在 openclaw message send 以及 cron/webhook 投递中启用 #channel-name 和 @username 目标。
无需配置,适配器使用账号配置中的机器人令牌。
多账号
Mattermost 支持在 channels.mattermost.accounts 下配置多个账号:
{ channels: { mattermost: { accounts: { default: { name: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" }, alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" }, }, }, },}故障排除
渠道中没有回复
确保机器人在该渠道中,并提及它(oncall)、使用触发前缀(onchar),或设置 chatmode: "onmessage"。
认证或多账号错误
- 检查机器人令牌、基础 URL,以及账号是否已启用。
- 多账号问题:环境变量只应用于
default账号。
原生斜杠命令失败
Unauthorized: invalid command token.:OpenClaw 未接受回调令牌。典型原因:- 斜杠命令注册失败,或启动时只部分完成
- 回调命中了错误的 Gateway 网关/账号
- Mattermost 仍有指向先前回调目标的旧命令
- Gateway 网关重启后没有重新激活斜杠命令
- 如果原生斜杠命令停止工作,请检查日志中是否有
mattermost: failed to register slash commands或mattermost: native slash commands enabled but no commands could be registered。 - 如果省略
callbackUrl,且日志警告回调解析为http://127.0.0.1:18789/...,那么该 URL 可能只有在 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间时才可达。请改为设置显式的外部可达commands.callbackUrl。
按钮问题
- 按钮显示为空白框:智能体可能正在发送格式错误的按钮数据。检查每个按钮是否同时具有
text和callback_data字段。 - 按钮会渲染但点击无效:验证 Mattermost 服务器配置中的
AllowedUntrustedInternalConnections是否包含127.0.0.1 localhost,并且 ServiceSettings 中的EnablePostActionIntegration是否为true。 - 点击按钮返回 404:按钮
id很可能包含连字符或下划线。Mattermost 的操作路由器会在非字母数字 ID 上失效。仅使用[a-zA-Z0-9]。 - Gateway 网关日志显示
invalid _token:HMAC 不匹配。检查你是否签名了所有上下文字段(而不是子集)、是否使用排序键,以及是否使用紧凑 JSON(无空格)。参见上面的 HMAC 部分。 - Gateway 网关日志显示
missing _token in context:按钮上下文中没有_token字段。构建集成载荷时确保包含它。 - 确认消息显示原始 ID 而不是按钮名称:
context.action_id与按钮的id不匹配。将两者设置为同一个清理后的值。 - 智能体不知道按钮:将
capabilities: ["inlineButtons"]添加到 Mattermost 渠道配置。