跳转至

Mattermost

状态:可下载插件(机器人令牌 + WebSocket 事件)。支持频道、私有频道、群组私信和私信。Mattermost 是一个可自托管的团队消息平台(mattermost.com)。

安装

openclaw plugins install @openclaw/mattermost
openclaw plugins install ./path/to/local/mattermost-plugin

详情:插件

快速设置

1. 确保插件可用

使用上述命令安装 @openclaw/mattermost。在继续之前,检查应用结果。

2. 创建 Mattermost 机器人

创建一个 Mattermost 机器人账号,复制机器人令牌,并将该机器人添加到它需要读取的团队和频道中。

3. 复制基础 URL

复制 Mattermost 基础 URL(例如 https://chat.example.com)。结尾的 /api/v4 会被自动去除。

4. 配置 OpenClaw 并启动网关

最小配置:

{
  channels: {
    mattermost: {
      enabled: true,
      botToken: "mm-token",
      baseUrl: "https://chat.example.com",
      dmPolicy: "pairing",
    },
  },
}

非交互式替代方案:

openclaw channels add --channel mattermost --bot-token <token> --http-url https://chat.example.com

Note

自托管于私有/局域网/tailnet 地址的 Mattermost:出站 Mattermost API 请求会经过 SSRF 防护,默认阻止私有和内部 IP。可通过 channels.mattermost.network.dangerouslyAllowPrivateNetwork: true 选择启用(按账户:channels.mattermost.accounts.<id>.network.dangerouslyAllowPrivateNetwork)。

原生斜杠命令

原生斜杠命令为可选启用。启用后,OpenClaw 会在机器人所属的每个团队上注册 oc_* 斜杠命令,并通过网关 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",
      },
    },
  },
}

已注册命令:/oc_status、/oc_model、/oc_models、/oc_new、/oc_help、/oc_think、/oc_reasoning、/oc_verbose、/oc_queue。当 nativeSkills: true 时,技能命令也会注册为 /oc_<skill>。

行为说明
  • native 和 nativeSkills 默认值为 "auto",对于 Mattermost 会解析为禁用。请显式设为 true。
  • callbackPath 默认为 /api/channels/mattermost/command。
  • 如果省略 callbackUrl,OpenClaw 会推导为 http://<gateway.customBindHost or localhost>:<gateway.port, default 18789><callbackPath>。通配符绑定主机(0.0.0.0、::)会回退到 localhost。
  • 对于多账户设置,commands 可以在顶层设置,也可以在 channels.mattermost.accounts.<id>.commands 下设置(账户值会覆盖顶层字段)。
  • 由其他集成创建的具有相同触发词(trigger)的现有斜杠命令保持不动(注册时会跳过);机器人创建的命令会在回调 URL 漂移时更新或重新创建。
  • 命令回调会使用 OpenClaw 注册 oc_* 命令时由 Mattermost 返回的每个命令的令牌进行验证。
  • OpenClaw 在接受每个回调之前会刷新当前 Mattermost 命令注册状态,因此被删除或重新生成的斜杠命令产生的过期令牌会在无需重启网关的情况下停止被接受。
  • 如果 Mattermost API 无法确认该命令仍为当前命令,回调验证将失败关闭(fail closed);失败的验证会被短暂缓存,并发查询会被合并,并且每个命令的新查询启动会进行限速,以约束重放压力。
  • 当注册失败、启动不完整,或回调令牌与解析出的命令的已注册令牌不匹配时,斜杠回调会失败关闭(一个命令的有效令牌无法通过另一个命令的上游验证)。
  • 被接受的回调会以一条临时的“Processing...”回复进行确认;真正的答案会作为普通消息发送。
可访问性要求

回调端点必须能从 Mattermost 服务器访问。

  • 不要将 callbackUrl 设置为 localhost,除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中。
  • 不要将 callbackUrl 设置为你的 Mattermost 基础 URL,除非该 URL 将 /api/channels/mattermost/command 反向代理到 OpenClaw。
  • 快速检查方法是 curl https://<gateway-host>/api/channels/mattermost/command;GET 请求应从 OpenClaw 返回 405 Method Not Allowed,而不是 404。
Mattermost 出站允许列表

如果你的回调目标地址是私有/tailnet/内部地址,请将 Mattermost 的 ServiceSettings.AllowedUntrustedInternalConnections 设置为包含回调主机/域名。

使用主机/域名条目,而不是完整 URL。

  • 正确:gateway.tailnet-name.ts.net
  • 错误:https://gateway.tailnet-name.ts.net

环境变量(默认账户)

如果你更倾向于使用环境变量,请在网关主机上设置以下变量:

  • MATTERMOST_BOT_TOKEN=...
  • MATTERMOST_URL=https://chat.example.com

Note

环境变量仅适用于默认账户(default)。其他账户必须使用配置值。

MATTERMOST_URL 不能从工作区的 .env 文件设置;请参阅工作区 .env 文件。

聊天模式

Mattermost 会自动响应私信(DM)。频道行为由 chatmode 控制:

仅在频道中被 @提及 时响应。

响应频道中的每条消息。

当消息以触发前缀开头时响应。

配置示例:

{
  channels: {
    mattermost: {
      chatmode: "onchar",
      oncharPrefixes: [">", "!"], // default
    },
  },
}

说明:

  • onchar 仍然响应显式 @提及。
  • channels.mattermost.requireMention 仍会被遵循,但优先使用 chatmode。每个频道的 groups.<channelId>.requireMention 设置优先于两者。
  • 当机器人在频道线程中发送可见回复后,同一线程中的后续消息无需新的 @提及或 onchar 前缀即可得到回复,因此多轮线程对话可以持续进行。参与状态会在机器人最后一次在该线程中回复后的 7 天内被记住,并在网关重启后保留。机器人仅观察过的线程不受影响;如需再次要求显式提及,请开始一条新的顶级消息。
  • 设置 channels.mattermost.implicitMentions.threadParticipation: false 可阻止已参与线程的后续消息绕过提及门控。账户覆盖使用 channels.mattermost.accounts.<id>.implicitMentions。Mattermost 不会生成 replyToBot 或 quotedBot 事实,因此这些标志在此处没有效果。

设置 channels.mattermost.requireMentionInBotThreads: false 可在根帖子由接收机器人发送的线程中,接受无需 @提及或 onchar 前缀的后续消息。将其设置为 true 可要求即使机器人已参与,也需在那里显式激活。省略该设置会保留上述行为。

账户设置会覆盖频道级值。对于单个频道,groups.<channelId>.requireMentionInBotThreads 会覆盖 groups["*"].requireMentionInBotThreads,然后才是账户值。OpenClaw 会通过 Mattermost 验证根帖子的作者和频道;不可用或已删除的根帖子会保留现有提及行为。发送者和频道限制仍然适用,顶级消息以及根帖子属于他人帖子的线程保持不变。

线程与会话

使用 channels.mattermost.replyToMode 控制频道和群组回复是保留在主频道中,还是在触发帖子下开启线程。

  • off(默认):仅当入站帖子已在某个线程中时,才在线程中回复。
  • first:对于顶级频道/群组帖子,在该帖子下开启线程,并将对话路由到线程作用域会话。
  • all 和 batched:在 Mattermost 中与 first 行为相同,因为一旦 Mattermost 拥有线程根,后续分块和媒体将继续在同一线程中。
  • 即使设置了 replyToMode,私信也默认为 off。

使用 channels.mattermost.replyToModeByChatType 覆盖 direct、group 或 channel 聊天的模式。设置 direct 可使私信启用线程:

  • off(默认):私信保持非线程化,位于一个滚动会话中。
  • first、all 或 batched:每条顶级私信都会开启一个由全新独立会话支持的 Mattermost 线程。
{
  channels: {
    mattermost: {
      replyToMode: "all",
      replyToModeByChatType: {
        direct: "first",
      },
    },
  },
}

说明:

  • 线程作用域会话使用触发帖子 ID 作为线程根。
  • first 和 all 等效,因为一旦 Mattermost 拥有线程根,后续分块和媒体将继续在同一线程中。
  • 按聊天类型的覆盖优先于 replyToMode。如果没有 direct 覆盖,现有部署将保持扁平、非线程化的私信。
  • 在重启或会话重置后,当线程作用域对话的待处理历史处于冷状态时,会从 Mattermost 恢复最近消息。这包括已启用线程的私信;扁平私信保持不变。恢复过程会尊重发送者访问权限和上下文可见性,排除触发消息,并受 historyLimit、200 条帖子的服务器窗口以及五秒截止时间限制。临时服务器故障不会无限期阻塞新消息。

访问控制(私信)

  • 默认:channels.mattermost.dmPolicy = "pairing"(未知发送者会收到配对码)。其他值:allowlist、open、disabled。
  • 通过以下方式批准:
  • openclaw pairing list mattermost
  • openclaw pairing approve mattermost <CODE>
  • 公开私信:channels.mattermost.dmPolicy="open" 加上 channels.mattermost.allowFrom=["*"](配置模式强制使用通配符)。
  • channels.mattermost.allowFrom 接受用户 ID(推荐)和 accessGroup:<name> 条目。参见 访问组。

频道(群组)

  • 默认:channels.mattermost.groupPolicy = "allowlist"(提及门控)。
  • 使用 channels.mattermost.groupAllowFrom 配置允许列表中的发送者(推荐用户 ID)。
  • channels.mattermost.groupAllowFrom 接受 accessGroup:<name> 条目。参见 访问组。
  • 每个频道的提及覆盖位于 channels.mattermost.groups.<channelId>.requireMention 或 channels.mattermost.groups["*"].requireMention 作为默认值。
  • 文本命令可以跟在提及之后:当 commands.text 启用(默认)时,@<bot-username> /new 会执行 /new。Mattermost 本身会将单独的 /new 作为 Mattermost 斜杠命令执行,而不是发布它。
  • @username 匹配是可变的,并且仅在 channels.mattermost.dangerouslyAllowNameMatching: true 时启用。
  • 开放频道:channels.mattermost.groupPolicy="open"(提及门控)。
  • 解析顺序:channels.mattermost.groupPolicy,然后 channels.defaults.groupPolicy,然后 "allowlist"。
  • 运行时说明:如果 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> 按 ID 的频道
目标 投递到
channel:<name> 或 #channel-name 按名称查找频道,会在机器人所属的团队中搜索
user:<id> 或 mattermost:<id> 与该用户私聊
@username 私聊(通过 Mattermost API 解析用户名)

出站发送每条消息最多支持一个附件;请将多个文件拆分为单独发送。

设置 channels.mattermost.mediaMaxMb 以 MiB 为单位限制每个入站下载和出站附件。accounts.<id>.mediaMaxMb 覆盖频道根配置,然后 agents.defaults.mediaMaxMb 提供回退值。未配置任何上限时,入站下载保留其 8 MiB 默认值,出站媒体保留共享加载器默认值。出站图片可能会被优化。配置上限后,下载或上传失败会导致发送失败,而不是发布未检查的原始 URL。未配置上限时,现有 URL 回退仍然可用。

Warning

裸 ID(如 64ifufp...)在 Mattermost 中是有歧义的(用户 ID 与频道 ID)。

OpenClaw 会优先按用户解析它们:

  • 如果该 ID 作为用户存在(GET /api/v4/users/<id> 成功),OpenClaw 会通过 /api/v4/channels/direct 解析直接频道并发送私聊。
  • 否则,该 ID 会被视为频道 ID。

如果需要确定性行为,请始终使用显式前缀(user:<id> / channel:<id>)。

DM 频道重试

当 OpenClaw 向 Mattermost DM 目标发送消息,并且需要先解析直接频道时,默认会重试瞬时的直接频道创建失败。

使用 channels.mattermost.dmChannelRetry 全局调整 Mattermost 插件的该行为,或使用 channels.mattermost.accounts.<id>.dmChannelRetry 针对单个账号调整。默认值:

{
  channels: {
    mattermost: {
      dmChannelRetry: {
        maxRetries: 3,
        initialDelayMs: 1000,
        maxDelayMs: 10000,
        timeoutMs: 30000,
      },
    },
  },
}

说明:

  • 这仅适用于 DM 频道创建(/api/v4/channels/direct),不适用于所有 Mattermost API 调用。
  • 重试使用带抖动的指数退避,并适用于速率限制、5xx 响应以及网络或超时错误等瞬时故障。
  • 除 429 外的 4xx 客户端错误被视为永久性错误,不会重试。

预览流式传输

Mattermost 会将思考、工具活动和部分回复文本流式传输到草稿预览帖子中,当最终答案可以安全发送时,该帖子会就地定稿。在 partial 模式下,预览会在同一帖子 ID 上更新,而不是用按块消息刷屏频道。在 block 模式下,预览会在已完成文本和工具活动块之间轮换,因此较早的块会作为独立帖子保持可见,而不是被下一个块覆盖。媒体/错误最终结果会取消待处理的预览编辑,并使用正常投递,而不是刷出一个一次性预览帖子。

预览流式传输在 partial 模式下默认开启。通过 channels.mattermost.streaming.mode 配置(旧版标量/布尔 streaming 值会由 openclaw doctor --fix 迁移):

{
  channels: {
    mattermost: {
      streaming: { mode: "partial" }, // off | partial | block | progress
    },
  },
}
流式传输模式
  • partial(默认):一个预览帖子,随着回复增长而被编辑,然后以完整答案定稿。
  • block 在已完成文本和工具活动块之间轮换预览,因此每个块都会作为独立帖子保持可见,而不是就地覆盖。并行和连续的工具更新共享当前工具活动帖子。
  • progress 在生成期间显示状态预览,并仅在完成时发布最终答案。
  • off 禁用预览流式传输。当 streaming.block.enabled: true 时,已完成助手块仍会作为正常块回复(独立帖子)投递,而不是单个合并的最终帖子。
流式传输行为说明
  • 如果流无法就地定稿(例如帖子在流式传输中途被删除),OpenClaw 会回退到发送一个新的最终帖子,以确保回复不会丢失。
  • 清除计划会移除一个本应为空的预览;替换计划即使文本未变也会获得一个新预览。在回合完成时,旧预览删除失败会再尝试一次,而不会删除已定稿的回复。如果删除仍然失败,旧预览可能会保留;详细日志会包含清理失败信息。
  • 纯思考负载会从频道帖子中抑制,包括以 > Thinking 引用块形式到达的文本。设置 /reasoning on 可在其他界面查看思考;Mattermost 最终帖子仅保留答案。
  • 请参阅 流式传输 了解频道映射矩阵。

读取频道历史记录(message 工具)

使用 message action=read 或 CLI 读取已配置的 Mattermost 机器人可访问的频道中的帖子:

openclaw message read --channel mattermost --target channel:<channelId> --limit 5 --json
  • 结果遵循 Mattermost 的有序帖子列表,并包含规范化后的 timestampMs 和 timestampUtc 字段。
  • limit 默认为 60,并受 Mattermost 最大值 200 限制。分页请使用 before=<postId> 或 after=<postId>;这两个游标不能组合使用。
  • 直接操作员调用依赖 Mattermost 的频道成员身份和 read_channel 权限。提供商 403 仍然是正常的、可见的工具错误。
  • 允许当前账号对当前 Mattermost 对话进行委托读取。跨频道委托读取还要求目标频道 ID 位于 channels.mattermost.groups 下、存在 "*" 组条目,或 groupPolicy: "open"。跨账号和跨频道 DM 读取会失败关闭。
  • 历史记录读取默认禁用。设置 channels.mattermost.actions.messages: true 以启用。使用 channels.mattermost.accounts.<id>.actions.messages 按账号覆盖该设置。
  • 这些访问规则同时适用于捆绑插件和通过 npm 或 ClawHub 安装的官方插件。委托读取要求调用运行和插件注册保持活动状态。

表情反应(消息工具)

  • 使用 message action=react 并设置 channel=mattermost。
  • messageId 是 Mattermost 帖子 ID。
  • emoji 接受类似 thumbsup 或 :+1: 的名称(冒号可选)。
  • 设置 remove=true(布尔值)以移除表情反应。
  • 表情反应的添加/移除事件会作为系统事件转发到路由后的代理会话,并受与消息相同的 DM/群组策略检查约束。

示例:

message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup remove=true

配置:

  • channels.mattermost.actions.reactions:启用/禁用表情反应操作(默认 true)。
  • 按账户覆盖:channels.mattermost.accounts.<id>.actions.reactions。

交互式按钮(消息工具)

发送带有可点击按钮的消息。当用户点击按钮时,代理会接收该选择并可以响应。

按钮来自语义 presentation 载荷(在普通代理回复和 message action=send 中)。OpenClaw 会将值按钮渲染为 Mattermost 交互式按钮,保留 URL 按钮在消息文本中可见,并将选择菜单降级为可读文本。

ask_user 问题提供的选项也会渲染为按钮,点击其中一个会直接回答该问题。该问题仍可通过输入回答,而 Gateway 未索引的选项则保留在正文中:即“其他…”选项,以及任何提出多个问题、问题为多选、机密,或没有提供两到四个不同选项的提示。其他所有类型的展示操作(command、callback、approval)在 Mattermost 上保持为可读文本,而不是变成按钮:因为这里的点击会作为消息到达代理,而不是执行该操作,所以控件会做出与其说明不同的操作。

message action=send channel=mattermost target=channel:<channelId> presentation={"blocks":[{"type":"buttons","buttons":[{"label":"Yes","value":"yes"},{"label":"No","value":"no"}]}]}

展示按钮字段:

label string (路径) 必填
显示标签(别名:text)。
value string (路径)
点击时回传的值,用作操作 ID(别名:callback_data、callbackData)。对于可点击按钮,除非设置了 url,否则必填。
url string (路径)
链接按钮;在消息正文中渲染为 label: url 文本,而不是交互式按钮。
style "primary" | "secondary" | "success" | "danger" (路径)
按钮样式。Mattermost 会对其不支持的值应用默认样式。

要在代理系统提示中声明支持按钮,请将 inlineButtons 添加到渠道能力中:

{
  channels: {
    mattermost: {
      capabilities: ["inlineButtons"],
    },
  },
}

当用户点击按钮时:

1. 访问检查

点击者必须通过与消息发送者相同的 DM/群组策略检查;未授权的点击会收到临时通知并被忽略。

2. 按钮替换为确认信息

所有按钮都会被替换为一行确认信息(例如:“✓ Yes 由 @user 选择”)。

3. 代理接收选择

代理会将该选择作为入站消息(外加一个系统事件)接收并作出响应。

实现说明
  • 按钮回调使用 HMAC-SHA256 验证(自动完成,无需配置)。
  • 点击时会替换整个附件块,因此所有按钮会一起移除——无法部分移除。
  • 包含连字符或下划线的操作 ID 会自动清理(Mattermost 路由限制)。
  • 如果点击的 action_id 与原始帖子上的某个操作不匹配,会以 403("Unknown action")拒绝。
配置与可达性
  • channels.mattermost.capabilities:能力字符串数组。添加 "inlineButtons" 可在代理系统提示中启用按钮工具描述。
  • channels.mattermost.interactions.callbackBaseUrl:按钮回调的可选外部基础 URL(例如 https://gateway.example.com)。当 Mattermost 无法直接通过其绑定主机访问网关时使用此设置。
  • 在多账户配置中,也可以在 channels.mattermost.accounts.<id>.interactions.callbackBaseUrl 下设置相同字段。
  • 如果省略 interactions.callbackBaseUrl,OpenClaw 会从 gateway.customBindHost + gateway.port(默认 18789)推导回调 URL,然后回退到 http://localhost:<port>。回调路径为 /mattermost/interactions/<accountId>。
  • 可达性规则:按钮回调 URL 必须能从 Mattermost 服务器访问。localhost 仅在 Mattermost 和 OpenClaw 运行在同一主机/网络命名空间时有效。
  • channels.mattermost.interactions.allowedSourceIps:按钮回调的源 IP 允许列表。未设置时,仅接受回环源(127.0.0.1、::1),因此远程 Mattermost 服务器必须在此加入允许列表,否则其点击会以 403 被拒绝。在反向代理后面时,还应设置 gateway.trustedProxies,以便从转发头中推导真实客户端 IP。
  • 如果你的回调目标是私有/Tailnet/内部网络,请将其主机/域名添加到 Mattermost 的 ServiceSettings.AllowedUntrustedInternalConnections。

直接 API 集成(外部脚本)

外部脚本和 Webhook 可以直接通过 Mattermost REST API 发布按钮,而不经过代理的 message 工具。优先使用 OpenClaw 的 message 工具。对于直接集成,请从 @openclaw/mattermost/api.js 导入 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
                action: "approve",
                // ... any custom fields ...
                _token: "<hmac>", // see HMAC section below
              },
            },
          },
        ],
      },
    ],
  },
}

Warning

关键规则

  1. 附件应放在 props.attachments 中,而不是顶层 attachments(会被静默忽略)。
  2. 每个操作都需要 type: "button" —— 缺少它时,点击会被静默吞掉。
  3. 每个操作都需要一个 id 字段 —— Mattermost 会忽略没有 ID 的操作。
  4. 操作 id 必须仅包含字母数字([a-zA-Z0-9])。连字符和下划线会破坏 Mattermost 的服务端操作路由(返回 404)。使用前请移除它们。
  5. context.action_id 必须与按钮的 id 匹配;网关会拒绝 action_id 在帖子中不存在的点击。
  6. context.action_id 是必填项 —— 交互处理器在缺少它时会返回 400。
  7. 回调源 IP 必须被允许(见上文 interactions.allowedSourceIps)。

HMAC 令牌生成

网关使用 HMAC-SHA256 验证按钮点击。外部脚本必须生成与网关验证逻辑匹配的令牌:

1. 从 bot token 派生密钥

HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken),十六进制编码。

2. 构建 context 对象

构建 context 对象,包含除 _token 之外的所有字段。

3. 使用排序后的键进行序列化

使用递归排序的键和无空格进行序列化(网关也会规范化嵌套对象并生成紧凑 JSON)。

4. 对 payload 签名

HMAC-SHA256(key=secret, data=serializedContext)

5. 添加令牌

将生成的十六进制摘要作为 _token 添加到 context 中。

Python 示例:

import hmac, hashlib, json

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"})。
  • 始终对 所有 context 字段签名(不包括 _token)。网关会先移除 _token,然后对剩余所有内容签名。只对子集签名会导致静默验证失败。
  • 使用 sort_keys=True —— 网关在签名前会排序键,并且 Mattermost 在存储 payload 时可能会重新排序 context 字段。
  • 从 bot token(确定性)派生密钥,而不是使用随机字节。创建按钮的进程和进行验证的网关必须使用相同的密钥。

目录适配器

Mattermost 插件包含一个目录适配器,可通过 Mattermost API 解析频道名和用户名。这使得 openclaw message send 以及 cron/webhook 投递支持 #channel-name 和 @username 目标。

无需配置 —— 适配器会使用账户配置中的 bot token。

多账户

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" },
      },
    },
  },
}

账户值会覆盖顶层字段;channels.mattermost.defaultAccount 用于在未指定账户时选择使用哪个账户。

故障排查

频道中没有回复

确保 bot 已加入频道并提及它(oncall),使用触发前缀(onchar),或设置 chatmode: "onmessage"。

认证或多账户错误
  • 检查 bot token、base URL 以及账户是否已启用。
  • 多账户问题:环境变量仅适用于 default 账户。
  • 私有/LAN Mattermost 主机需要 network.dangerouslyAllowPrivateNetwork: true(SSRF 防护默认会阻止私有 IP)。
原生斜杠命令失败
  • Unauthorized: invalid command token.:OpenClaw 未接受回调令牌。常见原因:
  • 斜杠命令注册失败,或启动时仅部分完成
  • 回调访问了错误的网关/账户
  • Mattermost 中仍保留指向先前回调目标的旧命令
  • 网关重启后未重新激活斜杠命令
  • 负载下出现 HTTP 429:使用出站 OAuth 连接或会移除 Authorization 头的代理的回调,仅在请求体中携带命令令牌。它们共享有界的匿名请求池,当请求池饱和时可能被限流。请通过代理保留 Mattermost 原始的 Authorization: Token 头,以便已识别的命令凭据获得独立容量。
  • 如果原生斜杠命令停止工作,请检查日志中是否有 mattermost: failed to register slash commands 或 mattermost: native slash commands enabled but no commands could be registered。
  • 如果省略 callbackUrl,且日志警告回调解析为回环 URL(例如 http://localhost:18789/...),则该 URL 可能仅在 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间时才可访问。请改为设置一个明确的外部可达 commands.callbackUrl。
按钮问题
  • 按钮显示为白色方框或完全不显示:按钮数据格式错误。每个 presentation 按钮都需要 label 和 value(缺少任一者的按钮会被丢弃)。
  • 按钮已渲染但点击无反应:请确认网关可从 Mattermost 服务器访问,Mattermost 服务器 IP 已包含在 channels.mattermost.interactions.allowedSourceIps 中(未配置时仅接受回环地址),并且 ServiceSettings.AllowedUntrustedInternalConnections 对私有目标包含回调主机。
  • 点击按钮返回 404:按钮 id 可能包含连字符或下划线。Mattermost 的操作路由器无法处理非字母数字 ID。请仅使用 [a-zA-Z0-9]。
  • 网关记录 rejected callback source:点击来自 interactions.allowedSourceIps 之外的 IP。请将 Mattermost 服务器或你的入口加入允许列表,并在反向代理后设置 gateway.trustedProxies。
  • 网关记录 invalid _token:HMAC 不匹配。请检查是否对所有 context 字段(而非子集)签名,是否使用排序后的键,以及是否使用紧凑 JSON(无空格)。参见上文 HMAC 部分。
  • 网关记录 missing _token in context:按钮的 context 中缺少 _token 字段。构建集成 payload 时请确保包含该字段。
  • 网关以 Unknown action 拒绝点击:context.action_id 与帖子上的任何操作 id 都不匹配。请将两者设置为相同的规范化值。
  • Agent 不提供按钮:请在 Mattermost 频道配置中添加 capabilities: ["inlineButtons"]。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw