Developer and self-hosted
Mattermost
Trạng thái: Plugin có thể tải xuống (mã thông báo bot + sự kiện WebSocket). Hỗ trợ kênh, nhóm và DM. Mattermost là một nền tảng nhắn tin nhóm có thể tự lưu trữ; xem trang chính thức tại mattermost.com để biết chi tiết sản phẩm và tải xuống.
Cài đặt
Cài đặt Mattermost trước khi cấu hình kênh:
npm registry
openclaw plugins install @openclaw/mattermost
Bản checkout cục bộ
openclaw plugins install ./path/to/local/mattermost-plugin
Chi tiết: Plugin
Thiết lập nhanh
Đảm bảo Plugin có sẵn
Các bản phát hành OpenClaw đóng gói hiện tại đã đi kèm Plugin này. Các bản cài đặt cũ hơn/tùy chỉnh có thể thêm thủ công bằng các lệnh ở trên.
Tạo bot Mattermost
Tạo tài khoản bot Mattermost và sao chép mã thông báo bot.
Sao chép URL cơ sở
Sao chép URL cơ sở của Mattermost (ví dụ: https://chat.example.com).
Cấu hình OpenClaw và khởi động Gateway
Cấu hình tối thiểu:
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
Lệnh gạch chéo gốc
Lệnh gạch chéo gốc là tùy chọn bật. Khi được bật, OpenClaw đăng ký các lệnh gạch chéo oc_* qua Mattermost API và nhận các POST gọi lại trên máy chủ HTTP của Gateway.
{
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",
},
},
},
}
Ghi chú hành vi
native: "auto"mặc định bị tắt cho Mattermost. Đặtnative: trueđể bật.- Nếu bỏ qua
callbackUrl, OpenClaw suy ra một URL từ máy chủ/cổng Gateway +callbackPath. - Với thiết lập nhiều tài khoản, có thể đặt
commandsở cấp cao nhất hoặc dướichannels.mattermost.accounts.<id>.commands(giá trị của tài khoản ghi đè các trường cấp cao nhất). - Các lệnh gọi lại được xác thực bằng mã thông báo theo từng lệnh do Mattermost trả về khi OpenClaw đăng ký các lệnh
oc_*. - OpenClaw làm mới đăng ký lệnh Mattermost hiện tại trước khi chấp nhận từng lệnh gọi lại để các mã thông báo cũ từ lệnh gạch chéo đã xóa hoặc tạo lại ngừng được chấp nhận mà không cần khởi động lại Gateway.
- Xác thực lệnh gọi lại đóng khi thất bại nếu Mattermost API không thể xác nhận lệnh vẫn là hiện tại; các lần xác thực thất bại được lưu tạm trong thời gian ngắn, các lượt tra cứu đồng thời được gộp lại, và các lượt bắt đầu tra cứu mới được giới hạn tốc độ theo từng lệnh để giới hạn áp lực phát lại.
- Lệnh gọi lại gạch chéo đóng khi thất bại nếu đăng ký thất bại, khởi động chỉ hoàn tất một phần, hoặc mã thông báo gọi lại không khớp với mã thông báo đã đăng ký của lệnh đã phân giải (một mã thông báo hợp lệ cho một lệnh không thể tới bước xác thực ngược dòng cho một lệnh khác).
Yêu cầu về khả năng truy cập
Điểm cuối gọi lại phải có thể truy cập được từ máy chủ Mattermost.
- Không đặt
callbackUrlthànhlocalhosttrừ khi Mattermost chạy trên cùng máy chủ/không gian tên mạng với OpenClaw. - Không đặt
callbackUrlthành URL cơ sở Mattermost của bạn trừ khi URL đó reverse-proxy/api/channels/mattermost/commandtới OpenClaw. - Kiểm tra nhanh là
curl https://<gateway-host>/api/channels/mattermost/command; một yêu cầu GET nên trả về405 Method Not Allowedtừ OpenClaw, không phải404.
Danh sách cho phép lưu lượng ra Mattermost
Nếu lệnh gọi lại của bạn nhắm tới địa chỉ riêng/tailnet/nội bộ, hãy đặt Mattermost ServiceSettings.AllowedUntrustedInternalConnections để bao gồm máy chủ/miền gọi lại.
Dùng mục nhập máy chủ/miền, không dùng URL đầy đủ.
- Tốt:
gateway.tailnet-name.ts.net - Không tốt:
https://gateway.tailnet-name.ts.net
Biến môi trường (tài khoản mặc định)
Đặt các biến này trên máy chủ Gateway nếu bạn muốn dùng biến môi trường:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Chế độ trò chuyện
Mattermost tự động phản hồi DM. Hành vi kênh được kiểm soát bởi chatmode:
oncall (mặc định)
Chỉ phản hồi khi được @nhắc đến trong kênh.
onmessage
Phản hồi mọi tin nhắn kênh.
onchar
Phản hồi khi một tin nhắn bắt đầu bằng tiền tố kích hoạt.
Ví dụ cấu hình:
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
Ghi chú:
oncharvẫn phản hồi các @đề cập rõ ràng.channels.mattermost.requireMentionđược tôn trọng cho cấu hình cũ nhưng nên dùngchatmode.
Luồng và phiên
Dùng channels.mattermost.replyToMode để kiểm soát việc trả lời trong kênh và nhóm ở lại kênh chính hay bắt đầu một luồng dưới bài đăng kích hoạt.
off(mặc định): chỉ trả lời trong một luồng khi bài đăng đến đã ở trong một luồng.first: với bài đăng kênh/nhóm cấp cao nhất, bắt đầu một luồng dưới bài đăng đó và định tuyến cuộc trò chuyện tới một phiên theo phạm vi luồng.all: hiện tại có cùng hành vi nhưfirstđối với Mattermost.- Tin nhắn trực tiếp bỏ qua thiết lập này và vẫn không theo luồng.
Ví dụ cấu hình:
{
channels: {
mattermost: {
replyToMode: "all",
},
},
}
Ghi chú:
- Các phiên theo phạm vi luồng dùng id bài đăng kích hoạt làm gốc luồng.
firstvàallhiện tương đương vì sau khi Mattermost có gốc luồng, các đoạn tiếp theo và phương tiện tiếp tục trong cùng luồng đó.
Kiểm soát truy cập (DM)
- Mặc định:
channels.mattermost.dmPolicy = "pairing"(người gửi không xác định nhận mã ghép nối). - Phê duyệt qua:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- DM công khai:
channels.mattermost.dmPolicy="open"cộng vớichannels.mattermost.allowFrom=["*"].
Kênh (nhóm)
- Mặc định:
channels.mattermost.groupPolicy = "allowlist"(bị chặn bởi yêu cầu đề cập). - Cho phép người gửi bằng
channels.mattermost.groupAllowFrom(khuyến nghị dùng ID người dùng). - Ghi đè đề cập theo từng kênh nằm dưới
channels.mattermost.groups.<channelId>.requireMentionhoặcchannels.mattermost.groups["*"].requireMentioncho mặc định. - So khớp
@usernamecó thể thay đổi và chỉ được bật khichannels.mattermost.dangerouslyAllowNameMatching: true. - Kênh mở:
channels.mattermost.groupPolicy="open"(bị chặn bởi yêu cầu đề cập). - Ghi chú runtime: nếu
channels.mattermosthoàn toàn thiếu, runtime quay vềgroupPolicy="allowlist"cho kiểm tra nhóm (ngay cả khichannels.defaults.groupPolicyđược đặt).
Ví dụ:
{
channels: {
mattermost: {
groupPolicy: "open",
groups: {
"*": { requireMention: true },
"team-channel-id": { requireMention: false },
},
},
},
}
Đích để gửi đi
Dùng các định dạng đích này với openclaw message send hoặc cron/webhook:
channel:<id>cho một kênhuser:<id>cho một DM@usernamecho một DM (được phân giải qua Mattermost API)
Thử lại kênh DM
Khi OpenClaw gửi tới đích DM Mattermost và cần phân giải kênh trực tiếp trước, mặc định nó sẽ thử lại các lỗi tạo kênh trực tiếp tạm thời.
Dùng channels.mattermost.dmChannelRetry để tinh chỉnh hành vi đó trên toàn cục cho Plugin Mattermost, hoặc channels.mattermost.accounts.<id>.dmChannelRetry cho một tài khoản.
{
channels: {
mattermost: {
dmChannelRetry: {
maxRetries: 3,
initialDelayMs: 1000,
maxDelayMs: 10000,
timeoutMs: 30000,
},
},
},
}
Ghi chú:
- Điều này chỉ áp dụng cho việc tạo kênh DM (
/api/v4/channels/direct), không phải mọi lệnh gọi Mattermost API. - Thử lại áp dụng cho các lỗi tạm thời như giới hạn tốc độ, phản hồi 5xx, và lỗi mạng hoặc hết thời gian chờ.
- Lỗi máy khách 4xx ngoài
429được xem là vĩnh viễn và không được thử lại.
Truyền phát bản xem trước
Mattermost truyền phát suy nghĩ, hoạt động công cụ và văn bản trả lời một phần vào một bài đăng xem trước nháp duy nhất, được hoàn tất tại chỗ khi câu trả lời cuối cùng an toàn để gửi. Bản xem trước cập nhật trên cùng id bài đăng thay vì làm đầy kênh bằng tin nhắn theo từng đoạn. Kết quả cuối cùng là phương tiện/lỗi sẽ hủy các chỉnh sửa bản xem trước đang chờ và dùng cách gửi bình thường thay vì đẩy ra một bài đăng xem trước dùng một lần.
Bật qua channels.mattermost.streaming:
{
channels: {
mattermost: {
streaming: "partial", // off | partial | block | progress
},
},
}
Chế độ truyền phát
partiallà lựa chọn thông thường: một bài đăng xem trước được chỉnh sửa khi câu trả lời dài thêm, rồi được hoàn tất với câu trả lời đầy đủ.blockdùng các đoạn nháp kiểu nối thêm bên trong bài đăng xem trước.progresshiển thị bản xem trước trạng thái trong khi tạo và chỉ đăng câu trả lời cuối cùng khi hoàn tất.offtắt truyền phát bản xem trước.
Ghi chú hành vi truyền phát
- Nếu luồng không thể được hoàn tất tại chỗ (ví dụ bài đăng bị xóa giữa luồng), OpenClaw quay về gửi một bài đăng cuối cùng mới để câu trả lời không bao giờ bị mất.
- Payload chỉ có suy luận bị ẩn khỏi bài đăng kênh, bao gồm văn bản đến dưới dạng blockquote
> Reasoning:. Đặt/reasoning onđể xem suy nghĩ ở các bề mặt khác; bài đăng Mattermost cuối cùng chỉ giữ câu trả lời. - Xem Truyền phát để biết ma trận ánh xạ kênh.
Phản ứng (công cụ tin nhắn)
- Dùng
message action=reactvớichannel=mattermost. messageIdlà id bài đăng Mattermost.emojichấp nhận tên nhưthumbsuphoặc:+1:(dấu hai chấm là tùy chọn).- Đặt
remove=true(boolean) để xóa một phản ứng. - Sự kiện thêm/xóa phản ứng được chuyển tiếp dưới dạng sự kiện hệ thống tới phiên agent đã định tuyến.
Ví dụ:
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
Cấu hình:
channels.mattermost.actions.reactions: bật/tắt hành động phản ứng (mặc định true).- Ghi đè theo tài khoản:
channels.mattermost.accounts.<id>.actions.reactions.
Nút tương tác (công cụ tin nhắn)
Gửi tin nhắn có nút có thể nhấp. Khi người dùng nhấp vào nút, agent nhận lựa chọn và có thể phản hồi.
Bật nút bằng cách thêm inlineButtons vào khả năng của kênh:
{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}
Dùng message action=send với tham số buttons. Nút là mảng 2D (các hàng nút):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
Trường nút:
textstringrequiredNhãn hiển thị.
callback_datastringrequiredGiá trị được gửi lại khi nhấp (được dùng làm ID hành động).
style"default" | "primary" | "danger"Kiểu nút.
Khi người dùng nhấp vào một nút:
Các nút được thay bằng xác nhận
Tất cả nút được thay bằng một dòng xác nhận (ví dụ: "✓ Yes selected by @user").
Agent nhận lựa chọn
Agent nhận lựa chọn dưới dạng tin nhắn đến và phản hồi.
Ghi chú triển khai
- Callback của nút dùng xác minh HMAC-SHA256 (tự động, không cần cấu hình).
- Mattermost loại bỏ dữ liệu callback khỏi phản hồi API của nó (tính năng bảo mật), nên tất cả nút bị xóa khi nhấp - không thể xóa một phần.
- ID hành động chứa dấu gạch nối hoặc dấu gạch dưới được tự động chuẩn hóa (giới hạn định tuyến của Mattermost).
Cấu hình và khả năng truy cập
channels.mattermost.capabilities: mảng các chuỗi capability. Thêm"inlineButtons"để bật mô tả công cụ nút trong lời nhắc hệ thống của agent.channels.mattermost.interactions.callbackBaseUrl: URL cơ sở bên ngoài tùy chọn cho callback của nút (ví dụhttps://gateway.example.com). Dùng khi Mattermost không thể truy cập Gateway trực tiếp tại bind host của nó.- Trong thiết lập nhiều tài khoản, bạn cũng có thể đặt cùng trường này dưới
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Nếu bỏ qua
interactions.callbackBaseUrl, OpenClaw suy ra URL callback từgateway.customBindHost+gateway.port, rồi dự phòng vềhttp://localhost:<port>. - Quy tắc khả năng truy cập: URL callback của nút phải có thể truy cập được từ máy chủ Mattermost.
localhostchỉ hoạt động khi Mattermost và OpenClaw chạy trên cùng host/namespace mạng. - Nếu đích callback của bạn là riêng tư/tailnet/nội bộ, hãy thêm host/domain của nó vào Mattermost
ServiceSettings.AllowedUntrustedInternalConnections.
Tích hợp API trực tiếp (script bên ngoài)
Script bên ngoài và webhook có thể đăng nút trực tiếp qua Mattermost REST API thay vì đi qua công cụ message của agent. Dùng buildButtonAttachments() từ Plugin khi có thể; nếu đăng JSON thô, hãy làm theo các quy tắc sau:
Cấu trúc payload:
{
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 (for name lookup)
action: "approve",
// ... any custom fields ...
_token: "<hmac>", // see HMAC section below
},
},
},
],
},
],
},
}
Tạo token HMAC
Gateway xác minh lượt nhấp nút bằng HMAC-SHA256. Script bên ngoài phải tạo token khớp với logic xác minh của Gateway:
Suy ra secret từ bot token
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
Tạo đối tượng context
Tạo đối tượng context với tất cả trường ngoại trừ _token.
Serialize với khóa đã sắp xếp
Serialize với khóa đã sắp xếp và không có khoảng trắng (Gateway dùng JSON.stringify với khóa đã sắp xếp, tạo đầu ra gọn).
Ký payload
HMAC-SHA256(key=secret, data=serializedContext)
Thêm token
Thêm hex digest thu được làm _token trong context.
Ví dụ 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}
Lỗi HMAC thường gặp
json.dumpscủa Python mặc định thêm khoảng trắng ({"key": "val"}). Dùngseparators=(",", ":")để khớp với đầu ra gọn của JavaScript ({"key":"val"}).- Luôn ký tất cả trường context (trừ
_token). Gateway loại bỏ_tokenrồi ký mọi thứ còn lại. Ký một tập con sẽ gây lỗi xác minh âm thầm. - Dùng
sort_keys=True- Gateway sắp xếp khóa trước khi ký, và Mattermost có thể sắp xếp lại các trường context khi lưu payload. - Suy ra secret từ bot token (xác định), không phải byte ngẫu nhiên. Secret phải giống nhau giữa tiến trình tạo nút và Gateway xác minh.
Bộ chuyển đổi thư mục
Plugin Mattermost bao gồm một bộ chuyển đổi thư mục để phân giải tên kênh và người dùng qua Mattermost API. Điều này cho phép các đích #channel-name và @username trong openclaw message send và các lần gửi cron/webhook.
Không cần cấu hình - bộ chuyển đổi dùng bot token từ cấu hình tài khoản.
Nhiều tài khoản
Mattermost hỗ trợ nhiều tài khoản dưới 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" },
},
},
},
}
Khắc phục sự cố
Không có phản hồi trong kênh
Đảm bảo bot ở trong kênh và nhắc đến nó (oncall), dùng tiền tố kích hoạt (onchar), hoặc đặt chatmode: "onmessage".
Lỗi xác thực hoặc nhiều tài khoản
- Kiểm tra bot token, URL cơ sở, và tài khoản có được bật hay không.
- Vấn đề nhiều tài khoản: biến môi trường chỉ áp dụng cho tài khoản
default.
Lệnh slash gốc thất bại
Unauthorized: invalid command token.: OpenClaw không chấp nhận callback token. Nguyên nhân thường gặp:- đăng ký lệnh slash thất bại hoặc chỉ hoàn tất một phần khi khởi động
- callback đang trỏ tới sai Gateway/tài khoản
- Mattermost vẫn có lệnh cũ trỏ tới đích callback trước đó
- Gateway khởi động lại mà không kích hoạt lại lệnh slash
- Nếu lệnh slash gốc ngừng hoạt động, hãy kiểm tra log để tìm
mattermost: failed to register slash commandshoặcmattermost: native slash commands enabled but no commands could be registered. - Nếu bỏ qua
callbackUrlvà log cảnh báo rằng callback được phân giải thànhhttp://127.0.0.1:18789/..., URL đó có lẽ chỉ truy cập được khi Mattermost chạy trên cùng host/namespace mạng với OpenClaw. Thay vào đó, hãy đặtcommands.callbackUrlrõ ràng có thể truy cập từ bên ngoài.
Vấn đề với nút
- Nút xuất hiện dưới dạng hộp trắng: agent có thể đang gửi dữ liệu nút sai định dạng. Kiểm tra rằng mỗi nút có cả hai trường
textvàcallback_data. - Nút hiển thị nhưng nhấp không có tác dụng: xác minh
AllowedUntrustedInternalConnectionstrong cấu hình máy chủ Mattermost bao gồm127.0.0.1 localhost, vàEnablePostActionIntegrationlàtruetrong ServiceSettings. - Nút trả về 404 khi nhấp:
idcủa nút có thể chứa dấu gạch nối hoặc dấu gạch dưới. Bộ định tuyến hành động của Mattermost hỏng với ID không phải chữ và số. Chỉ dùng[a-zA-Z0-9]. - Log Gateway báo
invalid _token: HMAC không khớp. Kiểm tra rằng bạn ký tất cả trường context (không phải một tập con), dùng khóa đã sắp xếp, và dùng JSON gọn (không có khoảng trắng). Xem phần HMAC ở trên. - Log Gateway báo
missing _token in context: trường_tokenkhông nằm trong context của nút. Đảm bảo nó được đưa vào khi tạo payload tích hợp. - Xác nhận hiển thị ID thô thay vì tên nút:
context.action_idkhông khớp vớiidcủa nút. Đặt cả hai thành cùng một giá trị đã chuẩn hóa. - Agent không biết về nút: thêm
capabilities: ["inlineButtons"]vào cấu hình kênh Mattermost.
Liên quan
- Định tuyến kênh - định tuyến phiên cho tin nhắn
- Tổng quan về kênh - tất cả kênh được hỗ trợ
- Nhóm - hành vi trò chuyện nhóm và kiểm soát nhắc đến
- Ghép đôi - xác thực DM và luồng ghép đôi
- Bảo mật - mô hình truy cập và gia cố