概述
Mattermost 是 fries-mac 与用户通信的主要平台(235条消息)。配置涉及服务器地址设置、Bot 账号绑定、文件发送功能、会话管理等方面。服务器部署在 mm.dora.restry.cn。
关键事件
- 2026-03-03: 修复 Mattermost 服务器地址错误(应为 mm.dora.restry.cn)
- 2026-03-03: 要求将配置信息准确记录,避免反复出错
- 2026-03-07: 在 tiger-host 上安装 Supabase(参考官方 Docker 文档)
- 2026-03-10: 处理
/compact、/new、/reset等命令 - 2026-03-17: 新建会话,切换模型到 claude-opus-4.6
- 2026-04-04: 持续进行配置维护和更新
2026-05-10 OpenClaw 在 MM 的 block streaming 协议(cspy MM client 修复实证)
wechat-bot-tickets cspy MM client 5-10 流式聚合 bug 才搞清的事实,沉淀给所有写「等 OpenClaw bot 在 MM 出完整 reply」逻辑的代码:
OpenClaw 文档 https://openclaw.ai/concepts/streaming + /channels/mattermost:
- Block streaming,不是 token-delta,不是 edit 同条 post:assistant 流式输出按 block flush 成多条独立 channel 消息。在 MM 上表现为发 N 条 post,全部
create_at同一毫秒,前 N-1 条message=""空 post,只有最后 1 条有真实内容;流式中每条又会被 edit 多次(edit_at持续若干秒后稳定)。 - Coalescing:
blockStreamingCoalesce.idleMs/minChars/maxChars,模型 idle 即 flush。idleMs是「流式结束」的唯一信号(不是done事件)。 - MM channel 默认行为:
channels.mattermost.streaming默认off,只发 final reply;设streaming.mode: "block"才走多消息模式。
正确的「等完整 reply」算法(实证 from cspy commit 58befa2):
- 整 channel 维度跟
max(update_at),任何 post 的 update 都算「还在动」 - 静默窗口 30s(远大于默认 idleMs)才认定流式结束
- final reply = 按
update_at倒序找第一个trim().length > 0的 post - timeout 兜底:deadline 到了仍 pickFinal,找到就 return ok(标
viaTimeout)
反模式:抓「第一条 message 非空的 post 立即 return」会把回复截断到几十字符(前面那条空 post 被绕过后,第一个 chunk 是开头几行就 return,后面真正长文那条根本没等)。
2026-05-11 MM WebSocket 客户端事件实测(cspy WS 架构升级)
5-11 用 cspy 真 token 直连 mm.cn.restry.cn WS 抓 90 秒事件流(wechat-bot-tickets WS 后端 + SSE typing UI 上线),坐实 OpenClaw bot 在 MM 上的 raw 行为:
[T=0.0s] 发出消息
[T=8.7s] ⌨️ event=typing user=nexora-mazu ← 输入状态
[T=10.7s] ⌨️ event=typing user=nexora-mazu ← 心跳(每 ~2s 续期)
[T=13.8s] 📝 event=posted ← post 内容是 JSON 字符串,需 JSON.parse(data.post)
[T=...] 📝 event=post_edited 多次 → edit_at 持续变直到稳定
写 MM WS 客户端的稳定算法(cspy lib/mm/ws-client.ts 实证):
- lazy connect + 单例:多 listener 共享同一 socket
- 重连指数退避 1s → 30s + 抖动;auth 用
seq_reply.status判断成功 - 过滤
broadcast.channel_id防跨 channel 串台 - subscribe 必须先于 postMessage —— 否则 race 错过 typing/posted 事件
- 流式结束判定:typing 5s 不再来 + post 1.5s 不再变化双窗口;timeout 兜底 deadline 到了仍取最新有内容的 post(标
viaTimeout) - escape hatch:
MM_WS_DISABLE=1整个关掉 WS、MM_TRANSPORT=polling切回旧路径 - 测试注入:
__setWsFactory(...)注 mock socket
SSE 推前端:/api/mm/events 路由按 botMmUserId 解析对应 DM channel,把 ws-client 的事件流转 SSE,加 15s 心跳防 nginx/Caddy 切断。前端用 EventSource 接,typing 三点动画 + 流式追加。详见 wechat-bot-tickets 5-11 段。
2026-05-07 B2P 中国实例 mm.cn.restry.cn(azchina / MC_RG)
新增第二个 Mattermost 实例 mm.cn.restry.cn,部署在 Azure China(subscription = azchina,resource group MC_RG),目的是给 B2P 中国境内访问者提供低延迟通道(不走主站 mm.dora.restry.cn 出墙路径)。Docker compose 起 Mattermost + Postgres,反代走当地 caddy。
useraccesstokens 取 token 的坑
服务端建好 user / 启用 personal access token 后,Hermes 配置里需要的是 token 字段(实际 bearer),不是表里看到的 id。useraccesstokens 表的 id 是 token 的内部主键、token 才是实际请求 header 用的 Authorization: Bearer <token> 值。早期错把 id 当 token 配进去 → 401。
-- 正确取法
SELECT user_id, token FROM useraccesstokens WHERE user_id = '<bot user id>';
-- 把 token 列贴到 Hermes config / .env,不是 id 列双实例策略
mm.dora.restry.cn— 国际主站 (Azure 香港 / 公网),OAuth/SSO 接 Logto,长期沉淀mm.cn.restry.cn— 中国 B2P 入口,独立账号体系,不做 federation(避免 Azure China ↔ 国际跨境数据合规复杂度)- Bot 在两边各注册一份,配置
MM_*变量分实例区分
5-08 复核:mm.cn.restry.cn 解析到 198.18.1.2 不是 fake-DNS
5-07 排查 claw-bot 沉默时一度怀疑本机 fake-DNS(198.18.0.0/15 是 RFC 2544 benchmark 段,常见于 Clash/V2Ray)。5-08 用公共 DNS(8.8.8.8、223.5.5.5)交叉解析仍是 198.18.1.2,curl /api/v4/system/ping 200/88ms,13 个 bot WebSocket 全 ESTAB —— 确认是真实公网 A 记录(azchina anycast 落点),非伪造。后续判定 fake-DNS 前应先公共 DNS 比对 + 应用层 curl,不要看到 198.18.x 就下结论。真实根因详见 openclaw-config dmPolicy: open 必须显式 allowFrom: ["*"] 段。
5-07 claw-bot 上 Hermes Gateway 接 mm.cn.restry.cn + 13 个 agent bot 账号
Daddy 在 claw-bot (192.168.1.235) 上把本地 Hermes Agent 接入 mm.cn.restry.cn。流程:
- Mattermost → System Console → Bot Accounts 启用,建
hermesbot,token9w9yxggejtn7jy5yfce3919u6o - Hermes Gateway 用 systemd 跑,
MATTERMOST_ALLOWED_USERS=matter、回复模式 thread - 同时给 13 个 OpenClaw agent 各建一个同名 MM bot 账号(
nexora-ops/nexora-pyerp/nexora-xipu/nexora-mazu/nexora-laiya等),但 Hermes Gateway 只能绑一个 bot token → 其它 bot 账号「有壳无魂」,发消息没人接。删掉了 4 个无对应 agent 的旧 bot:nexora-fe/nexora-be/nexora-qa/serverops(curl 频繁请求会被限流,prism-pm/prism-ui一次没删成功)。 - 方向决定(Daddy 5-07 10:07):要让 OpenClaw agent 也能被 MM 直接 @,必须在 OpenClaw 侧
channels.mattermost.accounts里把这些 bot 一一绑上,不在 Hermes 里绑。Hermes 这台只是接hermes这一个独立 agent 入口。
System admin token(azchina 实例):b4qoah9j63y8irq3cde1xoq96a,可用于 admin API 列 bots / 删 bot。
技术要点
- 服务器地址: mm.dora.restry.cn
- Bot Token: 通过 OpenClaw 网关配置
- 文件发送: 需要通过 Mattermost API 上传附件
- 会话管理: 支持
/compact(压缩上下文)、/new(新会话)、/reset(重置)
经验教训
- 服务器地址等关键配置必须准确记录到记忆中
- Bot 配置变更后需要重启 Gateway 才能生效
/compact命令可用于压缩上下文窗口,避免 token 超限- 文件发送功能需要正确调用 API,不能仅输出文件路径
相关主题
- openclaw-config
- file-sending
- caddy-reverse-proxy
- gatewaybot
- dev-port-management — 3000系/4000系端口分配方案
Bot 开发端口约定
以下信息来源于 gatewaybot 的 Mattermost DM 聊天记录(2026-03-18)。
各项目 Bot 开发时的本地端口分配:
| 项目 | 前端端口 | 后端端口 | 备注 |
|---|---|---|---|
| Clawline Gateway | 3020 | 3021 | 不使用 18800~18890 区间 |
用户明确要求不使用 18800~18890 区间端口,改用 3000 区间。开发站点通过 Caddy 反向代理暴露为 HTTPS(如 gw.dev.dora.restry.cn)。
注意事项:
- Vite dev server 需要配置
server.allowedHosts以允许域名访问 crypto.randomUUID()在非 HTTPS 环境下不可用,需用crypto.getRandomValues()作为 fallback
Prism Bot 频道配置
以下信息来源于 bnef 的 Mattermost DM 聊天记录(2026-03-13)。
Prism 项目使用了 3 个 Mattermost 频道:
- prism-general — 通用讨论和日报发布
- prism-dev — 开发讨论
- prism-standup — 每日站会自动推送
5 个 Bot 账号的 Mattermost 配置(在 openclaw.json 的 channels.mattermost.accounts 中):
| Bot | dmPolicy | chatmode | 群消息触发 |
|---|---|---|---|
| prism-pm | open | onchar(前缀 pm) | pm 开头 或 @prism-pm |
| prism-arch | open | oncall | @prism-arch |
| prism-data | open | oncall | @prism-data |
| prism-ui | open | oncall | @prism-ui |
| prism-docs | open | oncall | @prism-docs |
默认账号配置:dmPolicy: "pairing", groupPolicy: "open", allowFrom: ["*"]。
Mattermost 服务器迁移(2026-03-15)
以下信息来源于 work_assistant 的 Mattermost DM 聊天记录。
原 Mattermost 服务器 mm.dora.restry.cn 运行在本地。为 Prism 项目创建了独立的新实例:
| 步骤 | 内容 |
|---|---|
| VM 准备 | transparent-n3 → 重建为 mattermost-server(保留磁盘+网卡) |
| DNS | mattermost-server.chinanorth3.cloudapp.chinacloudapi.cn |
| 镜像 | 推送至 northacr.azurecr.cn(Azure China 北区,免密 pull) |
| 部署 | Docker Compose: Mattermost + PostgreSQL + Caddy(HTTPS 自动证书) |
| Bot 迁移 | 5 个 prism- bot 在新服务器上创建并转为 bot 账号,生成 access token |
| OpenClaw 更新 | Eagle 服务器 openclaw.json 的 baseUrl 和 token 切换到新服务器 |
| 清理 | 旧服务器上停用 9 个用户 + 删除 3 个 prism 频道 |
Bot 死循环事件
新服务器上线后立即出现 Bot 互 @ 死循环——一个 Bot 回复时 @ 了另一个 Bot,触发连锁响应。
修复方案:
- 配置层:
groupAllowFrom仅允许人类用户 ID 触发(allowlist 模式) - 人设层:所有 Agent SOUL.md 明确禁止主动 @ Bot
- PM Bot 保持群聊全响应,其他 4 个 Bot 仅响应 allowlist 中的真人 @提及
注意:
ignoreBots是编造的不存在字段,正确方式为groupPolicy: "allowlist"+groupAllowFrom
相关主题
- openclaw-config
- file-sending
- caddy-reverse-proxy
- bnef — BNEF Bot Mattermost 频道配置
- work-assistant — 执行迁移操作的代理
- prism-bots — 被迁移的 Bot 集群
- mm-bots — Bot 清单