Mattermost (Plugin)

Status: Unterstützt via Plugin (Bot-Token + WebSocket-Events). Kanäle, Gruppen und DMs werden unterstützt. Mattermost ist eine selbst-hostbare Team-Messaging-Plattform; Produktdetails und Downloads findest du auf der offiziellen Seite unter mattermost.com.

Plugin erforderlich

Mattermost wird als Plugin ausgeliefert und ist nicht in der Kerninstallation enthalten.

Installation über CLI (npm-Registry):

openclaw plugins install @openclaw/mattermost

Lokaler Checkout (wenn aus einem Git-Repo ausgeführt):

openclaw plugins install ./extensions/mattermost

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

Details: Plugins

Schnelleinrichtung

  1. Installiere das Mattermost-Plugin.
  2. Erstelle ein Mattermost-Bot-Konto und kopiere den Bot-Token.
  3. Kopiere die Mattermost-Basis-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-Befehle

Native Slash-Befehle sind Opt-in. Wenn aktiviert, registriert OpenClaw oc_*-Slash-Befehle ü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",
        // Verwende wenn Mattermost das Gateway nicht direkt erreichen kann (Reverse Proxy/öffentliche URL).
        callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
      },
    },
  },
}

Hinweise:

  • native: "auto" ist für Mattermost standardmäßig deaktiviert. Setze native: true zum Aktivieren.
  • Wenn callbackUrl weggelassen wird, leitet OpenClaw eine aus Gateway-Host/Port + callbackPath ab.
  • Für Multi-Account-Setups kann commands auf Top-Level oder unter channels.mattermost.accounts.<id>.commands gesetzt werden (Kontowerte überschreiben Top-Level-Felder).
  • Befehls-Callbacks werden mit Pro-Befehls-Tokens validiert und schlagen bei fehlender Token-Prüfung geschlossen fehl.
  • Erreichbarkeitsanforderung: Der Callback-Endpunkt muss vom Mattermost-Server erreichbar sein.
    • Setze callbackUrl nicht auf localhost, es sei denn, Mattermost läuft auf demselben Host/Netzwerk-Namespace wie OpenClaw.
    • Setze callbackUrl nicht auf deine Mattermost-Basis-URL, es sei denn, diese URL leitet /api/channels/mattermost/command per Reverse Proxy an OpenClaw weiter.
    • Ein schneller Test ist curl https://<gateway-host>/api/channels/mattermost/command; ein GET sollte 405 Method Not Allowed von OpenClaw zurückgeben, nicht 404.
  • Mattermost-Egress-Allowlist-Anforderung:
    • Wenn dein Callback private/Tailnet-/interne Adressen anspricht, setze Mattermosts ServiceSettings.AllowedUntrustedInternalConnections auf den Callback-Host/die Domain.
    • Verwende Host-/Domain-Einträge, keine vollständigen URLs.
      • Richtig: gateway.tailnet-name.ts.net
      • Falsch: https://gateway.tailnet-name.ts.net

Umgebungsvariablen (Standardkonto)

Setze diese auf dem Gateway-Host, wenn du Umgebungsvariablen bevorzugst:

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

Umgebungsvariablen gelten nur für das Standard-Konto (default). Andere Konten müssen Konfigurationswerte verwenden.

Chat-Modi

Mattermost antwortet auf DMs automatisch. Das Kanalverhalten wird durch chatmode gesteuert:

  • oncall (Standard): Nur bei @Mention in Kanälen antworten.
  • onmessage: Auf jede Kanalnachricht antworten.
  • onchar: Antworten, wenn eine Nachricht mit einem Trigger-Präfix beginnt.

Konfigurationsbeispiel:

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

Hinweise:

  • onchar antwortet weiterhin auf explizite @Mentions.
  • channels.mattermost.requireMention wird für Legacy-Konfigurationen berücksichtigt, aber chatmode ist bevorzugt.

Threading und Sessions

Verwende channels.mattermost.replyToMode, um zu steuern, ob Kanal- und Gruppenantworten im Hauptkanal bleiben oder einen Thread unter dem auslösenden Beitrag starten.

  • off (Standard): Nur in einem Thread antworten, wenn der eingehende Beitrag bereits in einem ist.
  • first: Für Top-Level-Kanal-/Gruppenbeiträge einen Thread unter diesem Beitrag starten und die Konversation in eine Thread-bezogene Session leiten.
  • all: Gleiches Verhalten wie first für Mattermost derzeit.
  • Direktnachrichten ignorieren diese Einstellung und bleiben ohne Thread.

Konfigurationsbeispiel:

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

Hinweise:

  • Thread-bezogene Sessions verwenden die auslösende Beitrags-ID als Thread-Root.
  • first und all sind derzeit gleichwertig, da Mattermost nach einem Thread-Root Folge-Chunks und Medien im selben Thread fortsetzt.

Zugriffssteuerung (DMs)

  • Standard: channels.mattermost.dmPolicy = "pairing" (unbekannte Absender erhalten einen Pairing-Code).
  • Genehmigung über:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • Öffentliche DMs: channels.mattermost.dmPolicy="open" plus channels.mattermost.allowFrom=["*"].

Kanäle (Gruppen)

  • Standard: channels.mattermost.groupPolicy = "allowlist" (Mention-gated).
  • Absender auf die Allowlist setzen mit channels.mattermost.groupAllowFrom (Benutzer-IDs empfohlen).
  • @username-Matching ist veränderlich und nur aktiviert, wenn channels.mattermost.dangerouslyAllowNameMatching: true.
  • Offene Kanäle: channels.mattermost.groupPolicy="open" (Mention-gated).
  • Laufzeithinweis: Wenn channels.mattermost vollständig fehlt, fällt die Laufzeit für Gruppenprüfungen auf groupPolicy="allowlist" zurück (auch wenn channels.defaults.groupPolicy gesetzt ist).

Ziele für ausgehende Zustellung

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

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

Nackte opake IDs (wie 64ifufp...) sind in Mattermost mehrdeutig (Benutzer-ID vs. Kanal-ID).

OpenClaw löst sie Benutzer-zuerst auf:

  • Wenn die ID als Benutzer existiert (GET /api/v4/users/<id> erfolgreich), sendet OpenClaw eine DM durch Auflösen des direkten Kanals via /api/v4/channels/direct.
  • Andernfalls wird die ID als Kanal-ID behandelt.

Wenn du deterministisches Verhalten brauchst, verwende immer die expliziten Präfixe (user:<id> / channel:<id>).

Reaktionen (Nachrichten-Tool)

  • Verwende message action=react mit channel=mattermost.
  • messageId ist die Mattermost-Beitrags-ID.
  • emoji akzeptiert Namen wie thumbsup oder :+1: (Doppelpunkte optional).
  • Setze remove=true (Boolean), um eine Reaktion zu entfernen.
  • Reaktions-Hinzufüge-/Entferne-Events werden als Systemereignisse an die geroutete Agent-Session 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: Reaktionsaktionen aktivieren/deaktivieren (Standard true).
  • Pro-Konto-Überschreibung: channels.mattermost.accounts.<id>.actions.reactions.

Interaktive Buttons (Nachrichten-Tool)

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

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

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

Verwende message action=send mit einem buttons-Parameter. Buttons sind ein 2D-Array (Zeilen 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): Anzeigetext.
  • callback_data (erforderlich): Wert, der bei Klick zurückgesendet wird (als Aktions-ID verwendet).
  • style (optional): "default", "primary" oder "danger".

Wenn ein Benutzer auf einen Button klickt:

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

Hinweise:

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

Konfiguration:

  • channels.mattermost.capabilities: Array von Capability-Strings. Füge "inlineButtons" hinzu, um die Button-Tool-Beschreibung im Agent-Systemprompt zu aktivieren.
  • channels.mattermost.interactions.callbackBaseUrl: Optionale externe Basis-URL für Button-Callbacks (z. B. https://gateway.example.com). Verwende dies, wenn Mattermost das Gateway nicht direkt am Bind-Host erreichen kann.
  • In Multi-Account-Setups kannst du dasselbe Feld unter channels.mattermost.accounts.<id>.interactions.callbackBaseUrl setzen.
  • Wenn interactions.callbackBaseUrl weggelassen wird, leitet OpenClaw die Callback-URL aus gateway.customBindHost + gateway.port ab, Fallback auf http://localhost:<port>.
  • Erreichbarkeitsregel: Die Button-Callback-URL muss vom Mattermost-Server erreichbar sein. localhost funktioniert nur, wenn Mattermost und OpenClaw auf demselben Host/Netzwerk-Namespace laufen.
  • Wenn dein Callback-Ziel privat/Tailnet/intern ist, füge dessen Host/Domain zu Mattermosts ServiceSettings.AllowedUntrustedInternalConnections hinzu.

Direkte API-Integration (externe Skripte)

Externe Skripte und Webhooks können Buttons direkt über die Mattermost REST API posten, anstatt durch das message-Tool des Agenten zu gehen. Verwende buildButtonAttachments() aus der Extension wenn möglich; beim Posten von rohem JSON beachte diese Regeln:

Payload-Struktur:

{
  channel_id: "<channelId>",
  message: "Choose an option:",
  props: {
    attachments: [
      {
        actions: [
          {
            id: "mybutton01", // nur alphanumerisch — siehe unten
            type: "button", // erforderlich, sonst werden Klicks stillschweigend ignoriert
            name: "Approve", // Anzeigetext
            style: "primary", // optional: "default", "primary", "danger"
            integration: {
              url: "https://gateway.example.com/mattermost/interactions/default",
              context: {
                action_id: "mybutton01", // muss mit Button-ID übereinstimmen (für Namenssuche)
                action: "approve",
                // ... benutzerdefinierte Felder ...
                _token: "<hmac>", // siehe HMAC-Abschnitt unten
              },
            },
          },
        ],
      },
    ],
  },
}

Kritische Regeln:

  1. Attachments gehören in props.attachments, nicht in Top-Level-attachments (wird stillschweigend ignoriert).
  2. Jede Aktion braucht type: "button" — ohne werden Klicks stillschweigend verschluckt.
  3. Jede Aktion braucht ein id-Feld — Mattermost ignoriert Aktionen ohne IDs.
  4. Aktions-id muss nur alphanumerisch sein ([a-zA-Z0-9]). Bindestriche und Unterstriche brechen Mattermosts serverseitiges Action-Routing (gibt 404 zurück). Vor Verwendung entfernen.
  5. context.action_id muss mit der id des Buttons übereinstimmen, damit die Bestätigungsnachricht den Button-Namen (z. B. „Approve”) anstelle einer rohen ID zeigt.
  6. context.action_id ist erforderlich — der Interaction-Handler gibt 400 ohne zurück.

HMAC-Token-Generierung:

Das Gateway verifiziert Button-Klicks mit HMAC-SHA256. Externe Skripte müssen Tokens generieren, die der Verifizierungslogik des Gateways entsprechen:

  1. Leite das Secret vom Bot-Token ab: HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
  2. Baue das Context-Objekt mit allen Feldern außer _token.
  3. Serialisiere mit sortierten Schlüsseln und ohne Leerzeichen (das Gateway verwendet JSON.stringify mit sortierten Schlüsseln, was kompakte Ausgabe erzeugt).
  4. Signiere: HMAC-SHA256(key=secret, data=serializedContext)
  5. Füge den resultierenden Hex-Digest als _token im Kontext 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-Fallstricke:

  • Pythons json.dumps fügt standardmäßig Leerzeichen hinzu ({"key": "val"}). Verwende separators=(",", ":"), um JavaScripts kompakte Ausgabe ({"key":"val"}) zu matchen.
  • Signiere immer alle Kontextfelder (minus _token). Das Gateway entfernt _token und signiert dann alles Verbleibende. Das Signieren einer Teilmenge verursacht stillschweigendes Verifizierungsfehlen.
  • Verwende sort_keys=True — das Gateway sortiert Schlüssel vor dem Signieren, und Mattermost kann Kontextfelder beim Speichern des Payloads umsortieren.
  • Leite das Secret vom Bot-Token ab (deterministisch), nicht von zufälligen Bytes. Das Secret muss im Prozess, der Buttons erstellt, und im Gateway, das verifiziert, identisch sein.

Verzeichnisadapter

Das Mattermost-Plugin enthält einen Verzeichnisadapter, der Kanal- und Benutzernamen über die Mattermost-API auflöst. Dies ermöglicht #channel-name- und @username-Ziele in openclaw message send und Cron-/Webhook-Zustellungen.

Keine Konfiguration erforderlich — der Adapter verwendet den Bot-Token aus der Kontokonfiguration.

Multi-Account

Mattermost unterstützt mehrere Konten unter 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" },
      },
    },
  },
}

Fehlerbehebung

  • Keine Antworten in Kanälen: Stelle sicher, dass der Bot im Kanal ist und ihn erwähnt (oncall), verwende ein Trigger-Präfix (onchar) oder setze chatmode: "onmessage".
  • Auth-Fehler: Bot-Token, Basis-URL und ob das Konto aktiviert ist, prüfen.
  • Multi-Account-Probleme: Umgebungsvariablen gelten nur für das default-Konto.
  • Buttons erscheinen als weiße Kästchen: Der Agent sendet möglicherweise fehlerhafte Button-Daten. Prüfe, ob jeder Button sowohl text- als auch callback_data-Felder hat.
  • Buttons werden gerendert, aber Klicks bewirken nichts: Prüfe AllowedUntrustedInternalConnections in der Mattermost-Serverkonfiguration auf 127.0.0.1 localhost, und dass EnablePostActionIntegration in ServiceSettings true ist.
  • Buttons geben 404 bei Klick zurück: Die Button-id enthält wahrscheinlich Bindestriche oder Unterstriche. Mattermosts Action-Router bricht bei nicht-alphanumerischen IDs. Verwende nur [a-zA-Z0-9].
  • Gateway protokolliert invalid _token: HMAC-Mismatch. Prüfe, ob du alle Kontextfelder (nicht nur eine Teilmenge) signierst, sortierte Schlüssel verwendest und kompaktes JSON (ohne Leerzeichen). Siehe den HMAC-Abschnitt oben.
  • Gateway protokolliert missing _token in context: Das _token-Feld fehlt im Kontext des Buttons. Stelle sicher, dass es beim Erstellen des Integration-Payloads enthalten ist.
  • Bestätigung zeigt rohe ID statt Button-Name: context.action_id stimmt nicht mit der id des Buttons überein. Setze beide auf denselben bereinigten Wert.
  • Agent kennt Buttons nicht: Füge capabilities: ["inlineButtons"] zur Mattermost-Kanalkonfiguration hinzu.