Mattermost
Статус: поддерживается через плагин (токен бота + события WebSocket). Поддерживаются каналы, группы и личные сообщения. Mattermost — это платформа для командного обмена сообщениями с возможностью самостоятельного хостинга; подробности о продукте и загрузках смотрите на официальном сайте mattermost.com.
Требуется плагин
Mattermost поставляется в виде плагина и не входит в базовую установку. Установите через CLI (npm registry):
openclaw plugins install @openclaw/mattermost
Локальная установка (при запуске из git-репозитория):
openclaw plugins install ./extensions/mattermost
Если вы выберете Mattermost во время настройки/первого запуска и будет обнаружена локальная копия репозитория, OpenClaw автоматически предложит путь для локальной установки. Подробнее: Плагины
Быстрая настройка
- Установите плагин Mattermost.
- Создайте учетную запись бота Mattermost и скопируйте токен бота.
- Скопируйте базовый URL Mattermost (например,
https://chat.example.com). - Настройте OpenClaw и запустите шлюз.
Минимальная конфигурация:
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
Нативные слеш-команды
Нативные слеш-команды включаются опционально. При включении OpenClaw регистрирует команды oc_* через API Mattermost и получает POST-запросы обратного вызова на HTTP-сервере шлюза.
{
channels: {
mattermost: {
commands: {
native: true,
nativeSkills: true,
callbackPath: "/api/channels/mattermost/command",
// Используйте, когда Mattermost не может напрямую обратиться к шлюзу (обратный прокси/публичный URL).
callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
},
},
},
}
Примечания:
native: "auto"по умолчанию отключено для Mattermost. Установитеnative: trueдля включения.- Если
callbackUrlне указан, OpenClaw формирует его из хоста/порта шлюза иcallbackPath. - Для настройки нескольких учетных записей
commandsможно задать на верхнем уровне или вchannels.mattermost.accounts.<id>.commands(значения для учетной записи переопределяют поля верхнего уровня). - Обратные вызовы команд проверяются с помощью токенов для каждой команды и завершаются ошибкой при неудачной проверке токена.
- Требование доступности: конечная точка обратного вызова должна быть доступна с сервера Mattermost.
- Не указывайте
callbackUrlкакlocalhost, если только Mattermost не работает на том же хосте/сетевом пространстве имен, что и OpenClaw. - Не указывайте
callbackUrlкак ваш базовый URL Mattermost, если только этот URL не проксирует запросы/api/channels/mattermost/commandна OpenClaw. - Быстрая проверка:
curl https://<gateway-host>/api/channels/mattermost/command; GET-запрос должен вернуть405 Method Not Allowedот OpenClaw, а не404.
- Не указывайте
- Требование к списку разрешенных исходящих подключений Mattermost:
- Если ваш обратный вызов указывает на приватные/Tailnet/внутренние адреса, установите в Mattermost
ServiceSettings.AllowedUntrustedInternalConnectionsвключение хоста/домена обратного вызова. - Используйте записи хоста/домена, а не полные URL.
- Хорошо:
gateway.tailnet-name.ts.net - Плохо:
https://gateway.tailnet-name.ts.net
- Хорошо:
- Если ваш обратный вызов указывает на приватные/Tailnet/внутренние адреса, установите в Mattermost
Переменные окружения (учетная запись по умолчанию)
Установите эти переменные на хосте шлюза, если предпочитаете использовать env vars:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Переменные окружения применяются только к учетной записи по умолчанию (default). Другие учетные записи должны использовать значения конфигурации.
Режимы чата
Mattermost автоматически отвечает на личные сообщения. Поведение в каналах контролируется параметром chatmode:
oncall(по умолчанию): отвечать только при упоминании через @ в каналах.onmessage: отвечать на каждое сообщение в канале.onchar: отвечать, когда сообщение начинается с префикса-триггера.
Пример конфигурации:
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
Примечания:
oncharтакже реагирует на явные упоминания через @.channels.mattermost.requireMentionучитывается для устаревших конфигураций, но предпочтительнее использоватьchatmode.
Контроль доступа (личные сообщения)
- По умолчанию:
channels.mattermost.dmPolicy = "pairing"(неизвестным отправителям выдается код сопряжения). - Подтверждение через:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Открытые личные сообщения:
channels.mattermost.dmPolicy="open"плюсchannels.mattermost.allowFrom=["*"].
Каналы (группы)
- По умолчанию:
channels.mattermost.groupPolicy = "allowlist"(с упоминанием через @). - Разрешите отправителей с помощью
channels.mattermost.groupAllowFrom(рекомендуются ID пользователей). - Сопоставление по
@usernameизменчиво и включается только приchannels.mattermost.dangerouslyAllowNameMatching: true. - Открытые каналы:
channels.mattermost.groupPolicy="open"(с упоминанием через @). - Примечание для времени выполнения: если
channels.mattermostполностью отсутствует, среда выполнения возвращается кgroupPolicy="allowlist"для проверок групп (даже если установленchannels.defaults.groupPolicy).
Цели для исходящей доставки
Используйте эти форматы целей с openclaw message send или cron/webhooks:
channel:<id>для каналаuser:<id>для личного сообщения@usernameдля личного сообщения (разрешается через API Mattermost)
Простые ID рассматриваются как каналы.
Реакции (инструмент сообщений)
- Используйте
message action=reactсchannel=mattermost. messageId— это ID поста Mattermost.emojiпринимает названия, такие какthumbsupили:+1:(двоеточия необязательны).- Установите
remove=true(логическое значение), чтобы удалить реакцию. - События добавления/удаления реакции пересылаются как системные события в маршрутизированный сеанс агента.
Примеры:
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
Конфигурация:
channels.mattermost.actions.reactions: включить/отключить действия с реакциями (по умолчанию true).- Переопределение для учетной записи:
channels.mattermost.accounts.<id>.actions.reactions.
Интерактивные кнопки (инструмент сообщений)
Отправляйте сообщения с кликабельными кнопками. Когда пользователь нажимает кнопку, агент получает выбор и может ответить. Включите кнопки, добавив inlineButtons в возможности канала:
{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}
Используйте message action=send с параметром buttons. Кнопки представляют собой двумерный массив (ряды кнопок):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Да","callback_data":"yes"},{"text":"Нет","callback_data":"no"}]]
Поля кнопки:
text(обязательно): отображаемая метка.callback_data(обязательно): значение, отправляемое обратно при нажатии (используется как ID действия).style(опционально):"default","primary"или"danger".
Когда пользователь нажимает кнопку:
- Все кнопки заменяются строкой подтверждения (например, ”✓ Да выбрано пользователем @user”).
- Агент получает выбор как входящее сообщение и отвечает.
Примечания:
- Обратные вызовы кнопок используют проверку HMAC-SHA256 (автоматически, без дополнительной настройки).
- Mattermost удаляет данные обратного вызова из ответов своего API (функция безопасности), поэтому все кнопки удаляются при нажатии — частичное удаление невозможно.
- ID действий, содержащие дефисы или подчеркивания, автоматически очищаются (ограничение маршрутизации Mattermost).
Конфигурация:
channels.mattermost.capabilities: массив строк возможностей. Добавьте"inlineButtons", чтобы включить описание инструмента кнопок в системном промпте агента.channels.mattermost.interactions.callbackBaseUrl: опциональный внешний базовый URL для обратных вызовов кнопок (например,https://gateway.example.com). Используйте его, когда Mattermost не может напрямую обратиться к хосту привязки шлюза.- В настройках с несколькими учетными записями вы также можете установить это поле в
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Если
interactions.callbackBaseUrlне указан, OpenClaw формирует URL обратного вызова изgateway.customBindHost+gateway.port, затем возвращается кhttp://localhost:<port>. - Правило доступности: URL обратного вызова кнопок должен быть доступен с сервера Mattermost.
localhostработает только тогда, когда Mattermost и OpenClaw работают на одном хосте/сетевом пространстве имен. - Если ваша цель обратного вызова является приватной/Tailnet/внутренней, добавьте ее хост/домен в Mattermost
ServiceSettings.AllowedUntrustedInternalConnections.
Прямая интеграция с API (внешние скрипты)
Внешние скрипты и вебхуки могут публиковать кнопки напрямую через REST API Mattermost, вместо того чтобы использовать инструмент message агента. По возможности используйте 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 ниже
},
},
},
],
},
],
},
}
Критические правила:
- Вложения помещаются в
props.attachments, а не вattachmentsверхнего уровня (тихо игнорируются). - Каждому действию нужен
type: "button"— без него нажатия тихо игнорируются. - Каждому действию нужно поле
id— Mattermost игнорирует действия без ID. idдействия должен содержать только буквенно-цифровые символы ([a-zA-Z0-9]). Дефисы и подчеркивания нарушают серверную маршрутизацию действий Mattermost (возвращает 404). Удаляйте их перед использованием.context.action_idдолжен совпадать сidкнопки, чтобы в сообщении подтверждения отображалось имя кнопки (например, "Подтвердить"), а не сырой ID.context.action_idобязателен — обработчик взаимодействий вернет 400 без него.
Генерация токена HMAC: Шлюз проверяет нажатия кнопок с помощью HMAC-SHA256. Внешние скрипты должны генерировать токены, соответствующие логике проверки шлюза:
- Получите секрет из токена бота:
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken) - Постройте объект контекста со всеми полями кроме
_token. - Сериализуйте с отсортированными ключами и без пробелов (шлюз использует
JSON.stringifyс отсортированными ключами, что дает компактный вывод). - Подпишите:
HMAC-SHA256(key=secret, data=serializedContext) - Добавьте полученный хеш в шестнадцатеричном формате как
_tokenв контекст.
Пример на Python:
import hmac, hashlib, json
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"}).- Всегда подписывайте все поля контекста (кроме
_token). Шлюз удаляет_token, а затем подписывает все остальное. Подпись подмножества приводит к тихому сбою проверки. - Используйте
sort_keys=True— шлюз сортирует ключи перед подписанием, а Mattermost может переупорядочить поля контекста при сохранении полезной нагрузки. - Получайте секрет из токена бота (детерминированно), а не из случайных байтов. Секрет должен быть одинаковым в процессе создания кнопок и в шлюзе, который проверяет.
Адаптер каталога
Плагин Mattermost включает адаптер каталога, который разрешает имена каналов и пользователей через API Mattermost. Это позволяет использовать цели #channel-name и @username в openclaw message send и доставках через cron/webhook. Дополнительная настройка не требуется — адаптер использует токен бота из конфигурации учетной записи.
Несколько учетных записей
Mattermost поддерживает несколько учетных записей в channels.mattermost.accounts:
{
channels: {
mattermost: {
accounts: {
default: { name: "Основная", botToken: "mm-token", baseUrl: "https://chat.example.com" },
alerts: { name: "Оповещения", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" },
},
},
},
}
Устранение неполадок
- Нет ответов в каналах: убедитесь, что бот находится в канале и упомяните его (oncall), используйте префикс-триггер (onchar) или установите
chatmode: "onmessage". - Ошибки аутентификации: проверьте токен бота, базовый URL и включена ли учетная запись.
- Проблемы с несколькими учетными записями: переменные окружения применяются только к учетной записи
default. - Кнопки отображаются как белые рамки: возможно, агент отправляет некорректные данные кнопок. Убедитесь, что у каждой кнопки есть поля
textиcallback_data. - Кнопки отображаются, но нажатия не работают: убедитесь, что
AllowedUntrustedInternalConnectionsв конфигурации сервера Mattermost включает127.0.0.1 localhost, и чтоEnablePostActionIntegrationустановлено вtrueв ServiceSettings. - При нажатии кнопки возвращается 404: вероятно,
idкнопки содержит дефисы или подчеркивания. Маршрутизатор действий Mattermost ломается на небуквенно-цифровых ID. Используйте только[a-zA-Z0-9]. - В журналах шлюза
invalid _token: несоответствие HMAC. Проверьте, что вы подписываете все поля контекста (а не подмножество), используете отсортированные ключи и компактный JSON (без пробелов). См. раздел HMAC выше. - В журналах шлюза
missing _token in context: поле_tokenотсутствует в контексте кнопки. Убедитесь, что оно включено при построении полезной нагрузки интеграции. - В подтверждении отображается сырой ID вместо имени кнопки:
context.action_idне совпадает сidкнопки. Установите оба значения одинаковыми и очищенными. - Агент не знает о кнопках: добавьте
capabilities: ["inlineButtons"]в конфигурацию канала Mattermost.