看懂 Mattermost:频道、帖子、Thread、私聊,以及它和 Slack/飞书哪里不一样
第一次从飞书切到 Mattermost,最容易卡住的不是“怎么发消息”,而是:我现在到底站在哪一层?这是一个频道、一条帖子、一个 thread,还是一次私聊?
这篇文章专门回答这个问题。我们不讲部署,不讲数据库,也不讲 token;只把 Mattermost 的信息结构、发帖机制、thread 语义,以及它和 Slack、飞书在机器人触发上的差别讲清楚。
Mattermost 更像 Slack/Discord 式的 workspace/team -> channel -> post -> thread 模型,而不是飞书里“群聊/私聊 + 话题/卡片/文档”混在一起的组织入口。把 Agent 放进 Mattermost 时,推荐默认 UX 是:频道里 @hermes-agent,thread 里继续 @hermes-agent,私聊 DM 里不用 @。
ChatArch 当前维护的 Mattermost 公网入口是:
https://matter.public.wzhecnu.cn/
上一篇文章已经解释过为什么 Mattermost 适合承担 ChatArch 的自托管实时 Agent 工作间,以及 Hermes 如何通过 Mattermost Gateway 接入频道、thread 和 DM。[12] 本文只讨论使用模型和消息结构。
先把层级摆正
Mattermost 的基本结构可以先按五层理解:
Mattermost server / workspace
Team
Channel
Post
Thread replies
Direct Message / Group Message channel
Post
Thread replies
第一层是一个 Mattermost server,也就是你打开的站点。ChatArch 当前入口是 matter.public.wzhecnu.cn。
第二层是 Team。Mattermost 的用户文档把 team 当成协作空间来组织成员、频道和团队设置。[1] 对用户来说,team 通常就是左上角那个团队空间;对 Agent 来说,它是权限、成员关系和链接路径的一部分。
第三层是 Channel。Mattermost 的 channel 类型包括 public channel、private channel、direct message 和 group message;它不是只有“群聊频道”一种东西。[2] 这点很重要:DM 在 Mattermost 里本质上也是一种 channel,只是 UI 上表现为两个人的私聊。
第四层是 Post。你在频道里发的一条顶层消息,就是一个 post。Mattermost 文档把发消息、格式化、附件、草稿和发送行为都归在 message/post 这条线上。[5]
第五层是 Thread。当你回复某一条 post 时,Mattermost 会围绕那条 root post 组织一串 threaded discussions;官方文档把 threaded discussions 作为组织对话、保持频道主时间线干净的一种方式。[4] 所以 thread 不是一个新的频道,而是“围绕某条消息展开的一组回复”。
Channel 不是飞书群聊的简单替代
飞书里常见心智是:
群聊:很多人在一个聊天流里说话,@bot 才触发
私聊:你和 bot 一对一说话,不用 @
话题/文档/卡片:是同一个工作空间里的扩展对象
Mattermost 更强调 channel。一个 channel 可以是公开频道,也可以是私有频道;也可以是 direct message 或 group message 这种非公开会话。[2] 这会带来三个使用差异。
第一,频道天然适合按任务和领域拆分。比如 agent-lab 可以放 Agent 调试,chatrss-triggers 可以放事件触发,ops 可以放服务运维。Mattermost 文档也把 channel 作为协作的主要空间来组织成员、消息和上下文。[3]
第二,频道里的普通消息不一定应该被机器人读取。一个 Agent 如果监听所有频道消息,很快就会变成噪音放大器:别人只是闲聊,bot 却开始规划任务。因此 ChatArch 当前建议:普通频道里默认要显式 @hermes-agent。 Mattermost 自身也提供 mention 机制,让用户在消息中点名具体的人或对象。[7]
第三,频道主时间线应该保持干净。长任务、调试、代码输出、日志摘要都适合落到 thread 里,而不是把频道刷屏。Mattermost 的 threaded discussions 正是为这种“围绕一条消息展开上下文”的模式设计的。[4]
Post 和 Thread:Mattermost 里最关键的一对概念
如果只记一件事,请记这个:
post 是入口;thread 是上下文。
你在频道里发一条顶层消息:
@hermes-agent 帮我看一下 ChatRSS 现在在做什么。
这条消息就是 root post。Hermes 如果回复到这条消息下面,就形成一个 thread:
Channel: agent-lab
Post: @hermes-agent 帮我看一下 ChatRSS 现在在做什么
Thread:
hermes-agent: 我看到 ChatRSS 当前是 trigger-router-action framework...
用户: 能跑通吗?举个例子
hermes-agent: 可以,我开一个真实帖子并读回回复...
这和飞书群聊里“消息一直往下滚”的感觉不同。Mattermost 的 thread 让一次任务有一个明确的 root:
- 这个 thread 在讲哪件事;
- 谁触发了它;
- bot 的回复是否回到了同一个上下文;
- 后续追问是否仍然围绕同一件事。
Mattermost 官方文档也把 reply 作为对消息进行回应的动作,而 threaded discussions 用来组织这些回应。[4][6]
对 Agent 来说,这个结构尤其有用。因为 Agent run 往往不只是一问一答:它可能会查代码、跑命令、写文档、生成链接,再等待用户确认。把这些都塞进一个频道主时间线会很乱;放在 thread 里,任务边界就清楚了。
DM:私聊也是 channel,但触发心智应该像飞书私聊
用户最自然的期待是:
群聊里需要 @bot;私聊 bot 不需要 @。
这个期待是合理的。Mattermost 里 DM 技术上是 direct message channel,[2] 但产品心智上它就是“我正在和这个 bot 私聊”。所以 ChatArch 当前 Hermes/Mattermost 的目标 UX 是:
| 场景 | 是否需要 @ | 推荐回复位置 |
|---|---|---|
DM 私聊 hermes-agent | 不需要 | 当前实测会进入该 DM 消息的 thread |
| 频道顶层消息 | 需要 @hermes-agent | 回复到这条消息的 thread |
| 已有 channel thread | 建议继续 @hermes-agent | 回复同一个 thread |
| 普通频道里不 @ 的消息 | 不触发 | 避免误读频道聊天 |
我们在 ChatArch Mattermost 上已经做过一次真实验证:用普通调试账号与 hermes-agent 建立 DM channel,不带 @ 发送消息,bot 成功回复;随后在同一个 DM thread 里继续不带 @ 追问,也能继续回复。公开文章只记录这个行为结论,不记录账号、token、用户 ID 或任何私有路径。
这里有一个 UX 细节:当前 Hermes Mattermost reply mode 会把 DM 回复也挂进 thread。 也就是说,DM 不是像飞书私聊那样完全平铺成一条条消息,而是:
DM with hermes-agent
用户: 帮我看一下这个问题
Thread:
hermes-agent: 我收到了这条 DM
用户: 继续测试,不带 @
hermes-agent: 这是同一个私聊 thread 里的连续对话
这不是 Mattermost 的唯一可能模式,而是当前 gateway 的回复策略。未来如果希望“频道里保持 thread,DM 里平铺普通消息”,可以把 reply policy 调成:channel replies use thread,DM replies use direct channel posts。
和 Slack 比:相似,但身份和事件入口不同
Mattermost 的使用体验常常会被描述成 Slack-like,这个类比大体成立,但不能直接等同。
Slack 的 Conversations API 把 public channel、private channel、DM、multi-person DM 等都放在 conversations 这套抽象里处理。[8] Slack 还有明确的 app_mention event,用来表示 app/bot 在频道里被提到;同时也有通用 message event,用来接收消息类事件。[9][10]
这和 Mattermost 很像:两者都可以把“频道消息、私聊消息、thread 回复”看成平台事件,再由 bot/adapter 决定是否响应。
但差别也很明显:
| 维度 | Slack | Mattermost |
|---|---|---|
| 平台形态 | SaaS workspace | 可自托管 server/workspace |
| 应用身份 | Slack App / Bot User / scopes / installation | Mattermost bot account / server API 访问身份 |
| 事件入口 | Events API、Socket Mode、Web API | WebSocket event stream、REST API、webhook/command 可选 |
| 私聊心智 | App DM 通常可直接对话,取决于 app scopes/event subscription | DM 是 direct channel,adapter 可把它设为免 @ |
| 频道触发 | 常见是 @app / app_mention | 常见是 @bot / mention gating |
| thread 结构 | thread_ts 组织回复;Slack 文档也单独说明了检索消息和 thread replies 的 API 行为。[11] | root post + thread replies;Mattermost 用户文档把 threaded discussions 作为组织对话的方式。[4] |
所以,如果你熟悉 Slack,可以把 Mattermost 初步理解成:“类似 Slack 的 workspace/channel/thread/bot 体验,但平台可以自己托管,bot 身份更接近这个 server 里的一个用户”。
和飞书比:飞书是组织入口,Mattermost 是 Agent 工作间
飞书和 Mattermost 最大的差异不是“谁也有群聊”,而是产品中心不同。
飞书更像一个组织入口:群聊、文档、日历、审批、任务、卡片、知识库都在同一个办公套件里。它的机器人心智也很成熟:群聊里 @,私聊里不用 @,卡片和回调可以承载很复杂的交互。
Mattermost 更像一个自托管实时工作间。它的核心不是文档套件,而是:
team -> channel -> post -> thread -> bot reply
这让 Mattermost 特别适合做 Agent room:
- 每个项目、任务线或事件源一个 channel;
- 每个具体任务一条 root post;
- Agent 的长回复、工具执行结果和追问都进 thread;
- 私聊用于个人调试、临时提问和低干扰入口;
- 是否进入 ChatRSS / TriggerEvent / ledger,由任务是否需要跨平台审计决定。
这也解释了为什么上一篇文章说 Mattermost 适合做 ChatArch 的自托管实时 Agent 工作间,而 ChatRSS 不需要进入实时聊天的 happy path。[12] 如果你只是想叫 Hermes 到一个房间里干活,Mattermost gateway 就够了;如果你要把 Mattermost、RSSHub、Discourse、GitHub、Zulip 等事件统一成可审计的 workflow,才需要 ChatRSS 那层 trigger-router-action 基础设施。
推荐的 ChatArch 使用约定
为了让人和 Agent 都不混乱,ChatArch 可以先采用四条约定。
1. Channel 按任务空间命名
不要把所有事情都塞进一个 general。更适合 Agent 的频道命名是:
agent-lab
chatrss-triggers
ops-runtime
blog-drafts
cc-connect
这样 Agent 被 @ 时,channel 名本身就是上下文提示。
2. 任务从 root post 开始
发一个清楚的顶层 post:
@hermes-agent 请检查 ChatRSS 现在的 trigger-router-action 流程,给一个可跑通例子。
后续不要另开一堆散消息;在这个 post 的 thread 里继续追问。
3. 频道里显式 @,DM 里直接说
默认规则:
频道 / thread:@hermes-agent
DM:不用 @
这样既保留飞书私聊的低摩擦,又避免频道里 bot 被所有消息唤醒。
4. 大任务进 thread,结论回主线
如果一个 thread 里跑出了可复用结论,可以最后人工或由 Agent 汇总一条短结论回频道主线:
结论:DM 免 @ 已验证;当前 reply mode 会让 DM 回复进入 thread。
后续:如需飞书式平铺私聊,调整 Mattermost gateway 的 DM reply policy。
这样频道主线像目录,thread 像工作日志。
给 Agent adapter 的设计启发
这篇虽然是使用指南,但对 connector/adapter 也有直接启发。
如果以后给 CC Connect 或 ChatRSS 增加 Mattermost adapter,至少要保留这些字段:
| 字段 | 为什么重要 |
|---|---|
| team/server | 多团队或多入口隔离 |
| channel id/type | 区分 public/private/DM/group message |
| root post id | 判断 thread 边界 |
| post id | 去重和回写定位 |
| sender id | allowlist、审计、会话隔离 |
| mention state | 决定频道消息是否触发 bot |
| reply target | 决定写回 channel 还是 thread |
换句话说,Mattermost adapter 不能只拿一段文本;它要保留“这段话从哪里来、是否在 thread 里、是否是 DM、是否点名 bot、应该回到哪里”。
最后:用一句话区分三者
如果只想快速建立心智,可以这样记:
| 平台 | 一句话心智 |
|---|---|
| 飞书 | 组织协作入口:群聊 @,私聊免 @,文档/卡片/审批强 |
| Slack | SaaS 团队聊天:workspace/channel/thread/app event 模型成熟 |
| Mattermost | 自托管 Agent 工作间:server/team/channel/post/thread/DM,适合把 Hermes 放进自己的房间 |
所以,Mattermost 不是飞书的替代品,也不只是 Slack 的开源版。对 ChatArch 来说,它最有价值的位置是:一个可自托管、可被 API 读写、以 channel 和 thread 管理上下文的人机协作房间。
Sources
[1] https://docs.mattermost.com/end-user-guide/collaborate/organize-using-teams.html [2] https://docs.mattermost.com/end-user-guide/collaborate/channel-types.html [3] https://docs.mattermost.com/end-user-guide/collaborate/collaborate-within-channels.html [4] https://docs.mattermost.com/end-user-guide/collaborate/organize-conversations.html [5] https://docs.mattermost.com/end-user-guide/collaborate/send-messages.html [6] https://docs.mattermost.com/end-user-guide/collaborate/reply-to-messages.html [7] https://docs.mattermost.com/end-user-guide/collaborate/mention-people.html [8] https://docs.slack.dev/apis/web-api/using-the-conversations-api [9] https://docs.slack.dev/reference/events/app_mention [10] https://docs.slack.dev/reference/events/message [11] https://docs.slack.dev/messaging/retrieving-messages [12] https://arch.gh.wzhecnu.cn/ChatBlog/blog/mattermost-hermes-agent-workspace