Developer and self-hosted
Mattermost
Status: Plugin do pobrania (token bota + zdarzenia WebSocket). Obsługiwane są kanały, grupy i wiadomości DM. Mattermost to platforma do zespołowej komunikacji, którą można hostować samodzielnie; szczegóły produktu i pliki do pobrania znajdziesz na oficjalnej stronie mattermost.com.
Instalacja
Zainstaluj Mattermost przed skonfigurowaniem kanału:
npm registry
openclaw plugins install @openclaw/mattermost
Local checkout
openclaw plugins install ./path/to/local/mattermost-plugin
Szczegóły: Plugins
Szybka konfiguracja
Ensure plugin is available
Bieżące pakietowane wydania OpenClaw już go zawierają. Starsze lub niestandardowe instalacje mogą dodać go ręcznie za pomocą powyższych poleceń.
Create a Mattermost bot
Utwórz konto bota Mattermost i skopiuj token bota.
Copy the base URL
Skopiuj bazowy URL Mattermost (np. https://chat.example.com).
Configure OpenClaw and start the gateway
Minimalna konfiguracja:
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
Natywne polecenia slash
Natywne polecenia slash są opcjonalne. Po włączeniu OpenClaw rejestruje polecenia slash oc_* przez API Mattermost i odbiera żądania zwrotne POST na serwerze 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"domyślnie jest wyłączone dla Mattermost. Ustawnative: true, aby włączyć.- Jeśli
callbackUrlzostanie pominięty, OpenClaw wyprowadzi go z hosta/portu Gateway +callbackPath. - W konfiguracjach z wieloma kontami
commandsmożna ustawić na najwyższym poziomie albo podchannels.mattermost.accounts.<id>.commands(wartości konta zastępują pola najwyższego poziomu). - Żądania zwrotne poleceń są weryfikowane za pomocą tokenów poszczególnych poleceń zwróconych przez Mattermost, gdy OpenClaw rejestruje polecenia
oc_*. - OpenClaw odświeża bieżącą rejestrację poleceń Mattermost przed zaakceptowaniem każdego żądania zwrotnego, więc nieaktualne tokeny z usuniętych lub ponownie wygenerowanych poleceń slash przestają być akceptowane bez restartu Gateway.
- Walidacja żądania zwrotnego jest domyślnie odrzucana, jeśli API Mattermost nie może potwierdzić, że polecenie jest nadal aktualne; nieudane walidacje są krótko buforowane, równoczesne wyszukiwania są łączone, a rozpoczęcia świeżych wyszukiwań są limitowane według polecenia, aby ograniczyć presję powtórek.
- Żądania zwrotne slash są odrzucane, gdy rejestracja się nie powiodła, uruchomienie było częściowe albo token żądania zwrotnego nie pasuje do zarejestrowanego tokenu rozpoznanego polecenia (token ważny dla jednego polecenia nie może przejść walidacji upstream dla innego polecenia).
Reachability requirement
Punkt końcowy żądania zwrotnego musi być osiągalny z serwera Mattermost.
- Nie ustawiaj
callbackUrlnalocalhost, chyba że Mattermost działa na tym samym hoście/przestrzeni nazw sieci co OpenClaw. - Nie ustawiaj
callbackUrlna bazowy URL Mattermost, chyba że ten URL przekierowuje przez reverse proxy/api/channels/mattermost/commanddo OpenClaw. - Szybki test to
curl https://<gateway-host>/api/channels/mattermost/command; GET powinien zwrócić z OpenClaw405 Method Not Allowed, a nie404.
Mattermost egress allowlist
Jeśli żądanie zwrotne wskazuje adresy prywatne/tailnet/wewnętrzne, ustaw Mattermost ServiceSettings.AllowedUntrustedInternalConnections tak, aby zawierało host/domenę żądania zwrotnego.
Użyj wpisów hosta/domeny, a nie pełnych URL-i.
- Dobrze:
gateway.tailnet-name.ts.net - Źle:
https://gateway.tailnet-name.ts.net
Zmienne środowiskowe (konto domyślne)
Ustaw je na hoście Gateway, jeśli wolisz zmienne środowiskowe:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Tryby czatu
Mattermost odpowiada na DM-y automatycznie. Zachowaniem kanału steruje chatmode:
oncall (default)
Odpowiadaj tylko po @wzmiance w kanałach.
onmessage
Odpowiadaj na każdą wiadomość w kanale.
onchar
Odpowiadaj, gdy wiadomość zaczyna się od prefiksu wyzwalającego.
Przykład konfiguracji:
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
Uwagi:
oncharnadal odpowiada na jawne @wzmianki.channels.mattermost.requireMentionjest respektowane dla starszych konfiguracji, ale preferowane jestchatmode.
Wątki i sesje
Użyj channels.mattermost.replyToMode, aby kontrolować, czy odpowiedzi w kanałach i grupach pozostają w głównym kanale, czy rozpoczynają wątek pod postem wyzwalającym.
off(domyślnie): odpowiadaj w wątku tylko wtedy, gdy przychodzący post już w nim jest.first: dla postów najwyższego poziomu w kanale/grupie rozpocznij wątek pod tym postem i przekieruj rozmowę do sesji ograniczonej do wątku.all: obecnie takie samo zachowanie jakfirstdla Mattermost.- Wiadomości bezpośrednie ignorują to ustawienie i pozostają bez wątków.
Przykład konfiguracji:
{
channels: {
mattermost: {
replyToMode: "all",
},
},
}
Uwagi:
- Sesje ograniczone do wątku używają identyfikatora posta wyzwalającego jako korzenia wątku.
firstiallsą obecnie równoważne, ponieważ gdy Mattermost ma korzeń wątku, kolejne fragmenty i media są kontynuowane w tym samym wątku.
Kontrola dostępu (DM-y)
- Domyślnie:
channels.mattermost.dmPolicy = "pairing"(nieznani nadawcy otrzymują kod parowania). - Zatwierdzanie przez:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Publiczne DM-y:
channels.mattermost.dmPolicy="open"pluschannels.mattermost.allowFrom=["*"].
Kanały (grupy)
- Domyślnie:
channels.mattermost.groupPolicy = "allowlist"(bramkowane wzmianką). - Dodaj nadawców do listy dozwolonych przez
channels.mattermost.groupAllowFrom(zalecane identyfikatory użytkowników). - Zastąpienia wzmianek dla poszczególnych kanałów znajdują się pod
channels.mattermost.groups.<channelId>.requireMentionalbochannels.mattermost.groups["*"].requireMentionjako wartość domyślna. - Dopasowywanie
@usernamejest zmienne i włączone tylko wtedy, gdychannels.mattermost.dangerouslyAllowNameMatching: true. - Otwarte kanały:
channels.mattermost.groupPolicy="open"(bramkowane wzmianką). - Uwaga dotycząca środowiska uruchomieniowego: jeśli
channels.mattermostcałkowicie brakuje, środowisko uruchomieniowe używa awaryjniegroupPolicy="allowlist"dla kontroli grup (nawet jeśli ustawionochannels.defaults.groupPolicy).
Przykład:
{
channels: {
mattermost: {
groupPolicy: "open",
groups: {
"*": { requireMention: true },
"team-channel-id": { requireMention: false },
},
},
},
}
Cele dla dostarczania wychodzącego
Użyj tych formatów celów z openclaw message send albo cron/webhooks:
channel:<id>dla kanałuuser:<id>dla DM@usernamedla DM (rozpoznawane przez API Mattermost)
Ponawianie kanału DM
Gdy OpenClaw wysyła do celu DM Mattermost i musi najpierw rozpoznać kanał bezpośredni, domyślnie ponawia przejściowe błędy tworzenia kanału bezpośredniego.
Użyj channels.mattermost.dmChannelRetry, aby dostroić to zachowanie globalnie dla Plugin Mattermost, albo channels.mattermost.accounts.<id>.dmChannelRetry dla jednego konta.
{
channels: {
mattermost: {
dmChannelRetry: {
maxRetries: 3,
initialDelayMs: 1000,
maxDelayMs: 10000,
timeoutMs: 30000,
},
},
},
}
Uwagi:
- Dotyczy to tylko tworzenia kanału DM (
/api/v4/channels/direct), a nie każdego wywołania API Mattermost. - Ponowienia dotyczą przejściowych błędów, takich jak limity szybkości, odpowiedzi 5xx oraz błędy sieci lub przekroczenia czasu.
- Błędy klienta 4xx inne niż
429są traktowane jako trwałe i nie są ponawiane.
Strumieniowanie podglądu
Mattermost strumieniuje myślenie, aktywność narzędzi i częściowy tekst odpowiedzi do jednego roboczego posta podglądu, który jest finalizowany w miejscu, gdy końcowa odpowiedź jest bezpieczna do wysłania. Podgląd jest aktualizowany na tym samym identyfikatorze posta zamiast zasypywać kanał wiadomościami dla każdego fragmentu. Końcowe wiadomości z mediami/błędami anulują oczekujące edycje podglądu i używają normalnego dostarczania zamiast opróżniać jednorazowy post podglądu.
Włącz przez channels.mattermost.streaming:
{
channels: {
mattermost: {
streaming: "partial", // off | partial | block | progress
},
},
}
Streaming modes
partialto zwykły wybór: jeden post podglądu, który jest edytowany w miarę narastania odpowiedzi, a następnie finalizowany kompletną odpowiedzią.blockużywa roboczych fragmentów w stylu dopisywania wewnątrz posta podglądu.progresspokazuje podgląd statusu podczas generowania i publikuje końcową odpowiedź dopiero po zakończeniu.offwyłącza strumieniowanie podglądu.
Streaming behavior notes
- Jeśli strumienia nie można sfinalizować w miejscu (na przykład post został usunięty w trakcie strumieniowania), OpenClaw awaryjnie wysyła świeży post końcowy, aby odpowiedź nigdy nie została utracona.
- Ładunki zawierające tylko rozumowanie są ukrywane w postach kanału, w tym tekst przychodzący jako cytat blokowy
> Reasoning:. Ustaw/reasoning on, aby widzieć myślenie w innych powierzchniach; końcowy post Mattermost zachowuje tylko odpowiedź. - Zobacz Strumieniowanie, aby poznać macierz mapowania kanałów.
Reakcje (narzędzie wiadomości)
- Użyj
message action=reactzchannel=mattermost. messageIdto identyfikator posta Mattermost.emojiprzyjmuje nazwy takie jakthumbsupalbo:+1:(dwukropki są opcjonalne).- Ustaw
remove=true(wartość logiczna), aby usunąć reakcję. - Zdarzenia dodania/usunięcia reakcji są przekazywane jako zdarzenia systemowe do skierowanej sesji agenta.
Przykłady:
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
Konfiguracja:
channels.mattermost.actions.reactions: włącza/wyłącza akcje reakcji (domyślnie true).- Zastąpienie dla konta:
channels.mattermost.accounts.<id>.actions.reactions.
Interaktywne przyciski (narzędzie wiadomości)
Wysyłaj wiadomości z klikalnymi przyciskami. Gdy użytkownik kliknie przycisk, agent otrzymuje wybór i może odpowiedzieć.
Włącz przyciski, dodając inlineButtons do możliwości kanału:
{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}
Użyj message action=send z parametrem buttons. Przyciski są tablicą 2D (wiersze przycisków):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
Pola przycisków:
textstringrequiredEtykieta wyświetlana.
callback_datastringrequiredWartość odsyłana po kliknięciu (używana jako ID akcji).
style"default" | "primary" | "danger"Styl przycisku.
Gdy użytkownik kliknie przycisk:
Przyciski zastąpione potwierdzeniem
Wszystkie przyciski są zastępowane wierszem potwierdzenia (np. „✓ Yes selected by @user”).
Agent otrzymuje wybór
Agent otrzymuje wybór jako wiadomość przychodzącą i odpowiada.
Uwagi dotyczące implementacji
- Callbacki przycisków używają weryfikacji HMAC-SHA256 (automatycznie, bez wymaganej konfiguracji).
- Mattermost usuwa dane callbacku ze swoich odpowiedzi API (funkcja bezpieczeństwa), więc wszystkie przyciski są usuwane po kliknięciu - częściowe usunięcie nie jest możliwe.
- ID akcji zawierające łączniki lub podkreślenia są automatycznie oczyszczane (ograniczenie routingu Mattermost).
Konfiguracja i osiągalność
channels.mattermost.capabilities: tablica ciągów funkcji. Dodaj"inlineButtons", aby włączyć opis narzędzia przycisków w systemowym prompcie agenta.channels.mattermost.interactions.callbackBaseUrl: opcjonalny zewnętrzny bazowy URL dla callbacków przycisków (na przykładhttps://gateway.example.com). Użyj tego, gdy Mattermost nie może bezpośrednio połączyć się z gatewayem pod jego hostem wiązania.- W konfiguracjach z wieloma kontami możesz też ustawić to samo pole pod
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Jeśli
interactions.callbackBaseUrlzostanie pominięte, OpenClaw wyprowadza URL callbacku zgateway.customBindHost+gateway.port, a następnie wraca dohttp://localhost:<port>. - Reguła osiągalności: URL callbacku przycisku musi być osiągalny z serwera Mattermost.
localhostdziała tylko wtedy, gdy Mattermost i OpenClaw działają na tym samym hoście/przestrzeni nazw sieci. - Jeśli cel callbacku jest prywatny/tailnet/wewnętrzny, dodaj jego host/domenę do
ServiceSettings.AllowedUntrustedInternalConnectionsMattermost.
Bezpośrednia integracja API (skrypty zewnętrzne)
Skrypty zewnętrzne i Webhooki mogą publikować przyciski bezpośrednio przez Mattermost REST API zamiast przez narzędzie message agenta. Gdy to możliwe, używaj buildButtonAttachments() z Plugin; jeśli publikujesz surowy JSON, przestrzegaj tych reguł:
Struktura ładunku:
{
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
},
},
},
],
},
],
},
}
Generowanie tokenu HMAC
Gateway weryfikuje kliknięcia przycisków za pomocą HMAC-SHA256. Skrypty zewnętrzne muszą generować tokeny zgodne z logiką weryfikacji gatewaya:
Wyprowadź sekret z tokenu bota
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
Zbuduj obiekt kontekstu
Zbuduj obiekt kontekstu ze wszystkimi polami oprócz _token.
Serializuj z posortowanymi kluczami
Serializuj z posortowanymi kluczami i bez spacji (gateway używa JSON.stringify z posortowanymi kluczami, co tworzy kompaktowe wyjście).
Podpisz ładunek
HMAC-SHA256(key=secret, data=serializedContext)
Dodaj token
Dodaj wynikowy skrót szesnastkowy jako _token w kontekście.
Przykład w Pythonie:
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}
Typowe pułapki HMAC
- Pythonowe
json.dumpsdomyślnie dodaje spacje ({"key": "val"}). Użyjseparators=(",", ":"), aby dopasować kompaktowe wyjście JavaScript ({"key":"val"}). - Zawsze podpisuj wszystkie pola kontekstu (bez
_token). Gateway usuwa_token, a następnie podpisuje wszystko, co pozostało. Podpisanie podzbioru powoduje cichą porażkę weryfikacji. - Użyj
sort_keys=True- gateway sortuje klucze przed podpisaniem, a Mattermost może zmienić kolejność pól kontekstu podczas przechowywania ładunku. - Wyprowadź sekret z tokenu bota (deterministycznie), a nie z losowych bajtów. Sekret musi być taki sam w procesie tworzącym przyciski i w gatewayu, który je weryfikuje.
Adapter katalogu
Plugin Mattermost zawiera adapter katalogu, który rozwiązuje nazwy kanałów i użytkowników przez Mattermost API. Umożliwia to używanie celów #channel-name i @username w openclaw message send oraz dostawach Cron/Webhook.
Konfiguracja nie jest potrzebna - adapter używa tokenu bota z konfiguracji konta.
Wiele kont
Mattermost obsługuje wiele kont pod 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" },
},
},
},
}
Rozwiązywanie problemów
Brak odpowiedzi w kanałach
Upewnij się, że bot jest w kanale, i wspomnij go (oncall), użyj prefiksu wyzwalacza (onchar) albo ustaw chatmode: "onmessage".
Błędy uwierzytelniania lub wielu kont
- Sprawdź token bota, bazowy URL oraz czy konto jest włączone.
- Problemy z wieloma kontami: zmienne środowiskowe dotyczą tylko konta
default.
Natywne polecenia ukośnikowe zawodzą
Unauthorized: invalid command token.: OpenClaw nie zaakceptował tokenu callbacku. Typowe przyczyny:- rejestracja polecenia ukośnikowego nie powiodła się lub została ukończona tylko częściowo podczas uruchamiania
- callback trafia do niewłaściwego gatewaya/konta
- Mattermost nadal ma stare polecenia wskazujące poprzedni cel callbacku
- gateway został ponownie uruchomiony bez ponownej aktywacji poleceń ukośnikowych
- Jeśli natywne polecenia ukośnikowe przestaną działać, sprawdź logi pod kątem
mattermost: failed to register slash commandslubmattermost: native slash commands enabled but no commands could be registered. - Jeśli
callbackUrljest pominięte, a logi ostrzegają, że callback został rozwiązany dohttp://127.0.0.1:18789/..., ten URL prawdopodobnie jest osiągalny tylko wtedy, gdy Mattermost działa na tym samym hoście/przestrzeni nazw sieci co OpenClaw. Zamiast tego ustaw jawne, zewnętrznie osiągalnecommands.callbackUrl.
Problemy z przyciskami
- Przyciski pojawiają się jako białe pola: agent może wysyłać nieprawidłowo sformowane dane przycisków. Sprawdź, czy każdy przycisk ma pola
texticallback_data. - Przyciski są renderowane, ale kliknięcia nic nie robią: sprawdź, czy
AllowedUntrustedInternalConnectionsw konfiguracji serwera Mattermost obejmuje127.0.0.1 localhostoraz czyEnablePostActionIntegrationma wartośćtruew ServiceSettings. - Przyciski zwracają 404 po kliknięciu:
idprzycisku prawdopodobnie zawiera łączniki lub podkreślenia. Router akcji Mattermost psuje się na ID niealfanumerycznych. Używaj tylko[a-zA-Z0-9]. - Logi gatewaya pokazują
invalid _token: niezgodność HMAC. Sprawdź, czy podpisujesz wszystkie pola kontekstu (nie podzbiór), używasz posortowanych kluczy i kompaktowego JSON (bez spacji). Zobacz sekcję HMAC powyżej. - Logi gatewaya pokazują
missing _token in context: pola_tokennie ma w kontekście przycisku. Upewnij się, że jest dołączone podczas budowania ładunku integracji. - Potwierdzenie pokazuje surowe ID zamiast nazwy przycisku:
context.action_idnie odpowiadaidprzycisku. Ustaw oba na tę samą oczyszczoną wartość. - Agent nie wie o przyciskach: dodaj
capabilities: ["inlineButtons"]do konfiguracji kanału Mattermost.
Powiązane
- Routing kanałów - routing sesji dla wiadomości
- Przegląd kanałów - wszystkie obsługiwane kanały
- Grupy - zachowanie czatu grupowego i bramkowanie wzmianek
- Parowanie - uwierzytelnianie DM i przepływ parowania
- Bezpieczeństwo - model dostępu i wzmacnianie zabezpieczeń