Developer and self-hosted

Mattermost

Status: herunterladbares Plugin (Bot-Token + WebSocket-Ereignisse). Kanäle, Gruppen und DMs werden unterstützt. Mattermost ist eine selbst hostbare Team-Messaging-Plattform; Produktdetails und Downloads finden Sie auf der offiziellen Website unter mattermost.com.

Installation

Installieren Sie Mattermost, bevor Sie den Kanal konfigurieren:

npm registry

openclaw plugins install @openclaw/mattermost

Local checkout

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

Details: Plugins

Schnelleinrichtung

  • Ensure plugin is available

    Aktuelle paketierte OpenClaw-Releases bündeln es bereits. Ältere/angepasste Installationen können es manuell mit den obigen Befehlen hinzufügen.

  • Create a Mattermost bot

    Erstellen Sie ein Mattermost-Bot-Konto und kopieren Sie das Bot-Token.

  • Copy the base URL

    Kopieren Sie die Mattermost-Basis-URL (z. B. https://chat.example.com).

  • Configure OpenClaw and start the 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 sie aktiviert sind, 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",
            // 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" ist für Mattermost standardmäßig deaktiviert. Setzen Sie native: true, um es zu aktivieren.
    • Wenn callbackUrl weggelassen wird, leitet OpenClaw eine aus Gateway-Host/-Port + callbackPath ab.
    • Bei Multi-Account-Setups kann commands auf oberster Ebene oder unter channels.mattermost.accounts.<id>.commands festgelegt werden (Account-Werte überschreiben Felder auf oberster Ebene).
    • Befehls-Callbacks werden mit den befehlsspezifischen Tokens validiert, die Mattermost zurückgibt, wenn OpenClaw oc_*-Befehle registriert.
    • OpenClaw aktualisiert die aktuelle Mattermost-Befehlsregistrierung, bevor jeder Callback akzeptiert wird, sodass veraltete Tokens aus gelöschten oder neu generierten Slash-Befehlen ohne Gateway-Neustart nicht mehr akzeptiert werden.
    • Die Callback-Validierung schlägt geschlossen fehl, wenn die Mattermost-API nicht bestätigen kann, dass der Befehl noch aktuell ist; fehlgeschlagene Validierungen werden kurz zwischengespeichert, gleichzeitige Lookups werden zusammengeführt, und Starts neuer Lookups werden pro Befehl ratenbegrenzt, um Replay-Druck zu begrenzen.
    • Slash-Callbacks schlagen geschlossen fehl, wenn die Registrierung fehlgeschlagen ist, der Start nur teilweise abgeschlossen wurde oder das Callback-Token nicht mit dem registrierten Token des aufgelösten Befehls übereinstimmt (ein für einen Befehl gültiges Token kann keine Upstream-Validierung für einen anderen Befehl erreichen).
    Reachability requirement

    Der Callback-Endpunkt muss vom Mattermost-Server aus erreichbar sein.

    • Setzen Sie callbackUrl nicht auf localhost, es sei denn, Mattermost läuft auf demselben Host/in demselben Netzwerk-Namespace wie OpenClaw.
    • Setzen Sie callbackUrl nicht auf Ihre Mattermost-Basis-URL, es sei denn, diese URL leitet /api/channels/mattermost/command per Reverse Proxy an OpenClaw weiter.
    • Eine schnelle Prüfung ist curl https://<gateway-host>/api/channels/mattermost/command; ein GET sollte von OpenClaw 405 Method Not Allowed zurückgeben, nicht 404.
    Mattermost egress allowlist

    Wenn Ihr Callback private/Tailnet/interne Adressen adressiert, setzen Sie Mattermost ServiceSettings.AllowedUntrustedInternalConnections so, dass der Callback-Host/die Callback-Domain enthalten ist.

    Verwenden Sie Host-/Domain-Einträge, keine vollständigen URLs.

    • Gut: gateway.tailnet-name.ts.net
    • Schlecht: https://gateway.tailnet-name.ts.net

    Umgebungsvariablen (Standard-Account)

    Setzen Sie diese auf dem Gateway-Host, wenn Sie Umgebungsvariablen bevorzugen:

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

    Chat-Modi

    Mattermost antwortet automatisch auf DMs. Das Verhalten in Kanälen wird durch chatmode gesteuert:

    oncall (default)

    Nur antworten, wenn in Kanälen eine @Erwähnung erfolgt.

    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 @Erwähnungen.
    • channels.mattermost.requireMention wird für Legacy-Konfigurationen berücksichtigt, aber chatmode wird bevorzugt.

    Threads und Sitzungen

    Verwenden Sie 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 Thread ist.
    • first: für Top-Level-Kanal-/Gruppenbeiträge einen Thread unter diesem Beitrag starten und die Unterhaltung an eine Thread-spezifische Sitzung routen.
    • all: derzeit dasselbe Verhalten wie first für Mattermost.
    • Direktnachrichten ignorieren diese Einstellung und bleiben ohne Thread.

    Konfigurationsbeispiel:

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

    Hinweise:

    • Thread-spezifische Sitzungen verwenden die ID des auslösenden Beitrags als Thread-Root.
    • first und all sind derzeit äquivalent, da Folge-Chunks und Medien in demselben Thread fortgesetzt werden, sobald Mattermost einen Thread-Root hat.

    Zugriffskontrolle (DMs)

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

    Kanäle (Gruppen)

    • Standard: channels.mattermost.groupPolicy = "allowlist" (erwähnungsgesteuert).
    • Absender mit channels.mattermost.groupAllowFrom zulassen (Benutzer-IDs empfohlen).
    • Erwähnungsüberschreibungen pro Kanal befinden sich unter channels.mattermost.groups.<channelId>.requireMention oder channels.mattermost.groups["*"].requireMention für einen Standardwert.
    • @username-Abgleich ist veränderlich und nur aktiviert, wenn channels.mattermost.dangerouslyAllowNameMatching: true.
    • Offene Kanäle: channels.mattermost.groupPolicy="open" (erwähnungsgesteuert).
    • 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).

    Beispiel:

    {
      channels: {
        mattermost: {
          groupPolicy: "open",
          groups: {
            "*": { requireMention: true },
            "team-channel-id": { requireMention: false },
          },
        },
      },
    }
    

    Ziele für ausgehende Zustellung

    Verwenden Sie 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)

    Wiederholung für DM-Kanäle

    Wenn OpenClaw an ein Mattermost-DM-Ziel sendet und zuerst den direkten Kanal auflösen muss, wiederholt es standardmäßig transiente Fehler bei der Erstellung direkter Kanäle.

    Verwenden Sie channels.mattermost.dmChannelRetry, um dieses Verhalten global für das Mattermost-Plugin abzustimmen, oder channels.mattermost.accounts.<id>.dmChannelRetry für einen Account.

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

    Hinweise:

    • Dies gilt nur für die Erstellung von DM-Kanälen (/api/v4/channels/direct), nicht für jeden Mattermost-API-Aufruf.
    • Wiederholungen gelten für transiente Fehler wie Ratenbegrenzungen, 5xx-Antworten sowie Netzwerk- oder Timeout-Fehler.
    • 4xx-Clientfehler außer 429 werden als dauerhaft behandelt und nicht wiederholt.

    Preview-Streaming

    Mattermost streamt Denken, Tool-Aktivität und partiellen Antworttext in einen einzelnen Entwurfsvorschau-Beitrag, der direkt finalisiert wird, wenn die endgültige Antwort sicher gesendet werden kann. Die Vorschau wird auf derselben Beitrags-ID aktualisiert, statt den Kanal mit Nachrichten pro Chunk zu überfluten. Medien-/Fehler-Endzustände brechen ausstehende Vorschau-Bearbeitungen ab und verwenden die normale Zustellung, statt einen wegwerfbaren Vorschau-Beitrag zu leeren.

    Aktivieren über channels.mattermost.streaming:

    {
      channels: {
        mattermost: {
          streaming: "partial", // off | partial | block | progress
        },
      },
    }
    
    Streaming modes
    • partial ist die übliche Wahl: ein Vorschau-Beitrag, der bearbeitet wird, während die Antwort wächst, und anschließend mit der vollständigen Antwort finalisiert wird.
    • block verwendet Entwurfs-Chunks im Anhängestil innerhalb des Vorschau-Beitrags.
    • progress zeigt während der Generierung eine Statusvorschau und postet erst bei Abschluss die endgültige Antwort.
    • off deaktiviert Preview-Streaming.
    Streaming behavior notes
    • Wenn der Stream nicht direkt finalisiert werden kann (zum Beispiel, weil der Beitrag mitten im Stream gelöscht wurde), fällt OpenClaw darauf zurück, einen neuen endgültigen Beitrag zu senden, damit die Antwort nie verloren geht.
    • Payloads, die nur Reasoning enthalten, werden in Kanalbeiträgen unterdrückt, einschließlich Text, der als > Reasoning:-Blockzitat eintrifft. Setzen Sie /reasoning on, um Denken in anderen Oberflächen zu sehen; der endgültige Mattermost-Beitrag enthält nur die Antwort.
    • Siehe Streaming für die Channel-Mapping-Matrix.

    Reaktionen (Nachrichten-Tool)

    • Verwenden Sie message action=react mit channel=mattermost.
    • messageId ist die Mattermost-Beitrags-ID.
    • emoji akzeptiert Namen wie thumbsup oder :+1: (Doppelpunkte sind optional).
    • Setzen Sie remove=true (boolesch), um eine Reaktion zu entfernen.
    • Ereignisse zum Hinzufügen/Entfernen von Reaktionen werden als Systemereignisse an die geroutete Agent-Sitzung 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 (standardmäßig true).
    • Überschreibung pro Account: channels.mattermost.accounts.<id>.actions.reactions.

    Interaktive Buttons (Nachrichten-Tool)

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

    Aktivieren Sie Buttons, indem Sie inlineButtons zu den Kanal-Capabilities hinzufügen:

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

    Verwenden Sie message action=send mit einem buttons-Parameter. Buttons sind ein 2D-Array (Button-Zeilen):

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

    Button-Felder:

    textstringrequired

    Anzeigebeschriftung.

    callback_datastringrequired

    Beim Klicken zurückgesendeter Wert (wird als Aktions-ID verwendet).

    style"default" | "primary" | "danger"

    Button-Stil.

    Wenn ein Benutzer auf einen Button klickt:

  • Buttons durch Bestätigung ersetzt

    Alle Buttons werden durch eine Bestätigungszeile ersetzt (z. B. „✓ Ja ausgewählt von @user“).

  • Agent erhält die Auswahl

    Der Agent erhält die Auswahl als eingehende Nachricht und antwortet.

  • Implementierungshinweise
    • Button-Callbacks verwenden HMAC-SHA256-Verifizierung (automatisch, keine Konfiguration erforderlich).
    • Mattermost entfernt Callback-Daten aus seinen API-Antworten (Sicherheitsfunktion), daher werden beim Klicken alle Buttons entfernt - teilweises Entfernen ist nicht möglich.
    • Aktions-IDs mit Bindestrichen oder Unterstrichen werden automatisch bereinigt (Mattermost-Routing-Einschränkung).
    Konfiguration und Erreichbarkeit
    • channels.mattermost.capabilities: Array von Capability-Zeichenfolgen. Fügen Sie "inlineButtons" hinzu, um die Beschreibung des Buttons-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). Verwenden Sie dies, wenn Mattermost das Gateway nicht direkt über dessen Bind-Host erreichen kann.
    • In Multi-Account-Setups können Sie dasselbe Feld auch unter channels.mattermost.accounts.<id>.interactions.callbackBaseUrl setzen.
    • Wenn interactions.callbackBaseUrl ausgelassen wird, leitet OpenClaw die Callback-URL aus gateway.customBindHost + gateway.port ab und fällt dann auf http://localhost:<port> zurück.
    • Erreichbarkeitsregel: Die Button-Callback-URL muss vom Mattermost-Server erreichbar sein. localhost funktioniert nur, wenn Mattermost und OpenClaw auf demselben Host/in demselben Netzwerk-Namespace ausgeführt werden.
    • Wenn Ihr Callback-Ziel privat/tailnet/intern ist, fügen Sie dessen Host/Domäne zu Mattermost ServiceSettings.AllowedUntrustedInternalConnections hinzu.

    Direkte API-Integration (externe Skripte)

    Externe Skripte und Webhooks können Buttons direkt über die Mattermost REST API posten, statt über das message-Tool des Agents zu gehen. Verwenden Sie nach Möglichkeit buildButtonAttachments() aus dem Plugin; wenn Sie rohes JSON posten, befolgen Sie diese 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
                  },
                },
              },
            ],
          },
        ],
      },
    }
    

    HMAC-Token-Generierung

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

  • Secret aus dem Bot-Token ableiten

    HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)

  • Context-Objekt erstellen

    Erstellen Sie das Context-Objekt mit allen Feldern außer _token.

  • Mit sortierten Schlüsseln serialisieren

    Serialisieren Sie mit sortierten Schlüsseln und ohne Leerzeichen (das Gateway verwendet JSON.stringify mit sortierten Schlüsseln, was eine kompakte Ausgabe erzeugt).

  • Payload signieren

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

  • Token hinzufügen

    Fügen Sie den resultierenden Hex-Digest als _token im Context hinzu.

  • Python-Beispiel:

    
    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"}). Verwenden Sie separators=(",", ":"), um die kompakte Ausgabe von JavaScript ({"key":"val"}) zu treffen.
    • Signieren Sie immer alle Context-Felder (minus _token). Das Gateway entfernt _token und signiert dann alles Verbleibende. Das Signieren einer Teilmenge verursacht einen stillschweigenden Verifizierungsfehler.
    • Verwenden Sie sort_keys=True - das Gateway sortiert Schlüssel vor dem Signieren, und Mattermost kann Context-Felder beim Speichern der Payload neu anordnen.
    • Leiten Sie das Secret aus dem Bot-Token ab (deterministisch), nicht aus 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 aktiviert #channel-name- und @username-Ziele in openclaw message send sowie bei Cron-/Webhook-Zustellungen.

    Es ist keine Konfiguration erforderlich - der Adapter verwendet das Bot-Token aus der Account-Konfiguration.

    Multi-Account

    Mattermost unterstützt mehrere Accounts 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

    Stellen Sie sicher, dass sich der Bot im Kanal befindet und erwähnen Sie ihn (oncall), verwenden Sie ein Trigger-Präfix (onchar), oder setzen Sie chatmode: "onmessage".

    Auth- oder Multi-Account-Fehler
    • Prüfen Sie das Bot-Token, die Basis-URL und ob der Account aktiviert ist.
    • Multi-Account-Probleme: Env-Vars gelten nur für den default-Account.
    Native Slash-Befehle schlagen fehl
    • Unauthorized: invalid command token.: OpenClaw hat das Callback-Token nicht akzeptiert. Typische Ursachen:
      • die Registrierung des Slash-Befehls ist beim Start fehlgeschlagen oder nur teilweise abgeschlossen
      • der Callback trifft das falsche Gateway/den falschen Account
      • Mattermost hat noch alte Befehle, die auf ein vorheriges Callback-Ziel zeigen
      • das Gateway wurde neu gestartet, ohne Slash-Befehle erneut zu aktivieren
    • Wenn native Slash-Befehle nicht mehr funktionieren, prüfen Sie die Logs auf mattermost: failed to register slash commands oder mattermost: native slash commands enabled but no commands could be registered.
    • Wenn callbackUrl ausgelassen wird und Logs warnen, dass der Callback zu http://127.0.0.1:18789/... aufgelöst wurde, ist diese URL wahrscheinlich nur erreichbar, wenn Mattermost auf demselben Host/in demselben Netzwerk-Namespace wie OpenClaw läuft. Setzen Sie stattdessen eine explizite extern erreichbare commands.callbackUrl.
    Button-Probleme
    • Buttons erscheinen als weiße Kästen: Der Agent sendet möglicherweise fehlerhafte Button-Daten. Prüfen Sie, dass jeder Button sowohl text- als auch callback_data-Felder hat.
    • Buttons werden gerendert, aber Klicks tun nichts: Verifizieren Sie, dass AllowedUntrustedInternalConnections in der Mattermost-Serverkonfiguration 127.0.0.1 localhost enthält und dass EnablePostActionIntegration in ServiceSettings true ist.
    • Buttons geben beim Klicken 404 zurück: Die Button-id enthält wahrscheinlich Bindestriche oder Unterstriche. Der Aktionsrouter von Mattermost bricht bei nicht alphanumerischen IDs. Verwenden Sie nur [a-zA-Z0-9].
    • Gateway-Logs invalid _token: HMAC-Abweichung. Prüfen Sie, dass Sie alle Context-Felder signieren (nicht nur eine Teilmenge), sortierte Schlüssel verwenden und kompaktes JSON (keine Leerzeichen) nutzen. Siehe den HMAC-Abschnitt oben.
    • Gateway-Logs missing _token in context: Das _token-Feld befindet sich nicht im Context des Buttons. Stellen Sie sicher, dass es beim Erstellen der Integrations-Payload enthalten ist.
    • Bestätigung zeigt rohe ID statt Button-Namen: context.action_id stimmt nicht mit der id des Buttons überein. Setzen Sie beide auf denselben bereinigten Wert.
    • Agent weiß nichts von Buttons: Fügen Sie capabilities: ["inlineButtons"] zur Mattermost-Kanalkonfiguration hinzu.

    Verwandte Themen