Developer and self-hosted
Mattermost
狀態:可下載的外掛(機器人權杖 + WebSocket 事件)。支援頻道、私人頻道、群組私訊和私訊。Mattermost 是可自行託管的團隊訊息平台(mattermost.com)。
安裝
npm registry
openclaw plugins install @openclaw/mattermost本機簽出
openclaw plugins install ./path/to/local/mattermost-plugin詳細資訊:外掛
快速設定
確認外掛可用
使用上述命令安裝 @openclaw/mattermost,若閘道已在執行,請重新啟動。
建立 Mattermost 機器人
建立 Mattermost 機器人帳號、複製機器人權杖,並將機器人加入其應讀取的團隊和頻道。
複製基底 URL
複製 Mattermost 基底 URL(例如 https://chat.example.com)。結尾的 /api/v4 會自動移除。
設定 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原生斜線命令
原生斜線命令須選擇加入。啟用後,OpenClaw 會在機器人所屬的每個團隊註冊 oc_* 斜線命令,並在閘道 HTTP 伺服器上接收回呼 POST。
{ channels: { mattermost: { commands: { native: true, nativeSkills: true, callbackPath: "/api/channels/mattermost/command", // 當 Mattermost 無法直接連線至閘道時使用(反向 Proxy/公開 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下(帳號值會覆寫頂層欄位)。 - 由其他整合建立且觸發詞相同的現有斜線命令不會遭到變更(註冊時會略過);機器人建立的命令則會在回呼 URL 發生偏移時更新或重新建立。
- 命令回呼會使用 OpenClaw 註冊
oc_*命令時由 Mattermost 傳回的各命令權杖進行驗證。 - OpenClaw 會在接受每個回呼前重新整理目前的 Mattermost 命令註冊,因此已刪除或重新產生的斜線命令所留下的過時權杖,無須重新啟動閘道便會停止被接受。
- 若 Mattermost API 無法確認命令仍為最新,回呼驗證會採取封閉式失敗;失敗的驗證會短暫快取、並行查詢會合併,且每個命令的新查詢啟動都會受到速率限制,以約束重播壓力。
- 若註冊失敗、啟動不完整,或回呼權杖與解析所得命令的已註冊權杖不符,斜線回呼會採取封閉式失敗(一個命令的有效權杖無法針對另一個命令進入上游驗證)。
- 已接受的回呼會以暫時性的「處理中...」回覆確認;實際答案會以一般訊息送達。
可連線性要求
Mattermost 伺服器必須能連線至回呼端點。
- 除非 Mattermost 與 OpenClaw 在同一主機/網路命名空間中執行,否則請勿將
callbackUrl設為localhost。 - 除非 Mattermost 基底 URL 會將
/api/channels/mattermost/command反向代理至 OpenClaw,否則請勿將callbackUrl設為該基底 URL。 - 快速檢查方式為
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
聊天模式
Mattermost 會自動回應私訊。頻道行為由 chatmode 控制:
oncall(預設)
僅在頻道中被 @提及時回應。
onmessage
回應每則頻道訊息。
onchar
當訊息以觸發前綴開頭時回應。
設定範例:
{ channels: { mattermost: { chatmode: "onchar", oncharPrefixes: [">", "!"], // 預設值 }, },}注意事項:
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.replyToMode 控制頻道和群組回覆要留在主頻道,還是在觸發貼文下建立討論串。
off(預設):僅在傳入貼文本來就在討論串中時,才於討論串回覆。first:對於頂層頻道/群組貼文,在該貼文下建立討論串,並將對話路由至討論串範圍的工作階段。- 目前在 Mattermost 中,
all和batched的行為與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覆寫,現有部署會維持平面、非討論串式的私訊。
存取控制(私訊)
- 預設值:
channels.mattermost.dmPolicy = "pairing"(未知傳送者會收到配對碼)。其他值:allowlist、open、disabled。 - 核准方式:
openclaw pairing list mattermostopenclaw 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設定預設值。 @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 或排程/網路鉤子使用:
| 目標 | 傳遞至 |
|---|---|
channel:<id> |
依 ID 指定的頻道 |
channel:<name> 或 #channel-name |
依名稱指定的頻道,搜尋機器人所屬的所有團隊 |
user:<id> 或 mattermost:<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 會將思考、工具活動和部分回覆文字串流至預覽草稿貼文,並在最終答案可安全傳送時就地完成該貼文。在 partial 模式下,預覽會更新相同的貼文 ID,而不會以每個區塊一則訊息的方式洗版頻道。在 block 模式下,預覽會在已完成文字與工具活動區塊之間輪替,因此較早的區塊會保留為各自的貼文,而不會被下一個區塊覆寫。媒體或錯誤的最終回覆會取消待處理的預覽編輯,並改用一般傳遞,而不會送出一次性的預覽貼文。
預覽串流在 partial 模式下預設開啟。透過 channels.mattermost.streaming.mode 設定(舊版純量/布林值 streaming 會由 openclaw doctor --fix 遷移):
{ channels: { mattermost: { streaming: { mode: "partial" }, // 關閉 | 部分 | 區塊 | 進度 }, },}串流模式
partial(預設):使用單一預覽貼文,隨著回覆增加而編輯,然後以完整答案完成。block會在已完成文字與工具活動區塊之間輪替預覽,使每個區塊都保留為各自的貼文,而不會就地覆寫。平行和連續的工具更新會共用目前的工具活動貼文。progress會在產生期間顯示狀態預覽,並僅在完成時發布最終答案。off會停用預覽串流。搭配streaming.block.enabled: true時,已完成的助理區塊仍會以一般區塊回覆(獨立貼文)傳遞,而不是合併為單一最終貼文。
串流行為注意事項
- 如果串流無法就地完成(例如貼文在串流期間遭到刪除),OpenClaw 會改為傳送新的最終貼文,確保回覆絕不遺失。
- 僅含思考內容的承載資料不會發布至頻道,包括以
> Thinking引用區塊形式抵達的文字。設定/reasoning on可在其他介面查看思考內容;Mattermost 的最終貼文只會保留答案。 - 如需頻道對應矩陣,請參閱串流。
表情回應(訊息工具)
- 搭配
channel=mattermost使用message action=react。 messageId是 Mattermost 貼文 ID。emoji接受如thumbsup或:+1:的名稱(冒號可省略)。- 將
remove=true(布林值)設為移除表情回應。 - 新增/移除表情回應事件會以系統事件轉送至已路由的代理程式工作階段,並套用與訊息相同的私訊/群組政策檢查。
範例:
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。
互動式按鈕(訊息工具)
傳送含可點擊按鈕的訊息。當使用者點擊按鈕時,代理程式會收到選取結果並可回應。
按鈕來自語意化的 presentation 承載資料(用於一般代理程式回覆及 message action=send)。OpenClaw 會將值按鈕呈現為 Mattermost 互動式按鈕、讓 URL 按鈕顯示於訊息文字中,並將選取選單降級為可讀文字。
message action=send channel=mattermost target=channel:<channelId> presentation={"blocks":[{"type":"buttons","buttons":[{"label":"是","value":"yes"},{"label":"否","value":"no"}]}]}呈現按鈕欄位:
labelstringrequired顯示標籤(別名:text)。
valuestring點擊時傳回的值,用作動作 ID(別名:callback_data、callbackData)。除非已設定 url,否則可點擊按鈕必須提供此值。
urlstring連結按鈕;在訊息本文中呈現為 label: url 文字,而非互動式按鈕。
style"primary" | "secondary" | "success" | "danger"按鈕樣式。對於不支援的值,Mattermost 會套用預設樣式。
若要在代理程式系統提示詞中宣告按鈕支援,請將 inlineButtons 新增至頻道功能:
{ channels: { mattermost: { capabilities: ["inlineButtons"], }, },}當使用者點擊按鈕時:
存取檢查
點擊者必須通過與訊息傳送者相同的私訊/群組政策檢查;未授權的點擊會收到暫時性通知並被忽略。
以確認訊息取代按鈕
所有按鈕都會被確認行取代(例如「✓ 是,由 @user 選取」)。
代理程式收到選取結果
代理程式會以輸入訊息(另加一個系統事件)的形式收到選取結果並回應。
實作注意事項
- 按鈕回呼使用 HMAC-SHA256 驗證(自動進行,不需設定)。
- 點擊時會取代整個附件區塊,因此所有按鈕會一併移除,無法只移除部分按鈕。
- 包含連字號或底線的動作 ID 會自動清理(Mattermost 路由限制)。
action_id與原始貼文中的任何動作不符的點擊,會以403(「未知動作」)拒絕。
設定與可連線性
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>。 - 可連線性規則:Mattermost 伺服器必須能連線至按鈕回呼 URL。僅當 Mattermost 與 OpenClaw 在相同主機/網路命名空間中執行時,
localhost才能運作。 channels.mattermost.interactions.allowedSourceIps:按鈕回呼的來源 IP 允許清單。若未設定,僅接受回送來源(127.0.0.1、::1),因此遠端 Mattermost 伺服器必須列入此處的允許清單,否則其點擊會以403拒絕。若位於反向代理後方,也請設定gateway.trustedProxies,以便從轉送標頭取得真實的用戶端 IP。- 如果你的回呼目標是私有/tailnet/內部位址,請將其主機/網域新增至 Mattermost
ServiceSettings.AllowedUntrustedInternalConnections。
直接 API 整合(外部指令碼)
外部指令碼和網路鉤子可以透過 Mattermost REST API 直接發布按鈕,而不必經由代理程式的 message 工具。建議優先使用 OpenClaw 的 message 工具。若為直接整合,請從 @openclaw/mattermost/api.js 匯入 buildButtonAttachments;若發布原始 JSON,請遵循以下規則:
承載資料結構:
{ channel_id: "<channelId>", message: "選擇一個選項:", props: { attachments: [ { actions: [ { id: "mybutton01", // 僅限英數字元,請參閱下方 type: "button", // 必填,否則點擊會被無聲忽略 name: "核准", // 顯示標籤 style: "primary", // 選填:"default"、"primary"、"danger" integration: { url: "https://gateway.example.com/mattermost/interactions/default", context: { action_id: "mybutton01", // 必須與按鈕 ID 相符 action: "approve", // ...任何自訂欄位... _token: "<hmac>", // 請參閱下方 HMAC 章節 }, }, }, ], }, ], },}HMAC 權杖產生
閘道會使用 HMAC-SHA256 驗證按鈕點擊。外部指令碼必須產生符合閘道驗證邏輯的權杖:
從機器人權杖衍生密鑰
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken),以十六進位編碼。
建構內容物件
使用除了 _token 以外的所有欄位建構內容物件。
使用已排序的鍵進行序列化
使用遞迴排序的鍵且不含空格進行序列化(閘道也會將巢狀物件正規化,並產生精簡 JSON)。
簽署承載資料
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除外)。閘道會移除_token,然後簽署剩餘的所有內容。只簽署部分欄位會導致驗證無聲失敗。 - 使用
sort_keys=True——閘道會在簽署前排序鍵,而 Mattermost 儲存承載資料時可能會重新排列內容欄位。 - 請從機器人權杖衍生密鑰(具確定性),不要使用隨機位元組。建立按鈕的處理程序與執行驗證的閘道必須使用相同的密鑰。
目錄配接器
Mattermost 外掛包含一個目錄配接器,可透過 Mattermost API 解析頻道與使用者名稱。這可讓 #channel-name 與 @username 目標用於 openclaw message send 及排程/網路鉤子遞送。
不需要任何設定——配接器會使用帳號設定中的機器人權杖。
多帳號
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 會選擇要使用的帳號。
疑難排解
頻道中沒有回覆
請確認機器人已加入頻道並提及它(oncall)、使用觸發前綴(onchar),或設定 chatmode: "onmessage"。
驗證或多帳號錯誤
- 檢查機器人權杖、基底 URL,以及帳號是否已啟用。
- 多帳號問題:環境變數只會套用至
default帳號。 - 私人/區域網路中的 Mattermost 主機需要
network.dangerouslyAllowPrivateNetwork: true(SSRF 防護機制預設會封鎖私人 IP)。
原生斜線命令失敗
Unauthorized: invalid command token.:OpenClaw 未接受回呼權杖。常見原因:- 斜線命令註冊失敗,或啟動時僅完成部分註冊
- 回呼送至錯誤的閘道/帳號
- Mattermost 仍保留指向先前回呼目標的舊命令
- 閘道重新啟動後未重新啟用斜線命令
- 如果原生斜線命令停止運作,請檢查日誌中是否有
mattermost: failed to register slash commands或mattermost: native slash commands enabled but no commands could be registered。 - 如果省略
callbackUrl,且日誌警告回呼解析為類似http://localhost:18789/...的迴路位址 URL,則只有當 Mattermost 與 OpenClaw 在相同主機/網路命名空間中執行時,該 URL 才可能可供存取。請改為明確設定可從外部存取的commands.callbackUrl。
按鈕問題
- 按鈕顯示為白色方塊或完全不顯示:按鈕資料格式錯誤。每個呈現按鈕都需要
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 伺服器或你的入口加入允許清單;若位於反向 Proxy 後方,請設定gateway.trustedProxies。 - 閘道日誌顯示
invalid _token:HMAC 不相符。請檢查是否簽署所有內容欄位(而非僅部分欄位)、使用已排序的鍵,並使用緊湊 JSON(不含空格)。請參閱上方的 HMAC 章節。 - 閘道日誌顯示
missing _token in context:按鈕的內容中沒有_token欄位。建立整合承載資料時,請確認已包含此欄位。 - 閘道以
Unknown action拒絕點擊:context.action_id與貼文上的任何動作id都不相符。請將兩者設定為相同的清理後值。 - 代理程式未提供按鈕:將
capabilities: ["inlineButtons"]加入 Mattermost 頻道設定。