Skip to content
站长自营API 中转

代理和中转可以分开处理

网络代理解决连接问题,ZZSwitch 更适合统一 Base URL、Key、余额和多模型路由。

站长自营API 中转

正在配置代理或 API 中转?可以把模型接口统一到一个网关里

系统代理负责让客户端连得上,API 中转负责统一 Base URL、Key、余额和多模型路由。ZZSwitch 是我自己运营的统一 API 网关,适合 OpenCode / Claude Code / Codex 等工具接入。

自托管 Mattermost 接入 OpenClaw 时,机器人在频道里不回复、斜杠命令返回 invalid command token 或交互按钮点击无反应是常见问题。先检查 botTokenbaseUrl 是否匹配,chatmode 是否设为 oncall(需 @mention),以及 Mattermost 服务端的 AllowedUntrustedInternalConnections 是否包含回调地址。按钮 HMAC 签名失败时,用 sort_keys=Trueseparators=(",",":") 生成紧凑 JSON。

Mattermost 接入 OpenClaw:Bot Token 配置与故障排除

Mattermost 是一个自托管的团队消息平台;支持频道、群组和私信。OpenClaw 通过插件(Bot Token + WebSocket 事件)接入手动 Mattermost 实例。

安装插件

当前正式版 OpenClaw 已内置 Mattermost 插件。旧版或自定义构建需要手动安装:

npm registry

```bash
openclaw plugins install @openclaw/mattermost
```

本地代码仓库

```bash
openclaw plugins install ./path/to/local/mattermost-plugin
```

详见:插件说明

快速配置

  1. 确认插件已可用(当前正式版已捆绑)。
  2. 在 Mattermost 中创建机器人账号,复制 Bot Token
  3. 复制 Mattermost 的 Base URL(例如 https://chat.example.com)。
  4. 最小配置示例:
json5
{
  channels: {
    mattermost: {
      enabled: true,
      botToken: "mm-token",
      baseUrl: "https://chat.example.com",
      dmPolicy: "pairing",
    },
  },
}

聊天模式

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

  • oncall(默认):只在频道中被 @提及时响应。
  • onmessage:响应每条频道消息。
  • onchar:消息以触发前缀开头时响应。
json5
{
  channels: {
    mattermost: {
      chatmode: "onchar",
      oncharPrefixes: [">", "!"],
    },
  },
}

onchar 模式下,显式 @提及仍有效。旧版 requireMention 配置仍被支持,但建议优先使用 chatmode

线程与会话

使用 replyToMode 控制频道和群组回复是在主频道中,还是在触发帖子下新建线程。

  • off(默认):只有当入站帖子本身在线程中时,才在线程中回复。
  • first:对顶层频道/群组帖子,在该帖子下新建线程,并将对话路由到线程作用域的会话。
  • all:当前与 first 行为相同。
json5
{
  channels: {
    mattermost: {
      replyToMode: "all",
    },
  },
}

线程作用域会话以触发帖子 ID 为线程根。私信忽略此设置。

原生斜杠命令

可选功能。启用后,OpenClaw 通过 Mattermost API 注册 oc_* 斜杠命令,并在 Gateway HTTP 服务器上接收回调 POST。

json5
{
  channels: {
    mattermost: {
      commands: {
        native: true,
        nativeSkills: true,
        callbackPath: "/api/channels/mattermost/command",
        // 当 Mattermost 无法直接访问 Gateway 时使用反向代理/公网 URL
        callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
      },
    },
  },
}

注意事项:

  • native: "auto" 默认禁用。设置 native: true 才启用。
  • 省略 callbackUrl 时,OpenClaw 自动从 Gateway 主机/端口 + callbackPath 推导。
  • 多账号时,commands 可在顶层或 channels.mattermost.accounts.<id>.commands 下设置(账号级值覆盖顶层)。
  • 回调验证使用 Mattermost 注册时返回的每命令 Token。注册失败、部分启动或 Token 不匹配时,斜杠回调安全关闭。
  • 回调端点必须可从 Mattermost 服务器访问。callbackUrl 不要设为 localhost,除非两者在同一主机/网络命名空间。
  • 快速检测:curl https://<gateway-host>/api/channels/mattermost/command 应返回 405(而非 404)。

Mattermost 出站白名单:如果回调目标是私有/Tailnet/内部地址,在 ServiceSettings.AllowedUntrustedInternalConnections 中添加主机/域名(非完整 URL)。
正确:gateway.tailnet-name.ts.net
错误:https://gateway.tailnet-name.ts.net

环境变量(默认账号)

设置以下环境变量作用于默认账号(default):

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

环境变量仅对 default 账号生效,其他账号必须在配置中明确填写。

访问控制(私信)

  • 默认 dmPolicy: "pairing":未知发送者收到配对码。
  • 审批方式:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • 开放私信:dmPolicy="open" 加上 allowFrom=["*"]allowFrom 也支持 accessGroup:&lt;name&gt;

频道(群组)

  • 默认 groupPolicy: "allowlist"(需 @提及)。
  • 白名单发送者用 groupAllowFrom(推荐用户 ID)。
  • 每频道提及覆盖在 groups.<channelId>.requireMentiongroups["*"].requireMention 下设置。
  • @username 匹配只在 dangerouslyAllowNameMatching: true 时启用。
  • 开放频道:groupPolicy="open"(仍需 @提及)。
  • 运行时注意:channels.mattermost 完全缺失时,群组检查回退到 groupPolicy="allowlist"(即使 channels.defaults.groupPolicy 已设置)。

示例:

json5
{
  channels: {
    mattermost: {
      groupPolicy: "open",
      groups: {
        "*": { requireMention: true },
        "team-channel-id": { requireMention: false },
      },
    },
  },
}

出站消息目标格式

openclaw message send 或 Cron/Webhook 中使用:

  • channel:&lt;id&gt;:发送到频道
  • user:&lt;id&gt;:发送私信
  • @username:发送私信(通过 API 解析)

裸 ID(如 64ifufp...)存在歧义:OpenClaw 按用户优先解析——如果 ID 是有效用户,则发送私信;否则视为频道 ID。如需确定性,始终使用前缀。

私信频道重试

OpenClaw 发送 DM 时,创建直接频道(/api/v4/channels/direct)的瞬时失败默认会重试。可通过 dmChannelRetry 调整:

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

仅重试速率限制、5xx、网络/超时错误;4xx 除 429 外视为永久错误,不重试。

预览流式(Preview streaming)

Mattermost 支持流式生成回复,在同一个草稿预览帖中逐步更新,最终在安全发送时定稿。配置 streaming 模式:

json5
{
  channels: {
    mattermost: {
      streaming: "partial", // off | partial | block | progress
    },
  },
}
  • partial(推荐):一个预览帖,随着回复增长编辑,最后定稿。
  • block:在预览帖内使用追加式草稿。
  • progress:生成时显示状态预览,完成后再发最终回复。
  • off:禁用。

如果流式无法定稿(如帖子被删除),OpenClaw 会发送一份新回复。思考块(> Thinking)不会出现在频道帖子中;启用 /reasoning on 可在其他界面看到。

表情回应(消息工具)

  • message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup
  • emoji 接受 thumbsup:+1:(冒号可选)。
  • remove=true 移除回应。
  • 配置:channels.mattermost.actions.reactions(默认 true),可每账号覆盖。

交互式按钮(消息工具)

启用按钮需在 capabilities 中添加 "inlineButtons"

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

发送带按钮的消息:

message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]

按钮字段:

  • text(必填):显示标签
  • callback_data(必填):点击时回传的值(用作 action ID)
  • style(可选):"default""primary""danger"

点击按钮后,所有按钮替换为确认行,智能体收到选择并响应。

配置和可达性:

  • channels.mattermost.interactions.callbackBaseUrl:可选外部 URL,当 Mattermost 无法直接访问 Gateway 时使用。
  • 多账号可在 accounts.&lt;id&gt;.interactions.callbackBaseUrl 设置。
  • 省略时从 gateway.customBindHost + port 推导,回退到 http://localhost:&lt;port&gt;
  • 回调 URL 必须可达;localhost 只在同主机/网络命名空间时有效。
  • 内部/tailnet 地址需在 Mattermost 的 AllowedUntrustedInternalConnections 中添加主机/域名。

直接 API 集成(外部脚本)

外部脚本可通过 Mattermost REST API 直接发送按钮。载荷必须放在 props.attachments[].actions[] 中。

关键规则:

  1. attachments 必须在 props 下,而非顶层。
  2. 每个 action 需要 type: "button",否则点击被静默忽略。
  3. 每个 action 需要 id(仅字母数字 [a-zA-Z0-9]),否则 Mattermost 返回 404。
  4. context.action_id 必须与 id 一致,否则确认消息显示原始 ID。
  5. 缺少 context.action_id 时,交互处理器返回 400。

HMAC 签名生成:

  1. 从 Bot Token 推导密钥:HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
  2. 构建 context(不含 _token),使用 key 排序的紧凑 JSON。
  3. 用密钥签名,得到 hex digest 作为 _token

Python 示例:

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 默认加空格,使用 separators=(",", ":")
  • 签名所有 context 字段(减去 _token)。
  • 使用 sort_keys=True,因为 Gateway 和 Mattermost 都可能重排字段。

目录适配器

插件内置目录适配器,通过 Bot Token 解析 #channel-name@username。无需单独配置。

多账号

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

环境变量只作用于 default 账号。

常见问题

机器人在 Mattermost 频道里不回复

确认 chatmode 是否设置(默认 oncall 需要 @提及)。检查 Bot Token 和 Base URL 是否正确,以及机器人账号是否已加入该频道。如果使用 onchar,确保触发前缀正确。

斜杠命令返回 invalid command token

常见原因:启动时注册失败、Mattermost 仍指向旧的回调目标、Gateway 重启后未重新激活命令。检查日志中 mattermost: failed to register slash commands。如果省略 callbackUrl 且日志显示 http://127.0.0.1:18789/...,设置显式的外部 URL。

交互按钮点击后无反应或显示白框

确认按钮数据包含 textcallback_data。验证 Mattermost 服务端 ServiceSettingsEnablePostActionIntegrationtrueAllowedUntrustedInternalConnections 包含回调地址。按钮 id 只能包含字母数字([a-zA-Z0-9]),否则返回 404。如果 Gateway 日志报 invalid _token,检查 HMAC 签名是否正确。

相关文档

站长自营API 中转

ZZSwitch API 中转

统一 Base URL、Key 和余额。