Developer and self-hosted
Mattermost
Стан: завантажуваний plugin (токен бота + події WebSocket). Канали, групи та DM підтримуються. Mattermost — це платформа командного обміну повідомленнями, яку можна самостійно розгорнути; подробиці про продукт і завантаження див. на офіційному сайті mattermost.com.
Встановлення
Встановіть Mattermost перед налаштуванням каналу:
npm registry
openclaw plugins install @openclaw/mattermostLocal checkout
openclaw plugins install ./path/to/local/mattermost-pluginДокладніше: Plugins
Швидке налаштування
Ensure plugin is available
Встановіть @openclaw/mattermost за допомогою наведеної вище команди, потім перезапустіть Gateway, якщо він уже запущений.
Create a Mattermost bot
Створіть обліковий запис бота Mattermost і скопіюйте токен бота.
Copy the base URL
Скопіюйте базову URL-адресу Mattermost (наприклад, https://chat.example.com).
Configure OpenClaw and start the gateway
Мінімальна конфігурація:
{ channels: { mattermost: { enabled: true, botToken: "mm-token", baseUrl: "https://chat.example.com", dmPolicy: "pairing", }, },}Нативні slash-команди
Нативні slash-команди вмикаються явно. Коли їх увімкнено, OpenClaw реєструє slash-команди oc_* через API Mattermost і отримує callback POST-запити на HTTP-сервері 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", }, }, },}Behavior notes
native: "auto"за замовчуванням вимкнено для Mattermost. Установітьnative: true, щоб увімкнути.- Якщо
callbackUrlпропущено, OpenClaw виводить його з хоста/порту gateway +callbackPath. - Для налаштувань із кількома обліковими записами
commandsможна задати на верхньому рівні або вchannels.mattermost.accounts.<id>.commands(значення облікового запису перевизначають поля верхнього рівня). - Callback-запити команд перевіряються за токенами кожної команди, які Mattermost повертає, коли OpenClaw реєструє команди
oc_*. - OpenClaw оновлює поточну реєстрацію команд Mattermost перед прийняттям кожного callback-запиту, тому застарілі токени від видалених або повторно згенерованих slash-команд перестають прийматися без перезапуску gateway.
- Перевірка callback-запиту завершується закритою відмовою, якщо API Mattermost не може підтвердити, що команда досі актуальна; невдалі перевірки коротко кешуються, паралельні пошуки об’єднуються, а запуск нових пошуків обмежується за частотою для кожної команди, щоб обмежити тиск повторного відтворення.
- Slash callback-запити завершуються закритою відмовою, коли реєстрація не вдалася, запуск був частковим або токен callback-запиту не відповідає зареєстрованому токену розпізнаної команди (токен, дійсний для однієї команди, не може дійти до upstream-перевірки для іншої команди).
Reachability requirement
Кінцева точка callback має бути доступною із сервера Mattermost.
- Не встановлюйте
callbackUrlнаlocalhost, якщо Mattermost не працює на тому самому хості/у тому самому мережевому просторі імен, що й OpenClaw. - Не встановлюйте
callbackUrlна базову URL-адресу Mattermost, якщо ця URL-адреса не проксирує/api/channels/mattermost/commandдо OpenClaw через reverse proxy. - Швидка перевірка:
curl https://<gateway-host>/api/channels/mattermost/command; GET має повернути405 Method Not Allowedвід OpenClaw, а не404.
Mattermost egress allowlist
Якщо ваш callback націлений на приватні/tailnet/внутрішні адреси, задайте Mattermost ServiceSettings.AllowedUntrustedInternalConnections, щоб включити хост/домен callback.
Використовуйте записи хоста/домену, а не повні URL-адреси.
- Правильно:
gateway.tailnet-name.ts.net - Неправильно:
https://gateway.tailnet-name.ts.net
Змінні середовища (обліковий запис за замовчуванням)
Задайте їх на хості gateway, якщо віддаєте перевагу змінним середовища:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Режими чату
Mattermost автоматично відповідає на DM. Поведінка каналу керується chatmode:
oncall (default)
Відповідати в каналах лише за @згадкою.
onmessage
Відповідати на кожне повідомлення в каналі.
onchar
Відповідати, коли повідомлення починається з тригерного префікса.
Приклад конфігурації:
{ channels: { mattermost: { chatmode: "onchar", oncharPrefixes: [">", "!"], }, },}Примітки:
oncharусе одно відповідає на явні @згадки.channels.mattermost.requireMentionвраховується для застарілих конфігурацій, але перевага надаєтьсяchatmode.- Після того як бот надішле видиму відповідь у гілці каналу, подальші повідомлення в цій самій гілці отримуватимуть відповідь без нової @згадки або префікса
onchar, тому багатокрокові розмови в гілці продовжуватимуться. Участь запам’ятовується на 7 днів неактивності гілки (оновлюється після кожної відповіді) і зберігається після перезапусків gateway. Гілки, які бот лише спостерігав, не змінюються; почніть нове повідомлення верхнього рівня, щоб знову вимагати явну згадку.
Гілки та сеанси
Використовуйте channels.mattermost.replyToMode, щоб керувати тим, чи відповіді в каналах і групах залишаються в основному каналі, чи починають гілку під дописом, який їх викликав.
off(за замовчуванням): відповідати в гілці лише тоді, коли вхідний допис уже в гілці.first: для дописів верхнього рівня в каналі/групі починати гілку під цим дописом і маршрутизувати розмову до сеансу, прив’язаного до гілки.all: така сама поведінка, якfirst, для Mattermost наразі.- Прямі повідомлення ігнорують це налаштування та залишаються без гілок.
Приклад конфігурації:
{ channels: { mattermost: { replyToMode: "all", }, },}Примітки:
- Сеанси, прив’язані до гілки, використовують id допису, який її викликав, як корінь гілки.
firstіallнаразі еквівалентні, тому що щойно Mattermost має корінь гілки, наступні фрагменти й медіа продовжуються в цій самій гілці.
Контроль доступу (DM)
- За замовчуванням:
channels.mattermost.dmPolicy = "pairing"(невідомі відправники отримують код спарювання). - Підтвердження через:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Публічні DM:
channels.mattermost.dmPolicy="open"плюсchannels.mattermost.allowFrom=["*"]. channels.mattermost.allowFromприймає записиaccessGroup:<name>. Див. групи доступу.
Канали (групи)
- За замовчуванням:
channels.mattermost.groupPolicy = "allowlist"(із вимогою згадки). - Дозволяйте відправників через
channels.mattermost.groupAllowFrom(рекомендовано user ID). channels.mattermost.groupAllowFromприймає записиaccessGroup:<name>. Див. групи доступу.- Перевизначення згадок для окремих каналів містяться в
channels.mattermost.groups.<channelId>.requireMentionабоchannels.mattermost.groups["*"].requireMentionдля значення за замовчуванням. - Зіставлення
@usernameє змінним і вмикається лише колиchannels.mattermost.dangerouslyAllowNameMatching: true. - Відкриті канали:
channels.mattermost.groupPolicy="open"(із вимогою згадки). - Примітка щодо runtime: якщо
channels.mattermostповністю відсутній, runtime повертається доgroupPolicy="allowlist"для перевірок груп (навіть якщо заданоchannels.defaults.groupPolicy).
Приклад:
{ channels: { mattermost: { groupPolicy: "open", groups: { "*": { requireMention: true }, "team-channel-id": { requireMention: false }, }, }, },}Цілі для вихідної доставки
Використовуйте ці формати цілей із openclaw message send або cron/webhook:
channel:<id>для каналуuser:<id>для DM@usernameдля DM (розпізнається через API Mattermost)
Повторна спроба для DM-каналу
Коли OpenClaw надсилає повідомлення до цілі DM у Mattermost і спершу має розпізнати прямий канал, він за замовчуванням повторює тимчасові помилки створення прямого каналу.
Використовуйте channels.mattermost.dmChannelRetry, щоб налаштувати цю поведінку глобально для plugin Mattermost, або channels.mattermost.accounts.<id>.dmChannelRetry для одного облікового запису.
{ channels: { mattermost: { dmChannelRetry: { maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 10000, timeoutMs: 30000, }, }, },}Примітки:
- Це застосовується лише до створення DM-каналу (
/api/v4/channels/direct), а не до кожного виклику API Mattermost. - Повторні спроби застосовуються до тимчасових збоїв, як-от rate limit, відповіді 5xx, а також мережеві помилки або timeout.
- Клієнтські помилки 4xx, окрім
429, вважаються постійними та не повторюються.
Потоковий попередній перегляд
Mattermost транслює міркування, активність інструментів і частковий текст відповіді в один чернетковий допис попереднього перегляду, який фіналізується на місці, коли фінальну відповідь безпечно надіслати. Попередній перегляд оновлюється в тому самому id допису замість засмічення каналу повідомленнями для кожного фрагмента. Фінальні медіа/помилки скасовують відкладені редагування попереднього перегляду та використовують звичайну доставку замість скидання одноразового допису попереднього перегляду.
Увімкніть через channels.mattermost.streaming:
{ channels: { mattermost: { streaming: "partial", // off | partial | block | progress }, },}Streaming modes
partial— звичайний вибір: один допис попереднього перегляду, який редагується в міру зростання відповіді, а потім фіналізується повною відповіддю.blockвикористовує чернеткові фрагменти в стилі додавання всередині допису попереднього перегляду.progressпоказує попередній перегляд стану під час генерації та публікує лише фінальну відповідь після завершення.offвимикає потоковий попередній перегляд.
Streaming behavior notes
- Якщо потік не можна фіналізувати на місці (наприклад, допис було видалено під час потоку), OpenClaw повертається до надсилання нового фінального допису, щоб відповідь ніколи не втратилася.
- Payload-и лише з міркуваннями пригнічуються в дописах каналу, включно з текстом, що надходить як blockquote
> Thinking. Установіть/reasoning on, щоб бачити міркування на інших поверхнях; фінальний допис Mattermost зберігає лише відповідь. - Див. потокове передавання для матриці зіставлення каналів.
Реакції (інструмент повідомлень)
- Використовуйте
message action=reactізchannel=mattermost. messageId— це id допису Mattermost.emojiприймає назви на кшталтthumbsupабо:+1:(двокрапки необов’язкові).- Установіть
remove=true(boolean), щоб видалити реакцію. - Події додавання/видалення реакцій пересилаються як системні події до маршрутизованого сеансу агента.
Приклади:
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.
Інтерактивні кнопки (інструмент повідомлень)
Надсилайте повідомлення з кнопками, на які можна натискати. Коли користувач натискає кнопку, агент отримує вибір і може відповісти.
Звичайні відповіді агента також можуть містити семантичні payload-и presentation. OpenClaw відображає кнопки значень як інтерактивні кнопки Mattermost, залишає URL-кнопки видимими в тексті повідомлення та понижує меню вибору до читабельного тексту.
Увімкніть кнопки, додавши inlineButtons до можливостей каналу:
{ channels: { mattermost: { capabilities: ["inlineButtons"], }, },}Використовуйте message action=send з параметром buttons. Кнопки — це двовимірний масив (рядки кнопок):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]Поля кнопки:
textstringrequiredПідпис для відображення.
callback_datastringrequiredЗначення, яке надсилається назад після натискання (використовується як ID дії).
style"default" | "primary" | "danger"Стиль кнопки.
Коли користувач натискає кнопку:
Кнопки замінено підтвердженням
Усі кнопки замінюються рядком підтвердження (наприклад, "✓ Yes selected by @user").
Агент отримує вибір
Агент отримує вибір як вхідне повідомлення та відповідає.
Нотатки щодо реалізації
- Callback-и кнопок використовують перевірку HMAC-SHA256 (автоматично, конфігурація не потрібна).
- Mattermost вилучає callback-дані зі своїх API-відповідей (функція безпеки), тому всі кнопки видаляються після натискання — часткове видалення неможливе.
- ID дій, що містять дефіси або підкреслення, автоматично санітизуються (обмеження маршрутизації Mattermost).
Конфігурація та доступність
channels.mattermost.capabilities: масив рядків можливостей. Додайте"inlineButtons", щоб увімкнути опис інструмента кнопок у системному prompt-і агента.channels.mattermost.interactions.callbackBaseUrl: необов’язкова зовнішня базова URL-адреса для callback-ів кнопок (наприклад,https://gateway.example.com). Використовуйте це, коли Mattermost не може напряму досягти Gateway за його bind-хостом.- У конфігураціях із кількома обліковими записами ви також можете задати те саме поле в
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Якщо
interactions.callbackBaseUrlпропущено, OpenClaw виводить callback-URL зgateway.customBindHost+gateway.port, а потім повертається доhttp://localhost:<port>. - Правило доступності: URL callback-у кнопки має бути доступним із сервера Mattermost.
localhostпрацює лише тоді, коли Mattermost і OpenClaw запускаються на одному хості/у тому самому мережевому просторі імен. - Якщо ваша ціль callback-у приватна/tailnet/внутрішня, додайте її хост/домен до
ServiceSettings.AllowedUntrustedInternalConnectionsMattermost.
Пряма інтеграція API (зовнішні скрипти)
Зовнішні скрипти та Webhook-и можуть публікувати кнопки напряму через Mattermost REST API замість проходження через інструмент агента message. За можливості використовуйте buildButtonAttachments() із Plugin; якщо публікуєте сирий JSON, дотримуйтеся цих правил:
Структура 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 }, }, }, ], }, ], },}Генерація HMAC-токена
Gateway перевіряє натискання кнопок за допомогою HMAC-SHA256. Зовнішні скрипти мають генерувати токени, що відповідають логіці перевірки Gateway:
Виведіть секрет із токена бота
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
Побудуйте об’єкт context
Побудуйте об’єкт context з усіма полями, крім _token.
Серіалізуйте з відсортованими ключами
Серіалізуйте з відсортованими ключами і без пробілів (Gateway використовує JSON.stringify з відсортованими ключами, що створює компактний вивід).
Підпишіть payload
HMAC-SHA256(key=secret, data=serializedContext)
Додайте токен
Додайте отриманий шістнадцятковий digest як _token у context.
Приклад 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
json.dumpsу Python за замовчуванням додає пробіли ({"key": "val"}). Використовуйтеseparators=(",", ":"), щоб відповідати компактному виводу JavaScript ({"key":"val"}).- Завжди підписуйте всі поля context (за винятком
_token). Gateway видаляє_token, а потім підписує все, що залишилося. Підписування підмножини спричиняє мовчазний збій перевірки. - Використовуйте
sort_keys=True— Gateway сортує ключі перед підписуванням, а Mattermost може змінити порядок полів context під час збереження payload-а. - Виводьте секрет із токена бота (детерміновано), а не з випадкових байтів. Секрет має бути однаковим у процесі, який створює кнопки, і в Gateway, який їх перевіряє.
Адаптер каталогу
Plugin Mattermost містить адаптер каталогу, який розв’язує назви каналів і користувачів через Mattermost API. Це вмикає цілі #channel-name і @username в openclaw message send та доставках Cron/Webhook.
Конфігурація не потрібна — адаптер використовує токен бота з конфігурації облікового запису.
Кілька облікових записів
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" }, }, }, },}Усунення несправностей
Немає відповідей у каналах
Переконайтеся, що бот є в каналі, і згадайте його (oncall), використайте префікс-тригер (onchar) або задайте chatmode: "onmessage".
Помилки автентифікації або кількох облікових записів
- Перевірте токен бота, базову URL-адресу та чи ввімкнено обліковий запис.
- Проблеми з кількома обліковими записами: змінні env застосовуються лише до облікового запису
default.
Нативні slash-команди не працюють
Unauthorized: invalid command token.: OpenClaw не прийняв callback-токен. Типові причини:- реєстрація slash-команди не вдалася або лише частково завершилася під час запуску
- callback потрапляє до неправильного Gateway/облікового запису
- у Mattermost усе ще є старі команди, що вказують на попередню ціль callback-у
- Gateway перезапустився без повторної активації slash-команд
- Якщо нативні slash-команди перестають працювати, перевірте журнали на
mattermost: failed to register slash commandsабоmattermost: native slash commands enabled but no commands could be registered. - Якщо
callbackUrlпропущено, а журнали попереджають, що callback розв’язано вhttp://127.0.0.1:18789/..., ця URL-адреса, ймовірно, доступна лише тоді, коли Mattermost працює на тому самому хості/у тому самому мережевому просторі імен, що й OpenClaw. Натомість задайте явний зовні доступнийcommands.callbackUrl.
Проблеми з кнопками
- Кнопки виглядають як білі прямокутники: агент може надсилати неправильно сформовані дані кнопок. Перевірте, що кожна кнопка має обидва поля
textіcallback_data. - Кнопки відображаються, але натискання нічого не роблять: перевірте, що
AllowedUntrustedInternalConnectionsу конфігурації сервера Mattermost містить127.0.0.1 localhost, аEnablePostActionIntegrationмає значенняtrueу ServiceSettings. - Кнопки повертають 404 після натискання:
idкнопки, ймовірно, містить дефіси або підкреслення. Маршрутизатор дій Mattermost ламається на небуквено-цифрових ID. Використовуйте лише[a-zA-Z0-9]. - Журнали Gateway містять
invalid _token: невідповідність HMAC. Перевірте, що ви підписуєте всі поля context (не підмножину), використовуєте відсортовані ключі та компактний JSON (без пробілів). Див. розділ HMAC вище. - Журнали Gateway містять
missing _token in context: поле_tokenвідсутнє в context кнопки. Переконайтеся, що воно включене під час побудови integration payload. - Підтвердження показує сирий ID замість назви кнопки:
context.action_idне збігається зidкнопки. Установіть обидва в однакове санітизоване значення. - Агент не знає про кнопки: додайте
capabilities: ["inlineButtons"]до конфігурації каналу Mattermost.
Пов’язане
- Маршрутизація каналів — маршрутизація сеансів для повідомлень
- Огляд каналів — усі підтримувані канали
- Групи — поведінка групового чату та контроль згадок
- Спарювання — автентифікація DM і потік спарювання
- Безпека — модель доступу та посилення захисту