Developer and self-hosted
Mattermost
Статус: загружаемый Plugin (токен бота + события WebSocket). Поддерживаются каналы, группы и личные сообщения. 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", }, },}Нативные слеш-команды
Нативные слеш-команды включаются отдельно. Когда они включены, OpenClaw регистрирует слеш-команды 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-запроса, поэтому устаревшие токены удаленных или заново созданных слеш-команд перестают приниматься без перезапуска Gateway.
- Проверка callback-запроса завершается закрыто, если API Mattermost не может подтвердить, что команда все еще актуальна; неудачные проверки кратковременно кэшируются, параллельные lookup-запросы объединяются, а запуск свежих lookup-запросов ограничивается по частоте для каждой команды, чтобы сдерживать нагрузку от повторного воспроизведения.
- Callback-запросы слеш-команд завершаются закрыто, если регистрация не удалась, запуск был частичным или токен callback-запроса не совпадает с зарегистрированным токеном найденной команды (токен, действительный для одной команды, не может пройти upstream-проверку для другой команды).
Reachability requirement
Конечная точка callback должна быть доступна с сервера Mattermost.
- Не задавайте
callbackUrlкакlocalhost, если Mattermost не работает на том же хосте или в том же сетевом namespace, что и OpenClaw. - Не задавайте
callbackUrlкак базовый URL Mattermost, если этот URL не проксирует/api/channels/mattermost/commandобратно в OpenClaw. - Быстрая проверка:
curl https://<gateway-host>/api/channels/mattermost/command; GET должен вернуть от OpenClaw405 Method Not Allowed, а не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 автоматически отвечает на личные сообщения. Поведение в каналах управляется chatmode:
oncall (default)
Отвечать в каналах только при @упоминании.
onmessage
Отвечать на каждое сообщение в канале.
onchar
Отвечать, когда сообщение начинается с префикса-триггера.
Пример конфигурации:
{ channels: { mattermost: { chatmode: "onchar", oncharPrefixes: [">", "!"], }, },}Примечания:
oncharвсе равно отвечает на явные @упоминания.channels.mattermost.requireMentionучитывается для устаревших конфигураций, но предпочтителенchatmode.- После того как бот отправит видимый ответ в ветке канала, последующие сообщения в той же ветке получают ответ без нового @упоминания или префикса
onchar, поэтому многоходовые обсуждения в ветке продолжаются без прерываний. Участие запоминается на 7 дней неактивности ветки (обновляется при каждом ответе) и сохраняется после перезапуска Gateway. Ветки, которые бот только наблюдал, не затрагиваются; начните новое сообщение верхнего уровня, чтобы снова требовать явное упоминание.
Ветки и сеансы
Используйте channels.mattermost.replyToMode, чтобы управлять тем, остаются ли ответы в каналах и группах в основном канале или начинают ветку под сообщением-триггером.
off(по умолчанию): отвечать в ветке только тогда, когда входящий пост уже находится в ветке.first: для постов верхнего уровня в канале/группе начать ветку под этим постом и направить разговор в сеанс, scoped к ветке.all: сегодня для Mattermost поведение такое же, как уfirst.- Личные сообщения игнорируют этот параметр и остаются без веток.
Пример конфигурации:
{ channels: { mattermost: { replyToMode: "all", }, },}Примечания:
- Сеансы, scoped к ветке, используют id поста-триггера как корень ветки.
firstиallсейчас эквивалентны, потому что после появления корня ветки в Mattermost последующие фрагменты и медиа продолжаются в той же ветке.
Контроль доступа (личные сообщения)
- По умолчанию:
channels.mattermost.dmPolicy = "pairing"(неизвестные отправители получают код сопряжения). - Одобрение через:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Публичные личные сообщения:
channels.mattermost.dmPolicy="open"плюсchannels.mattermost.allowFrom=["*"]. channels.mattermost.allowFromпринимает записи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"(с ограничением по упоминанию). - Примечание о 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/webhooks:
channel:<id>для каналаuser:<id>для личного сообщения@usernameдля личного сообщения (разрешается через API Mattermost)
Повторные попытки для DM-канала
Когда OpenClaw отправляет сообщение в цель Mattermost DM и сначала должен разрешить прямой канал, он по умолчанию повторяет временные сбои создания прямого канала.
Используйте channels.mattermost.dmChannelRetry, чтобы настроить это поведение глобально для Mattermost Plugin, или channels.mattermost.accounts.<id>.dmChannelRetry для одной учетной записи.
{ channels: { mattermost: { dmChannelRetry: { maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 10000, timeoutMs: 30000, }, }, },}Примечания:
- Это применяется только к созданию DM-канала (
/api/v4/channels/direct), а не к каждому вызову API Mattermost. - Повторные попытки применяются к временным сбоям, таким как лимиты частоты, ответы 5xx, а также сетевые ошибки или тайм-ауты.
- Клиентские ошибки 4xx, кроме
429, считаются постоянными и не повторяются.
Потоковый предпросмотр
Mattermost передает размышления, активность инструментов и частичный текст ответа в один черновой пост предпросмотра, который финализируется на месте, когда итоговый ответ безопасно отправлять. Предпросмотр обновляется в том же id поста, вместо того чтобы засорять канал сообщениями для каждого фрагмента. Финальные медиа/ошибки отменяют ожидающие правки предпросмотра и используют обычную доставку вместо сброса одноразового поста предпросмотра.
Включите через channels.mattermost.streaming:
{ channels: { mattermost: { streaming: "partial", // off | partial | block | progress }, },}Streaming modes
partial— обычный выбор: один пост предпросмотра, который редактируется по мере роста ответа, затем финализируется полным ответом.blockиспользует черновые фрагменты в стиле append внутри поста предпросмотра.progressпоказывает статусный предпросмотр во время генерации и публикует итоговый ответ только при завершении.offотключает потоковый предпросмотр.
Streaming behavior notes
- Если поток нельзя финализировать на месте (например, пост был удален в середине потока), OpenClaw откатывается к отправке нового финального поста, чтобы ответ никогда не потерялся.
- Payloads только с размышлениями подавляются в постах канала, включая текст, который приходит как blockquote
> Thinking. Установите/reasoning on, чтобы видеть размышления на других поверхностях; финальный пост Mattermost сохраняет только ответ. - См. Streaming для матрицы сопоставления каналов.
Реакции (инструмент сообщений)
- Используйте
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.
Интерактивные кнопки (инструмент сообщений)
Отправляйте сообщения с кликабельными кнопками. Когда пользователь нажимает кнопку, агент получает выбор и может ответить.
Обычные ответы агента также могут включать семантические полезные нагрузки 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"Стиль кнопки.
Когда пользователь нажимает кнопку:
Buttons replaced with confirmation
Все кнопки заменяются строкой подтверждения (например, "✓ Yes выбрано @user").
Agent receives the selection
Агент получает выбранный вариант как входящее сообщение и отвечает.
Implementation notes
- Обратные вызовы кнопок используют проверку HMAC-SHA256 (автоматически, настройка не требуется).
- Mattermost удаляет данные обратного вызова из своих ответов API (функция безопасности), поэтому при нажатии удаляются все кнопки — частичное удаление невозможно.
- ID действий, содержащие дефисы или подчёркивания, автоматически очищаются (ограничение маршрутизации Mattermost).
Config and reachability
channels.mattermost.capabilities: массив строк возможностей. Добавьте"inlineButtons", чтобы включить описание инструмента кнопок в системном промпте агента.channels.mattermost.interactions.callbackBaseUrl: необязательный внешний базовый URL для обратных вызовов кнопок (например,https://gateway.example.com). Используйте это, когда Mattermost не может напрямую достичь Gateway на его bind-хосте.- В конфигурациях с несколькими аккаунтами то же поле можно также задать в
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Если
interactions.callbackBaseUrlопущен, OpenClaw выводит URL обратного вызова изgateway.customBindHost+gateway.port, затем откатывается кhttp://localhost:<port>. - Правило доступности: URL обратного вызова кнопки должен быть доступен с сервера Mattermost.
localhostработает только когда Mattermost и OpenClaw запущены на одном хосте/в одном сетевом пространстве имён. - Если цель обратного вызова приватная/tailnet/внутренняя, добавьте её хост/домен в
ServiceSettings.AllowedUntrustedInternalConnectionsMattermost.
Прямая интеграция API (внешние скрипты)
Внешние скрипты и Webhook могут публиковать кнопки напрямую через Mattermost REST API вместо использования инструмента агента message. По возможности используйте buildButtonAttachments() из Plugin; если публикуете сырой JSON, следуйте этим правилам:
Структура полезной нагрузки:
{ 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:
Derive the secret from the bot token
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
Build the context object
Создайте объект контекста со всеми полями, кроме _token.
Serialize with sorted keys
Сериализуйте с отсортированными ключами и без пробелов (Gateway использует JSON.stringify с отсортированными ключами, что даёт компактный вывод).
Sign the payload
HMAC-SHA256(key=secret, data=serializedContext)
Add the token
Добавьте полученный шестнадцатеричный дайджест как _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}Common HMAC pitfalls
- Python
json.dumpsпо умолчанию добавляет пробелы ({"key": "val"}). Используйтеseparators=(",", ":"), чтобы соответствовать компактному выводу JavaScript ({"key":"val"}). - Всегда подписывайте все поля контекста (за вычетом
_token). Gateway удаляет_token, затем подписывает всё оставшееся. Подпись подмножества приводит к тихому сбою проверки. - Используйте
sort_keys=True— Gateway сортирует ключи перед подписью, а Mattermost может переупорядочить поля контекста при сохранении полезной нагрузки. - Выводите секрет из токена бота (детерминированно), а не из случайных байтов. Секрет должен быть одинаковым в процессе, который создаёт кнопки, и в 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" }, }, }, },}Устранение неполадок
No replies in channels
Убедитесь, что бот находится в канале, и упомяните его (oncall), используйте префикс-триггер (onchar) или задайте chatmode: "onmessage".
Auth or multi-account errors
- Проверьте токен бота, базовый URL и включён ли аккаунт.
- Проблемы с несколькими аккаунтами: переменные окружения применяются только к аккаунту
default.
Native slash commands fail
Unauthorized: invalid command token.: OpenClaw не принял токен обратного вызова. Типичные причины:- регистрация slash-команды завершилась неудачно или только частично при запуске
- обратный вызов попадает не в тот Gateway/аккаунт
- в Mattermost всё ещё есть старые команды, указывающие на предыдущую цель обратного вызова
- Gateway был перезапущен без повторной активации slash-команд
- Если встроенные slash-команды перестают работать, проверьте журналы на наличие
mattermost: failed to register slash commandsилиmattermost: native slash commands enabled but no commands could be registered. - Если
callbackUrlопущен и журналы предупреждают, что обратный вызов разрешился вhttp://127.0.0.1:18789/..., этот URL, вероятно, доступен только когда Mattermost запущен на том же хосте/в том же сетевом пространстве имён, что и OpenClaw. Вместо этого задайте явный внешне доступныйcommands.callbackUrl.
Buttons issues
- Кнопки отображаются как белые прямоугольники: агент может отправлять некорректно сформированные данные кнопок. Проверьте, что у каждой кнопки есть оба поля:
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. Проверьте, что вы подписываете все поля контекста (а не подмножество), используете отсортированные ключи и компактный JSON (без пробелов). См. раздел HMAC выше. - Журналы Gateway показывают
missing _token in context: поле_tokenотсутствует в контексте кнопки. Убедитесь, что оно включено при построении полезной нагрузки интеграции. - Подтверждение показывает сырой ID вместо имени кнопки:
context.action_idне совпадает сidкнопки. Задайте для обоих одно и то же очищенное значение. - Агент не знает о кнопках: добавьте
capabilities: ["inlineButtons"]в конфигурацию канала Mattermost.
Связанные материалы
- Маршрутизация каналов — маршрутизация сеансов для сообщений
- Обзор каналов — все поддерживаемые каналы
- Группы — поведение группового чата и ограничение по упоминаниям
- Сопряжение — аутентификация DM и поток сопряжения
- Безопасность — модель доступа и усиление защиты