Mattermost (plugin)
Status: obslugiwany przez plugin (token bota + zdarzenia WebSocket). Kanaly, grupy i DM sa obslugiwane. Mattermost to samodzielnie hostowalnia platforma wiadomosci zespolowych; zobacz oficjalna strone na mattermost.com po szczegoly produktu i pliki do pobrania.
Wymagany plugin
Mattermost jest dostarczany jako plugin i nie jest dolaczony do instalacji podstawowej.
Instalacja przez CLI (rejestr npm):
openclaw plugins install @openclaw/mattermost
Lokalny checkout (przy uruchomieniu z repozytorium git):
openclaw plugins install ./extensions/mattermost
Jesli wybierzesz Mattermost podczas konfiguracji/onboardingu i zostanie wykryty checkout git, OpenClaw automatycznie zaproponuje sciezke instalacji lokalnej.
Szczegoly: Pluginy
Szybka konfiguracja
- Zainstaluj plugin Mattermost.
- Utworz konto bota Mattermost i skopiuj token bota.
- Skopiuj bazowy URL Mattermost (np.
https://chat.example.com). - Skonfiguruj OpenClaw i uruchom gateway.
Minimalna konfiguracja:
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
Natywne polecenia slash
Natywne polecenia slash sa wlaczane na zadanie. Po wlaczeniu OpenClaw rejestruje polecenia slash oc_* przez
API Mattermost i odbiera callbackowe POST-y na serwerze HTTP gateway.
{
channels: {
mattermost: {
commands: {
native: true,
nativeSkills: true,
callbackPath: "/api/channels/mattermost/command",
// Uzyj gdy Mattermost nie moze bezposrednio osiagnac gateway (reverse proxy/publiczny URL).
callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
},
},
},
}
Uwagi:
native: "auto"domyslnie jest wylaczone dla Mattermost. Ustawnative: trueaby wlaczyc.- Jesli
callbackUrljest pominiety, OpenClaw wyprowadza go z hosta/portu gateway +callbackPath. - W konfiguracjach wielokontowych
commandsmoze byc ustawione na najwyzszym poziomie lub podchannels.mattermost.accounts.<id>.commands(wartosci konta nadpisuja pola najwyzszego poziomu). - Callbacki polecen sa walidowane tokenami per polecenie i odrzucaja zamkniete gdy sprawdzenie tokenu nie powiedzie sie.
- Wymog osiagalnosci: endpoint callbacku musi byc osiagalny z serwera Mattermost.
- Nie ustawiaj
callbackUrlnalocalhost, chyba ze Mattermost dziala na tym samym hoscie/przestrzeni sieciowej co OpenClaw. - Nie ustawiaj
callbackUrlna bazowy URL Mattermost, chyba ze ten URL proxyuje/api/channels/mattermost/commanddo OpenClaw. - Szybkie sprawdzenie:
curl https://<gateway-host>/api/channels/mattermost/command; GET powinien zwrocic405 Method Not Allowedz OpenClaw, nie404.
- Nie ustawiaj
- Wymog listy dozwolonych egress Mattermost:
- Jesli twoj callback celuje w prywatne/tailnetowe/wewnetrzne adresy, ustaw Mattermost
ServiceSettings.AllowedUntrustedInternalConnectionsaby zawieral host/domene callbacku. - Uzywaj wpisow host/domena, nie pelnych URL-i.
- Dobrze:
gateway.tailnet-name.ts.net - Zle:
https://gateway.tailnet-name.ts.net
- Dobrze:
- Jesli twoj callback celuje w prywatne/tailnetowe/wewnetrzne adresy, ustaw Mattermost
Zmienne srodowiskowe (domyslne konto)
Ustaw je na hoscie gateway jesli wolisz zmienne srodowiskowe:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Zmienne srodowiskowe dotycza tylko domyslnego konta (default). Inne konta musza uzywac wartosci konfiguracji.
Tryby czatu
Mattermost odpowiada na DM automatycznie. Zachowanie kanalow jest kontrolowane przez chatmode:
oncall(domyslnie): odpowiadaj tylko gdy @wspomniano na kanalach.onmessage: odpowiadaj na kazda wiadomosc kanalu.onchar: odpowiadaj gdy wiadomosc zaczyna sie od prefiksu wyzwalajacego.
Przyklad konfiguracji:
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
Uwagi:
oncharnadal odpowiada na jawne @wzmianki.channels.mattermost.requireMentionjest honorowane dla starszych konfiguracji, ale preferowany jestchatmode.
Watkowanie i sesje
Uzyj channels.mattermost.replyToMode aby kontrolowac, czy odpowiedzi na kanalach i grupach pozostaja na
glownym kanale czy zaczynaja watek pod postem wyzwalajacym.
off(domyslnie): odpowiadaj w watku tylko gdy post przychodzacy juz jest w watku.first: dla postow kanalowych/grupowych najwyzszego poziomu, zacznij watek pod tym postem i kieruj rozmowe do sesji o zakresie watku.all: takie samo zachowanie jakfirstdla Mattermost dzisiaj.- Wiadomosci bezposrednie ignoruja to ustawienie i pozostaja bez watkow.
Przyklad konfiguracji:
{
channels: {
mattermost: {
replyToMode: "all",
},
},
}
Uwagi:
- Sesje o zakresie watku uzywaja ID postu wyzwalajacego jako korzenia watku.
firstiallsa obecnie rownowazne, poniewaz gdy Mattermost ma korzen watku, kolejne fragmenty i media kontynuuja w tym samym watku.
Kontrola dostepu (DM)
- Domyslnie:
channels.mattermost.dmPolicy = "pairing"(nieznani nadawcy otrzymuja kod parowania). - Zatwierdzanie przez:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- Publiczne DM:
channels.mattermost.dmPolicy="open"pluschannels.mattermost.allowFrom=["*"].
Kanaly (grupy)
- Domyslnie:
channels.mattermost.groupPolicy = "allowlist"(bramkowane wzmiankami). - Dodaj nadawcow do listy dozwolonych przez
channels.mattermost.groupAllowFrom(zalecane ID uzytkownikow). - Dopasowywanie
@usernamejest zmienne i wlaczane tylko gdychannels.mattermost.dangerouslyAllowNameMatching: true. - Otwarte kanaly:
channels.mattermost.groupPolicy="open"(bramkowane wzmiankami). - Uwaga runtime: jesli
channels.mattermostcalkowicie brakuje, runtime stosuje zastepczymgroupPolicy="allowlist"dla sprawdzen grupowych (nawet jeslichannels.defaults.groupPolicyjest ustawione).
Cele dostarczania wychodzacego
Uzyj tych formatow celow z openclaw message send lub cron/webhookami:
channel:<id>dla kanaluuser:<id>dla DM@usernamedla DM (rozwiazywane przez API Mattermost)
Nagie nieprzejrzyste ID (jak 64ifufp...) sa niejednoznaczne w Mattermost (ID uzytkownika vs ID kanalu).
OpenClaw rozwiazuje je najpierw jako uzytkownika:
- Jesli ID istnieje jako uzytkownik (
GET /api/v4/users/<id>sie powiedzie), OpenClaw wysyla DM przez rozwiazanie bezposredniego kanalu przez/api/v4/channels/direct. - W przeciwnym razie ID jest traktowane jako ID kanalu.
Jesli potrzebujesz deterministycznego zachowania, zawsze uzywaj jawnych prefiksow (user:<id> / channel:<id>).
Reakcje (narzedzie wiadomosci)
- Uzyj
message action=reactzchannel=mattermost. messageIdto ID postu Mattermost.emojiakceptuje nazwy jakthumbsuplub:+1:(dwukropki sa opcjonalne).- Ustaw
remove=true(boolean) aby usunac reakcje. - Zdarzenia dodawania/usuwania reakcji sa przekazywane jako zdarzenia systemowe do sesji routowanego agenta.
Przyklady:
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: wlaczenie/wylaczenie akcji reakcji (domyslnie true).- Nadpisanie per konto:
channels.mattermost.accounts.<id>.actions.reactions.
Interaktywne przyciski (narzedzie wiadomosci)
Wysylaj wiadomosci z klicalnymi przyciskami. Gdy uzytkownik kliknie przycisk, agent otrzymuje wybor i moze odpowiedziec.
Wlacz przyciski dodajac inlineButtons do mozliwosci kanalu:
{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}
Uzyj message action=send z parametrem buttons. Przyciski to tablica 2D (wiersze przyciskow):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
Pola przyciskow:
text(wymagane): etykieta wyswietlania.callback_data(wymagane): wartosc wyslana po kliknieciu (uzywana jako ID akcji).style(opcjonalne):"default","primary"lub"danger".
Gdy uzytkownik kliknie przycisk:
- Wszystkie przyciski sa zastepowane linia potwierdzenia (np. “Wybrano Yes przez @user”).
- Agent otrzymuje wybor jako wiadomosc przychodzaca i odpowiada.
Uwagi:
- Callbacki przyciskow uzywaja weryfikacji HMAC-SHA256 (automatycznie, bez konfiguracji).
- Mattermost usuwa callback data ze swoich odpowiedzi API (funkcja bezpieczenstwa), wiec wszystkie przyciski sa usuwane po kliknieciu — czesciowe usuwanie nie jest mozliwe.
- ID akcji zawierajace myslniki lub podkreslenia sa automatycznie sanityzowane (ograniczenie routingu Mattermost).
Konfiguracja:
channels.mattermost.capabilities: tablica ciagu mozliwosci. Dodaj"inlineButtons"aby wlaczyc opis narzedzia przyciskow w promptcie systemowym agenta.channels.mattermost.interactions.callbackBaseUrl: opcjonalny zewnetrzny bazowy URL dla callbackow przyciskow (np.https://gateway.example.com). Uzyj gdy Mattermost nie moze osiagnac gateway bezposrednio po hoscie powiazania.- W konfiguracjach wielokontowych mozesz rowniez ustawic to samo pole pod
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Jesli
interactions.callbackBaseUrljest pominiety, OpenClaw wyprowadza URL callbacku zgateway.customBindHost+gateway.port, nastepnie stosuje zastepczymhttp://localhost:<port>. - Regula osiagalnosci: URL callbacku przyciskow musi byc osiagalny z serwera Mattermost.
localhostdziala tylko gdy Mattermost i OpenClaw dzialaja na tym samym hoscie/przestrzeni sieciowej. - Jesli twoj cel callbacku jest prywatny/tailnetowy/wewnetrzny, dodaj jego host/domene do Mattermost
ServiceSettings.AllowedUntrustedInternalConnections.
Bezposrednia integracja API (skrypty zewnetrzne)
Zewnetrzne skrypty i webhooki moga publikowac przyciski bezposrednio przez REST API Mattermost
zamiast przechodzic przez narzedzie message agenta. Uzyj buildButtonAttachments() z
rozszerzenia gdy to mozliwe; jesli publikujesz surowy JSON, przestrzegaj tych zasad:
Struktura payloadu:
{
channel_id: "<channelId>",
message: "Choose an option:",
props: {
attachments: [
{
actions: [
{
id: "mybutton01", // tylko alfanumeryczne — zobacz nizej
type: "button", // wymagane, inaczej klikniecia sa cicho ignorowane
name: "Approve", // etykieta wyswietlania
style: "primary", // opcjonalnie: "default", "primary", "danger"
integration: {
url: "https://gateway.example.com/mattermost/interactions/default",
context: {
action_id: "mybutton01", // musi pasowac do id przycisku (dla wyszukania nazwy)
action: "approve",
// ... dowolne niestandardowe pola ...
_token: "<hmac>", // zobacz sekcje HMAC ponizej
},
},
},
],
},
],
},
}
Krytyczne zasady:
- Zalaczniki ida w
props.attachments, nie wattachmentsnajwyzszego poziomu (cicho ignorowane). - Kazda akcja potrzebuje
type: "button"— bez tego klikniecia sa cicho polykane. - Kazda akcja potrzebuje pola
id— Mattermost ignoruje akcje bez ID. idakcji musi byc tylko alfanumeryczne ([a-zA-Z0-9]). Myslniki i podkreslenia lamia routing akcji po stronie serwera Mattermost (zwraca 404). Usun je przed uzyciem.context.action_idmusi pasowac doidprzycisku, aby wiadomosc potwierdzenia pokazywala nazwe przycisku (np. “Approve”) zamiast surowego ID.context.action_idjest wymagane — handler interakcji zwraca 400 bez niego.
Generowanie tokenu HMAC:
Gateway weryfikuje klikniecia przyciskow za pomoca HMAC-SHA256. Zewnetrzne skrypty musza generowac tokeny pasujace do logiki weryfikacji gateway:
- Wyprowadz sekret z tokenu bota:
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken) - Zbuduj obiekt context ze wszystkimi polami oprocz
_token. - Serializuj z posortowanymi kluczami i bez spacji (gateway uzywa
JSON.stringifyz posortowanymi kluczami, co produkuje kompaktowe wyjscie). - Podpisz:
HMAC-SHA256(key=secret, data=serializedContext) - Dodaj wynikowy hex digest jako
_tokenw kontekscie.
Przyklad 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}
Czeste pulapki HMAC:
json.dumpsPythona domyslnie dodaje spacje ({"key": "val"}). Uzyjseparators=(",", ":")aby dopasowac kompaktowe wyjscie JavaScript ({"key":"val"}).- Zawsze podpisuj wszystkie pola kontekstu (minus
_token). Gateway usuwa_tokennastepnie podpisuje wszystko pozostale. Podpisywanie podzbiorow powoduje cicha awarie weryfikacji. - Uzyj
sort_keys=True— gateway sortuje klucze przed podpisywaniem, a Mattermost moze zmienic kolejnosc pol kontekstu podczas przechowywania payloadu. - Wyprowadz sekret z tokenu bota (deterministycznie), nie z losowych bajtow. Sekret musi byc taki sam w procesie tworzacym przyciski i gateway weryfikujacym.
Adapter katalogu
Plugin Mattermost zawiera adapter katalogu, ktory rozwiazuje nazwy kanalow i uzytkownikow
przez API Mattermost. Umozliwia to cele #channel-name i @username w
openclaw message send i dostarczaniu cron/webhook.
Konfiguracja nie jest potrzebna — adapter uzywa tokenu bota z konfiguracji konta.
Wiele kont
Mattermost obsluguje 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" },
},
},
},
}
Rozwiazywanie problemow
- Brak odpowiedzi na kanalach: upewnij sie, ze bot jest na kanale i wspomnij go (oncall), uzyj prefiksu wyzwalajacego (onchar) lub ustaw
chatmode: "onmessage". - Bledy autoryzacji: sprawdz token bota, bazowy URL i czy konto jest wlaczone.
- Problemy z wieloma kontami: zmienne srodowiskowe dotycza tylko konta
default. - Przyciski wyswietlaja sie jako biale pola: agent moze wysylac zle sformatowane dane przyciskow. Sprawdz, czy kazdy przycisk ma pola
texticallback_data. - Przyciski sie renderuja, ale klikniecia nic nie robia: zweryfikuj
AllowedUntrustedInternalConnectionsw konfiguracji serwera Mattermost zawiera127.0.0.1 localhosti zeEnablePostActionIntegrationjesttruew ServiceSettings. - Przyciski zwracaja 404 po kliknieciu:
idprzycisku prawdopodobnie zawiera myslniki lub podkreslenia. Router akcji Mattermost lamie sie na niealfanumerycznych ID. Uzywaj tylko[a-zA-Z0-9]. - Logi gateway
invalid _token: niezgodnosc HMAC. Sprawdz, ze podpisujesz wszystkie pola kontekstu (nie podzbiory), uzywasz posortowanych kluczy i kompaktowego JSON (bez spacji). Zobacz sekcje HMAC powyzej. - Logi gateway
missing _token in context: pole_tokennie jest w kontekscie przycisku. Upewnij sie, ze jest dolaczone przy budowaniu payloadu integracji. - Potwierdzenie pokazuje surowe ID zamiast nazwy przycisku:
context.action_idnie pasuje doidprzycisku. Ustaw oba na ta sama sanityzowana wartosc. - Agent nie wie o przyciskach: dodaj
capabilities: ["inlineButtons"]do konfiguracji kanalu Mattermost.