Skip to main content
Статус: загружаемый плагин (токен бота + события WebSocket). Поддерживаются каналы, закрытые каналы, групповые личные сообщения и личные сообщения. Mattermost — это платформа для командного обмена сообщениями с возможностью самостоятельного размещения (mattermost.com).

Установка

Подробнее: Плагины

Быстрая настройка

1

Убедитесь, что плагин доступен

Установите @openclaw/mattermost с помощью приведённой выше команды, затем перезапустите Gateway, если он уже запущен.
2

Создайте бота Mattermost

Создайте учётную запись бота Mattermost, скопируйте токен бота и добавьте бота в команды и каналы, которые он должен читать.
3

Скопируйте базовый URL

Скопируйте базовый URL Mattermost (например, https://chat.example.com). Завершающий /api/v4 удаляется автоматически.
4

Настройте OpenClaw и запустите Gateway

Минимальная конфигурация:
Неинтерактивный вариант:
Для самостоятельно размещённого Mattermost с адресом в частной сети/LAN/tailnet: исходящие запросы к API Mattermost проходят через защиту от SSRF, которая по умолчанию блокирует частные и внутренние IP-адреса. Разрешите их с помощью channels.mattermost.network.dangerouslyAllowPrivateNetwork: true (для отдельной учётной записи: channels.mattermost.accounts.<id>.network.dangerouslyAllowPrivateNetwork).

Нативные команды со слешем

Нативные команды со слешем включаются явно. Когда они включены, OpenClaw регистрирует команды со слешем oc_* в каждой команде, участником которой является бот, и получает обратные POST-запросы на HTTP-сервере Gateway.
Зарегистрированные команды: /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 обратного вызова.
  • Обратные вызовы команд проверяются с помощью отдельных токенов команд, возвращаемых Mattermost при регистрации OpenClaw команд oc_*.
  • Перед принятием каждого обратного вызова OpenClaw обновляет текущие данные о регистрации команд Mattermost, поэтому устаревшие токены удалённых или повторно созданных команд со слешем перестают приниматься без перезапуска Gateway.
  • Если API Mattermost не может подтвердить актуальность команды, проверка обратного вызова завершается отказом; неудачные проверки кратковременно кэшируются, параллельные запросы объединяются, а частота запуска новых проверок ограничивается отдельно для каждой команды, чтобы сдерживать нагрузку от повторного воспроизведения запросов.
  • Обратные вызовы команд со слешем завершаются отказом, если регистрация не удалась, запуск был частичным или токен обратного вызова не совпадает с зарегистрированным токеном найденной команды (токен, действительный для одной команды, не может пройти последующую проверку для другой команды).
  • Принятые обратные вызовы подтверждаются эфемерным ответом «Обработка…»; фактический ответ поступает как обычное сообщение.
Конечная точка обратного вызова должна быть доступна с сервера 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.
Если обратный вызов направлен на частные адреса, адреса tailnet или внутренние адреса, задайте в Mattermost ServiceSettings.AllowedUntrustedInternalConnections, включив в него хост или домен обратного вызова.Используйте записи хостов или доменов, а не полные URL.
  • Правильно: gateway.tailnet-name.ts.net
  • Неправильно: https://gateway.tailnet-name.ts.net

Переменные окружения (учётная запись по умолчанию)

Если предпочитаете переменные окружения, задайте их на хосте Gateway:
  • MATTERMOST_BOT_TOKEN=...
  • MATTERMOST_URL=https://chat.example.com
Переменные окружения применяются только к учётной записи по умолчанию (default). Для остальных учётных записей необходимо использовать значения конфигурации.MATTERMOST_URL нельзя задать из файла .env рабочей области; см. Файлы .env рабочей области.

Режимы чата

Mattermost автоматически отвечает на личные сообщения. Поведение в каналах управляется параметром chatmode:
Отвечать в каналах только при @упоминании.
Пример конфигурации:
Примечания:
  • onchar по-прежнему отвечает на явные @упоминания.
  • channels.mattermost.requireMention по-прежнему учитывается, но предпочтителен chatmode. Настройки groups.<channelId>.requireMention для отдельных каналов имеют приоритет над обоими.
  • После того как бот отправляет видимый ответ в обсуждении канала, на последующие сообщения в том же обсуждении он отвечает без нового @упоминания или префикса onchar, поэтому многошаговые беседы в обсуждении продолжаются без прерывания. Участие запоминается на 7 дней после последнего ответа бота в этом обсуждении и сохраняется после перезапусков Gateway. Это не относится к обсуждениям, которые бот только просматривал; чтобы снова требовалось явное упоминание, начните новое сообщение верхнего уровня.

Обсуждения и сеансы

Используйте channels.mattermost.replyToMode, чтобы определить, должны ли ответы в каналах и группах оставаться в основном канале или начинать обсуждение под сообщением-триггером.
  • off (по умолчанию): отвечать в обсуждении, только если входящее сообщение уже находится в нём.
  • first: для сообщений верхнего уровня в каналах и группах начинать обсуждение под этим сообщением и направлять беседу в сеанс, относящийся к обсуждению.
  • all и batched: сейчас в Mattermost работают так же, как first, поскольку после появления корневого сообщения обсуждения в Mattermost последующие части ответа и медиафайлы продолжают отправляться в то же обсуждение.
  • Для личных сообщений по умолчанию используется off, даже если задан replyToMode.
Используйте channels.mattermost.replyToModeByChatType, чтобы переопределить режим для чатов direct, group или channel. Задайте direct, чтобы включить обсуждения для личных сообщений:
  • off (по умолчанию): личные сообщения остаются без обсуждений в одном непрерывном сеансе.
  • first, all или batched: каждое личное сообщение верхнего уровня начинает обсуждение Mattermost, связанное с новым независимым сеансом.
Примечания:
  • Сеансы, относящиеся к обсуждению, используют идентификатор сообщения-триггера в качестве корневого сообщения обсуждения.
  • first и all сейчас эквивалентны, поскольку после появления корневого сообщения обсуждения в Mattermost последующие части ответа и медиафайлы продолжают отправляться в то же обсуждение.
  • Переопределения для отдельных типов чата имеют приоритет над replyToMode. Без переопределения direct существующие развёртывания сохраняют плоские личные сообщения без обсуждений.

Управление доступом (личные сообщения)

  • По умолчанию: channels.mattermost.dmPolicy = "pairing" (неизвестные отправители получают код сопряжения). Другие значения: allowlist, open, disabled.
  • Подтверждение выполняется с помощью:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • Общедоступные личные сообщения: channels.mattermost.dmPolicy="open" вместе с channels.mattermost.allowFrom=["*"] (схема конфигурации требует подстановочный знак).
  • channels.mattermost.allowFrom принимает идентификаторы пользователей (рекомендуется) и записи accessGroup:<name>. См. Группы доступа.

Каналы (группы)

  • По умолчанию: channels.mattermost.groupPolicy = "allowlist" (требуется упоминание).
  • Добавьте отправителей в список разрешённых с помощью channels.mattermost.groupAllowFrom (рекомендуются идентификаторы пользователей).
  • 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) и однократно записывает предупреждение в журнал.
Пример:

Цели исходящей доставки

Используйте эти форматы целей с openclaw message send или cron/webhooks: При исходящей отправке поддерживается не более одного вложения на сообщение; несколько файлов следует отправлять отдельными сообщениями.
Непрефиксированные непрозрачные идентификаторы (например, 64ifufp...) в Mattermost неоднозначны (идентификатор пользователя или канала).OpenClaw разрешает их, сначала проверяя пользователя:
  • Если идентификатор принадлежит существующему пользователю (GET /api/v4/users/<id> завершается успешно), OpenClaw отправляет личное сообщение, определяя личный канал через /api/v4/channels/direct.
  • В противном случае идентификатор считается идентификатором канала.
Если требуется детерминированное поведение, всегда используйте явные префиксы (user:<id> / channel:<id>).

Повторная попытка для канала личных сообщений

Когда OpenClaw отправляет сообщение адресату личной переписки Mattermost и сначала должен определить прямой канал, по умолчанию он повторяет попытки при временных сбоях создания прямого канала. Используйте channels.mattermost.dmChannelRetry, чтобы настроить это поведение глобально для плагина Mattermost, или channels.mattermost.accounts.<id>.dmChannelRetry для отдельной учётной записи. Значения по умолчанию:
Примечания:
  • Это относится только к созданию канала личной переписки (/api/v4/channels/direct), а не к каждому вызову API Mattermost.
  • Повторные попытки используют экспоненциальную задержку с джиттером и применяются при временных сбоях, таких как ограничения частоты запросов, ответы 5xx, сетевые ошибки и истечение времени ожидания.
  • Клиентские ошибки 4xx, кроме 429, считаются постоянными, и повторные попытки для них не выполняются.

Потоковая передача предпросмотра

Mattermost передаёт рассуждения, сведения об активности инструментов и частичный текст ответа в черновую публикацию предпросмотра, которая финализируется на месте, когда окончательный ответ можно безопасно отправить. В режиме partial предпросмотр обновляется в публикации с тем же идентификатором, а не засоряет канал отдельными сообщениями для каждого фрагмента. В режиме block предпросмотр переключается между блоками завершённого текста и активности инструментов, поэтому предыдущие блоки остаются видимыми как отдельные публикации, а не перезаписываются следующими. Финальные сообщения с медиафайлами или ошибками отменяют ожидающие изменения предпросмотра и используют обычную доставку вместо отправки ненужной публикации предпросмотра. Потоковая передача предпросмотра включена по умолчанию в режиме partial. Настройте её с помощью channels.mattermost.streaming.mode (устаревшие скалярные или логические значения streaming переносятся командой openclaw doctor --fix):
  • partial (по умолчанию): одна публикация предпросмотра, которая редактируется по мере формирования ответа, а затем финализируется полным ответом.
  • block переключает предпросмотр между блоками завершённого текста и активности инструментов, поэтому каждый блок остаётся видимым как отдельная публикация, а не перезаписывается на месте. Параллельные и последовательные обновления инструментов используют общую текущую публикацию активности инструментов.
  • progress показывает предпросмотр состояния во время генерации и публикует окончательный ответ только после завершения.
  • off отключает потоковую передачу предпросмотра. При использовании streaming.block.enabled: true завершённые блоки ассистента по-прежнему доставляются как обычные блочные ответы (отдельные публикации), а не как одна объединённая финальная публикация.
  • Если поток невозможно финализировать на месте (например, публикация была удалена во время потоковой передачи), OpenClaw отправляет новую финальную публикацию, чтобы ответ не был потерян.
  • Полезная нагрузка, содержащая только рассуждения, не публикуется в канале, включая текст, поступающий как цитата > Thinking. Установите /reasoning on, чтобы видеть рассуждения в других интерфейсах; финальная публикация Mattermost содержит только ответ.
  • Матрицу сопоставления каналов см. в разделе Потоковая передача.

Реакции (инструмент сообщений)

  • Используйте message action=react с channel=mattermost.
  • messageId — идентификатор публикации Mattermost.
  • emoji принимает названия наподобие thumbsup или :+1: (двоеточия необязательны).
  • Установите remove=true (логическое значение), чтобы удалить реакцию.
  • События добавления и удаления реакций передаются как системные события в соответствующий сеанс агента с применением тех же проверок политик личных и групповых переписок, что и для сообщений.
Примеры:
Конфигурация:
  • channels.mattermost.actions.reactions: включение или отключение действий с реакциями (по умолчанию — true).
  • Переопределение для отдельной учётной записи: channels.mattermost.accounts.<id>.actions.reactions.

Интерактивные кнопки (инструмент сообщений)

Отправляйте сообщения с нажимаемыми кнопками. Когда пользователь нажимает кнопку, агент получает выбранное значение и может ответить. Кнопки поступают из семантической полезной нагрузки presentation (в обычных ответах агента и в message action=send). OpenClaw отображает кнопки со значениями как интерактивные кнопки Mattermost, оставляет кнопки со ссылками видимыми в тексте сообщения и преобразует меню выбора в удобочитаемый текст.
Поля кнопок представления:
string
обязательно
Отображаемая подпись (псевдоним: text).
string
Значение, возвращаемое при нажатии и используемое как идентификатор действия (псевдонимы: callback_data, callbackData). Обязательно для нажимаемой кнопки, если не задано url.
string
Кнопка-ссылка; отображается как текст label: url в теле сообщения, а не как интерактивная кнопка.
"primary" | "secondary" | "success" | "danger"
Стиль кнопки. Для неподдерживаемых значений Mattermost применяет оформление по умолчанию.
Чтобы указать поддержку кнопок в системном промпте агента, добавьте inlineButtons в возможности канала:
Когда пользователь нажимает кнопку:
1

Проверка доступа

Пользователь, нажавший кнопку, должен пройти те же проверки политик личных и групповых переписок, что и отправитель сообщения; при неавторизованных нажатиях показывается временное уведомление, а сами нажатия игнорируются.
2

Замена кнопок подтверждением

Все кнопки заменяются строкой подтверждения (например, «✓ Да — выбор пользователя @user»).
3

Агент получает выбранное значение

Агент получает выбранное значение как входящее сообщение (а также системное событие) и отвечает.
  • Обратные вызовы кнопок проверяются с помощью HMAC-SHA256 (автоматически, настройка не требуется).
  • При нажатии заменяется весь блок вложения, поэтому все кнопки удаляются одновременно — частичное удаление невозможно.
  • Идентификаторы действий, содержащие дефисы или символы подчёркивания, автоматически очищаются (ограничение маршрутизации Mattermost).
  • Нажатия, у которых action_id не соответствует действию в исходной публикации, отклоняются с ошибкой 403 («Неизвестное действие»).
  • channels.mattermost.capabilities: массив строк возможностей. Добавьте "inlineButtons", чтобы включить описание инструмента кнопок в системном промпте агента.
  • channels.mattermost.interactions.callbackBaseUrl: необязательный внешний базовый URL для обратных вызовов кнопок (например, https://gateway.example.com). Используйте его, если Mattermost не может напрямую обратиться к Gateway по адресу привязки.
  • В конфигурациях с несколькими учётными записями это же поле можно задать в channels.mattermost.accounts.<id>.interactions.callbackBaseUrl.
  • Если interactions.callbackBaseUrl не указан, OpenClaw формирует URL обратного вызова из gateway.customBindHost + gateway.port (по умолчанию 18789), а затем использует http://localhost:<port> как резервный вариант. Путь обратного вызова: /mattermost/interactions/<accountId>.
  • Требование доступности: URL обратного вызова кнопки должен быть доступен с сервера Mattermost. localhost работает только тогда, когда Mattermost и OpenClaw запущены на одном хосте или в одном сетевом пространстве имён.
  • channels.mattermost.interactions.allowedSourceIps: список разрешённых исходных IP-адресов для обратных вызовов кнопок. Если он не задан, принимаются только локальные источники (127.0.0.1, ::1), поэтому удалённый сервер Mattermost необходимо добавить в этот список, иначе его нажатия будут отклонены с ошибкой 403. При работе через обратный прокси также задайте gateway.trustedProxies, чтобы реальный IP-адрес клиента определялся по перенаправленным заголовкам.
  • Если адрес обратного вызова является частным, внутренним или находится в tailnet, добавьте его хост или домен в ServiceSettings.AllowedUntrustedInternalConnections Mattermost.

Прямая интеграция с API (внешние скрипты)

Внешние скрипты и вебхуки могут публиковать кнопки напрямую через REST API Mattermost вместо использования инструмента агента message. Предпочтительно использовать инструмент message OpenClaw. Для прямых интеграций импортируйте buildButtonAttachments из @openclaw/mattermost/api.js; при публикации необработанного JSON соблюдайте следующие правила: Структура полезной нагрузки:
Критически важные правила
  1. Вложения размещаются в props.attachments, а не в attachments верхнего уровня (иначе они молча игнорируются).
  2. Для каждого действия требуется type: "button" — без него нажатия молча игнорируются.
  3. Для каждого действия требуется поле id — Mattermost игнорирует действия без идентификаторов.
  4. Значение id действия должно содержать только буквы и цифры ([a-zA-Z0-9]). Дефисы и символы подчёркивания нарушают серверную маршрутизацию действий Mattermost (возвращается 404). Удаляйте их перед использованием.
  5. context.action_id должен соответствовать id кнопки; Gateway отклоняет нажатия, если action_id отсутствует в публикации.
  6. context.action_id обязателен — без него обработчик взаимодействия возвращает 400.
  7. Исходный IP-адрес обратного вызова должен быть разрешён (см. interactions.allowedSourceIps выше).
Генерация токена HMAC Gateway проверяет нажатия кнопок с помощью HMAC-SHA256. Внешние скрипты должны генерировать токены, соответствующие логике проверки Gateway:
1

Получение секрета из токена бота

HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken), в шестнадцатеричном представлении.
2

Создание объекта контекста

Создайте объект контекста со всеми полями, кроме _token.
3

Сериализация с отсортированными ключами

Выполните сериализацию с рекурсивно отсортированными ключами и без пробелов (Gateway также канонизирует вложенные объекты и создаёт компактный JSON).
4

Подписание полезной нагрузки

HMAC-SHA256(key=secret, data=serializedContext)
5

Добавление токена

Добавьте полученный шестнадцатеричный дайджест в контекст как _token.
Пример на Python:
  • Python json.dumps по умолчанию добавляет пробелы ({"key": "val"}). Используйте separators=(",", ":"), чтобы результат соответствовал компактному выводу JavaScript ({"key":"val"}).
  • Всегда подписывайте все поля контекста (кроме _token). Gateway удаляет _token, а затем подписывает все оставшиеся поля. Подписание только части полей приводит к сбою проверки без сообщения об ошибке.
  • Используйте sort_keys=True: Gateway сортирует ключи перед подписанием, а Mattermost может изменить порядок полей контекста при сохранении полезной нагрузки.
  • Получайте секрет из токена бота детерминированным способом, а не генерируйте случайные байты. Секрет должен совпадать в процессе, который создает кнопки, и в Gateway, выполняющем проверку.

Адаптер каталога

Плагин Mattermost включает адаптер каталога, который разрешает имена каналов и пользователей через API Mattermost. Это позволяет использовать цели #channel-name и @username в openclaw message send, а также при доставке через Cron и Webhook. Настройка не требуется: адаптер использует токен бота из конфигурации учетной записи.

Несколько учетных записей

Mattermost поддерживает несколько учетных записей в channels.mattermost.accounts:
Значения учетной записи переопределяют поля верхнего уровня; channels.mattermost.defaultAccount определяет, какая учетная запись используется, если она не указана.

Устранение неполадок

Убедитесь, что бот добавлен в канал, и упомяните его (oncall), используйте префикс-триггер (onchar) либо задайте chatmode: "onmessage".
  • Проверьте токен бота, базовый URL и то, включена ли учетная запись.
  • Проблемы с несколькими учетными записями: переменные среды применяются только к учетной записи default.
  • Для частных или локальных хостов Mattermost требуется network.dangerouslyAllowPrivateNetwork: true (защита от SSRF по умолчанию блокирует частные IP-адреса).
  • Unauthorized: invalid command token.: OpenClaw не принял токен обратного вызова. Типичные причины:
    • регистрация команды с косой чертой завершилась с ошибкой или была выполнена лишь частично при запуске
    • обратный вызов поступает не в тот Gateway или не для той учетной записи
    • в Mattermost все еще сохранены старые команды, указывающие на предыдущую цель обратного вызова
    • Gateway перезапустился без повторной активации команд с косой чертой
  • Если встроенные команды с косой чертой перестали работать, проверьте наличие в журналах mattermost: failed to register slash commands или mattermost: native slash commands enabled but no commands could be registered.
  • Если callbackUrl не указан, а в журналах выводится предупреждение, что для обратного вызова определен loopback-URL, например http://localhost:18789/..., этот URL, вероятно, доступен только в том случае, если Mattermost работает на том же хосте или в том же сетевом пространстве имен, что и OpenClaw. Вместо него задайте явно доступный извне commands.callbackUrl.
  • Кнопки отображаются как белые прямоугольники или не отображаются вовсе: данные кнопок имеют неверный формат. Для каждой кнопки представления требуются label и value (кнопки без любого из этих значений отбрасываются).
  • Кнопки отображаются, но нажатия ничего не делают: убедитесь, что Gateway доступен с сервера Mattermost, IP-адрес сервера Mattermost включен в channels.mattermost.interactions.allowedSourceIps (без этого принимается только loopback-адрес), а ServiceSettings.AllowedUntrustedInternalConnections включает хост обратного вызова для частных целей.
  • При нажатии кнопки возвращается ошибка 404: значение id кнопки, вероятно, содержит дефисы или символы подчеркивания. Маршрутизатор действий Mattermost не работает с идентификаторами, содержащими не буквенно-цифровые символы. Используйте только [a-zA-Z0-9].
  • В журналах Gateway отображается rejected callback source: нажатие поступило с IP-адреса, не входящего в interactions.allowedSourceIps. Добавьте сервер Mattermost или точку входа в список разрешенных адресов и задайте gateway.trustedProxies при использовании обратного прокси.
  • В журналах Gateway отображается invalid _token: HMAC не совпадает. Убедитесь, что подписываются все поля контекста, а не только их часть, ключи сортируются и используется компактный JSON без пробелов. См. раздел о HMAC выше.
  • В журналах Gateway отображается missing _token in context: поле _token отсутствует в контексте кнопки. Убедитесь, что оно включено при формировании полезной нагрузки интеграции.
  • Gateway отклоняет нажатие с ошибкой Unknown action: context.action_id не соответствует ни одному действию id в публикации. Задайте для обоих одинаковое очищенное значение.
  • Агент не предлагает кнопки: добавьте capabilities: ["inlineButtons"] в конфигурацию канала Mattermost.

Связанные материалы