Zum Inhalt springen

OpenClaw mit Mattermost verbinden: Schnelle Einrichtung

Mattermost wird als Plugin bereitgestellt und ist nicht in der Core-Installation enthalten. Am besten installierst du es direkt über die CLI (npm registry):

Terminal-Fenster
openclaw plugins install @openclaw/mattermost

Falls du mit einem lokalen Git-Repo arbeitest, kannst du den lokalen Pfad nutzen:

Terminal-Fenster
openclaw plugins install ./path/to/local/mattermost-plugin

Wenn du Mattermost während des Setups auswählst und ein Git-Checkout erkannt wird, bietet OpenClaw dir den lokalen Installationspfad automatisch an.

Details findest du hier: Plugins

  1. Installiere das Mattermost-Plugin.
  2. Erstelle einen Mattermost-Bot-Account und kopiere das bot token.
  3. Kopiere die Mattermost base URL (z. B. https://chat.example.com).
  4. Konfiguriere OpenClaw und starte das Gateway.

Minimale Konfiguration:

{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}

Native Slash-Commands sind optional. Wenn du sie aktivierst, registriert OpenClaw oc_* Slash-Commands über die Mattermost API und empfängt Callback-POSTs auf dem Gateway-HTTP-Server.

{
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",
},
},
},
}

Hinweise:

  • native: "auto" ist für Mattermost standardmäßig deaktiviert. Setze native: true, um es zu aktivieren.
  • Wenn callbackUrl fehlt, leitet OpenClaw die URL aus dem Gateway-Host/Port und dem callbackPath ab.
  • Bei Setups mit mehreren Accounts kannst du commands global oder unter channels.mattermost.accounts.<id>.commands definieren (Account-Werte überschreiben globale Felder).
  • Command-Callbacks werden mit Tokens pro Befehl validiert und schlagen fehl, wenn die Prüfung nicht erfolgreich ist.
  • Erreichbarkeit: Der Callback-Endpunkt muss vom Mattermost-Server aus erreichbar sein.
    • Setze callbackUrl nicht auf localhost, außer Mattermost läuft auf demselben Host oder im selben Netzwerk-Namespace wie OpenClaw.
    • Setze callbackUrl nicht auf deine Mattermost-Base-URL, außer diese URL leitet /api/channels/mattermost/command per Reverse-Proxy an OpenClaw weiter.
    • Ein schneller Test: curl https://<gateway-host>/api/channels/mattermost/command; ein GET sollte von OpenClaw ein 405 Method Not Allowed zurückgeben, kein 404.
  • Mattermost Egress-Allowlist:
    • Wenn dein Callback private, Tailnet- oder interne Adressen nutzt, musst du in den Mattermost-Einstellungen ServiceSettings.AllowedUntrustedInternalConnections den Callback-Host oder die Domain hinzufügen.
    • Nutze Host/Domain-Einträge, keine vollständigen URLs.
      • Gut: gateway.tailnet-name.ts.net
      • Schlecht: https://gateway.tailnet-name.ts.net

Falls du Umgebungsvariablen bevorzugst, kannst du diese auf dem Gateway-Host setzen:

  • MATTERMOST_BOT_TOKEN=...
  • MATTERMOST_URL=https://chat.example.com

Diese Variablen gelten nur für den Standard-Account (default). Für alle anderen Accounts musst du die Konfigurationswerte nutzen.

Mattermost antwortet automatisch auf DMs. Das Verhalten in Channels steuerst du über chatmode:

  • oncall (Standard): Antwortet nur, wenn du in Channels mit @ erwähnt wirst.
  • onmessage: Antwortet auf jede Nachricht im Channel.
  • onchar: Antwortet, wenn eine Nachricht mit einem bestimmten Präfix beginnt.

Konfigurationsbeispiel:

{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}

Hinweise:

  • onchar reagiert trotzdem auf explizite @mentions.
  • channels.mattermost.requireMention wird für Legacy-Konfigurationen unterstützt, aber chatmode ist die bessere Wahl.

Nutze channels.mattermost.replyToMode, um zu steuern, ob Antworten in Channels und Gruppen im Haupt-Channel bleiben oder einen Thread unter dem auslösenden Post starten.

  • off (Standard): Antwortet nur dann in einem Thread, wenn der eingehende Post bereits Teil eines Threads ist.
  • first: Erstellt bei Top-Level-Posts in Channels oder Gruppen einen Thread und leitet die Konversation in eine Session mit Thread-Scope.
  • all: Verhält sich aktuell genau wie first.
  • Direct messages ignorieren diese Einstellung und bleiben immer ohne Thread.

Konfigurationsbeispiel:

{
channels: {
mattermost: {
replyToMode: "all",
},
},
}

Hinweise:

  • Sessions mit Thread-Scope nutzen die ID des auslösenden Posts als Thread-Root.
  • first und all sind momentan identisch, da Mattermost nach der Erstellung eines Thread-Roots alle weiteren Chunks und Medien in demselben Thread fortführt.
  • Standard: channels.mattermost.dmPolicy = "pairing" (unbekannte Absender erhalten einen Pairing-Code).
  • Freigabe über:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • Öffentliche DMs: channels.mattermost.dmPolicy="open" plus channels.mattermost.allowFrom=["*"].
  • Standard: channels.mattermost.groupPolicy = "allowlist" (Zugriff nur per Mention).
  • Absender auf die Allowlist setzen mit channels.mattermost.groupAllowFrom (User-IDs werden empfohlen).
  • @username Matching ist veränderbar und nur aktiv, wenn channels.mattermost.dangerouslyAllowNameMatching: true gesetzt ist.
  • Offene Channels: channels.mattermost.groupPolicy="open" (ebenfalls per Mention gesteuert).
  • Runtime-Hinweis: Wenn channels.mattermost komplett fehlt, nutzt die Runtime automatisch groupPolicy="allowlist" für Gruppen-Checks (selbst wenn channels.defaults.groupPolicy konfiguriert ist).

Nutze diese Zielformate mit openclaw message send oder Cron/Webhooks:

  • channel:<id> für einen Channel
  • user:<id> für eine DM
  • @username für eine DM (aufgelöst über die Mattermost API)

Einfache IDs (wie 64ifufp...) sind in Mattermost nicht eindeutig, da sie sowohl eine User-ID als auch eine Channel-ID sein könnten.

OpenClaw löst diese nach dem Prinzip „User zuerst“ auf:

  • Wenn die ID als User existiert (GET /api/v4/users/<id> ist erfolgreich), sendet OpenClaw eine DM, indem der direkte Channel über /api/v4/channels/direct ermittelt wird.
  • Andernfalls wird die ID als Channel-ID behandelt.

Wenn du ein eindeutiges Verhalten willst, solltest du immer die expliziten Präfixe (user:<id> oder channel:<id>) verwenden.

Wenn OpenClaw an ein Mattermost DM-Ziel sendet und zuerst den direkten Channel auflösen muss, werden vorübergehende Fehler bei der Erstellung des direkten Channels standardmäßig wiederholt.

Nutze channels.mattermost.dmChannelRetry, um dieses Verhalten global für das Mattermost-Plugin zu konfigurieren, oder channels.mattermost.accounts.<id>.dmChannelRetry für einen spezifischen Account.

{
channels: {
mattermost: {
dmChannelRetry: {
maxRetries: 3,
initialDelayMs: 1000,
maxDelayMs: 10000,
timeoutMs: 30000,
},
},
},
}

Hinweise:

  • Das gilt nur für die Erstellung von DM-Channels (/api/v4/channels/direct) und nicht für jeden beliebigen Mattermost API-Aufruf.
  • Wiederholungen erfolgen bei vorübergehenden Fehlern wie Rate Limits, 5xx-Antworten sowie Netzwerk- oder Timeout-Problemen.
  • 4xx-Client-Fehler (außer 429) gelten als dauerhaft und werden nicht erneut versucht.
  • Nutze message action=react mit channel=mattermost.
  • messageId ist die Mattermost Post-ID.
  • emoji akzeptiert Namen wie thumbsup oder :+1: (Doppelpunkte sind optional).
  • Setze remove=true (Boolean), um eine Reaktion zu entfernen.
  • Events zum Hinzufügen oder Entfernen von Reaktionen werden als System-Events an die Session des Agents weitergeleitet.

Beispiele:

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

Konfiguration:

  • channels.mattermost.actions.reactions: Aktiviert oder deaktiviert Reaktions-Aktionen (Standard ist true).
  • Override pro Account: channels.mattermost.accounts.<id>.actions.reactions.

Sende Nachrichten mit klickbaren Buttons. Wenn ein User auf einen Button klickt, erhält der Agent die Auswahl und kann darauf antworten.

Aktiviere Buttons, indem du inlineButtons zu den Channel-Capabilities hinzufügst:

{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}

Nutze message action=send mit einem buttons Parameter. Buttons sind ein 2D-Array (Reihen von Buttons):

message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]

Button-Felder:

  • text (erforderlich): Anzeigename.
  • callback_data (erforderlich): Wert, der beim Klick zurückgesendet wird (wird als Action-ID genutzt).
  • style (optional): "default", "primary", "danger".

Wenn ein User auf einen Button klickt:

  1. Alle Buttons werden durch eine Bestätigungszeile ersetzt (z. B. ”✓ Yes ausgewählt von @user”).
  2. Der Agent erhält die Auswahl als eingehende Nachricht und antwortet.

Hinweise:

  • Button-Callbacks nutzen HMAC-SHA256 Verifizierung (automatisch, keine Konfiguration nötig).
  • Mattermost entfernt Callback-Daten aus seinen API-Antworten (Sicherheitsfeature), daher werden beim Klick alle Buttons entfernt — ein teilweises Entfernen ist nicht möglich.
  • Action-IDs mit Bindestrichen oder Unterstrichen werden automatisch bereinigt (eine Einschränkung beim Mattermost-Routing).

Konfiguration:

  • channels.mattermost.capabilities: Array aus Capability-Strings. Füge "inlineButtons" hinzu, um die Beschreibung des Button-Tools im System-Prompt des Agents zu aktivieren.
  • channels.mattermost.interactions.callbackBaseUrl: Optionale externe Basis-URL für Button-Callbacks (zum Beispiel https://gateway.example.com). Nutze dies, wenn Mattermost das Gateway nicht direkt über den Bind-Host erreichen kann.
  • In Setups mit mehreren Accounts kannst du dasselbe Feld auch unter channels.mattermost.accounts.<id>.interactions.callbackBaseUrl setzen.
  • Wenn interactions.callbackBaseUrl fehlt, leitet OpenClaw die Callback-URL von gateway.customBindHost + gateway.port ab und nutzt sonst http://localhost:<port>.
  • Erreichbarkeit: Die Button-Callback-URL muss vom Mattermost-Server aus erreichbar sein. localhost funktioniert nur, wenn Mattermost und OpenClaw auf demselben Host oder im selben Netzwerk-Namespace laufen.
  • Wenn dein Callback-Ziel privat, ein Tailnet oder intern ist, füge den Host oder die Domain zu ServiceSettings.AllowedUntrustedInternalConnections in Mattermost hinzu.

Externe Skripte und Webhooks können Buttons direkt über die Mattermost REST API posten, anstatt das message Tool des Agents zu nutzen. Nutze nach Möglichkeit buildButtonAttachments() aus der Extension; wenn du rohes JSON postest, folge diesen Regeln:

Payload-Struktur:

{
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
},
},
},
],
},
],
},
}

Wichtige Regeln:

  1. Attachments gehören in props.attachments, nicht in das Top-Level-Feld attachments (wird sonst ignoriert).
  2. Jede Action braucht type: "button" — ohne diesen Typ werden Klicks einfach ignoriert.
  3. Jede Action braucht ein id Feld — Mattermost ignoriert Actions ohne IDs.
  4. Die Action-id darf nur alphanumerisch sein ([a-zA-Z0-9]). Bindestriche und Unterstriche stören das serverseitige Routing von Mattermost (führt zu 404). Entferne sie vor der Nutzung.
  5. context.action_id muss mit der id des Buttons übereinstimmen, damit die Bestätigungsnachricht den Button-Namen (z. B. “Approve”) statt einer ID anzeigt.
  6. context.action_id ist erforderlich — der Interaction-Handler gibt ohne diesen Wert einen 400-Fehler zurück.

HMAC-Token-Generierung:

Das Gateway verifiziert Button-Klicks mit HMAC-SHA256. Externe Skripte müssen Token generieren, die zur Verifizierungslogik des Gateways passen:

  1. Leite das Secret vom Bot-Token ab: HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
  2. Erstelle das Context-Objekt mit allen Feldern außer _token.
  3. Serialisiere es mit sortierten Keys und ohne Leerzeichen (das Gateway nutzt JSON.stringify mit sortierten Keys für kompakten Output).
  4. Signiere: HMAC-SHA256(key=secret, data=serializedContext)
  5. Füge den resultierenden Hex-Digest als _token zum Context hinzu.

Python-Beispiel:

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}

Häufige HMAC-Fehler:

  • Pythons json.dumps fügt standardmäßig Leerzeichen hinzu ({"key": "val"}). Nutze separators=(",", ":"), um den kompakten JavaScript-Output zu erzeugen ({"key":"val"}).
  • Signiere immer alle Context-Felder (außer _token). Das Gateway entfernt _token und signiert den Rest. Wenn du nur einen Teil signierst, schlägt die Verifizierung fehl.
  • Nutze sort_keys=True — das Gateway sortiert Keys vor dem Signieren, und Mattermost könnte die Reihenfolge beim Speichern ändern.
  • Leite das Secret vom Bot-Token ab (deterministisch), nicht von Zufallswerten. Das Secret muss beim Erstellen der Buttons und beim Gateway identisch sein.

AI Setup Assistant

Das Mattermost-Plugin enthält einen Directory-Adapter, der Channel- und Benutzernamen über die Mattermost API auflöst. Das ermöglicht dir die Nutzung von #channel-name und @username als Ziele in openclaw message send sowie bei automatisierten Zustellungen über Cron-Jobs oder Webhooks.

Du musst dafür nichts extra konfigurieren — der Adapter nutzt einfach das Bot-Token aus deiner Account-Konfiguration.

Mattermost unterstützt mehrere Accounts unter channels.mattermost.accounts. Ich empfehle diesen Aufbau, wenn du verschiedene Teams oder Umgebungen sauber voneinander trennen möchtest:

{
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" },
},
},
},
}
  • Keine Antworten in Channels: Stell sicher, dass der Bot im Channel ist, erwähne ihn (oncall), nutze einen Trigger-Präfix (onchar) oder setze chatmode: "onmessage".
  • Auth-Fehler: Prüfe das Bot-Token und die Base-URL.
  • Probleme mit mehreren Accounts: Umgebungsvariablen gelten nur für den default Account.
  • Buttons erscheinen als weiße Boxen: Der Agent sendet eventuell fehlerhafte Button-Daten. Prüfe, ob jeder Button sowohl text als auch callback_data Felder hat.
  • Buttons werden angezeigt, aber Klicks bewirken nichts: Verifiziere, dass AllowedUntrustedInternalConnections in der Mattermost-Serverkonfiguration 127.0.0.1 localhost enthält und EnablePostActionIntegration in den ServiceSettings auf true steht.
  • Buttons geben beim Klick einen 404-Fehler zurück: Die Button-id enthält wahrscheinlich Bindestriche oder Unterstriche. Der Action-Router von Mattermost bricht bei nicht-alphanumerischen IDs ab. Nutze nur [a-zA-Z0-9].
  • Gateway loggt invalid _token: HMAC-Abweichung. Prüfe, ob du alle Context-Felder signierst, sortierte Keys verwendest, kompaktes JSON nutzt und keine Leerzeichen einfügst. Schau dir dazu den HMAC-Abschnitt oben an.
  • Gateway loggt missing _token in context: Das _token-Feld fehlt im Context des Buttons. Stell sicher, dass es beim Erstellen des Integration-Payloads enthalten ist.
  • Die Bestätigung zeigt die rohe ID statt des Button-Namens: context.action_id stimmt nicht mit der Button-id überein. Setze beide auf denselben bereinigten Wert.
  • Agent weiß nichts von Buttons: Füge capabilities: ["inlineButtons"] zur Mattermost-Channel-Konfiguration hinzu.

AI Setup Assistant

OpenClaw

OpenClaw Expert

Noch festgefahren?

Wenn diese Seite nicht hilft, frage OpenClaw Expert nach Schritt-fuer-Schritt-Loesungen.