Mattermost (plugin)

Status: ondersteund via plugin (bottoken + WebSocket-events). Kanalen, groepen en DM’s worden ondersteund. Mattermost is een zelf te hosten teamberichtenplatform; zie de officiële site op mattermost.com voor productdetails en downloads.

Plugin vereist

Mattermost wordt als plugin geleverd en is niet gebundeld met de kerninstallatie.

Installeren via CLI (npm-register):

openclaw plugins install @openclaw/mattermost

Lokale checkout (vanuit een git-repo):

openclaw plugins install ./extensions/mattermost

Als je Mattermost kiest tijdens configureren/onboarding en een git-checkout wordt gedetecteerd, biedt OpenClaw automatisch het lokale installatiepad aan.

Details: Plugins

Snelle installatie

  1. Installeer de Mattermost-plugin.
  2. Maak een Mattermost-botaccount aan en kopieer het bottoken.
  3. Kopieer de Mattermost basis-URL (bijv. https://chat.example.com).
  4. Configureer OpenClaw en start de gateway.

Minimale configuratie:

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

Native slash-commando’s

Native slash-commando’s zijn opt-in. Wanneer ingeschakeld, registreert OpenClaw oc_* slash-commando’s via de Mattermost-API en ontvangt callback-POST’s op de 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",
      },
    },
  },
}

Opmerkingen:

  • native: "auto" staat standaard uitgeschakeld voor Mattermost. Stel native: true in om in te schakelen.
  • Als callbackUrl wordt weggelaten, leidt OpenClaw er een af van gatewayhost/poort + callbackPath.
  • Voor multi-account-opstellingen kan commands op het hoogste niveau of onder channels.mattermost.accounts.<id>.commands worden ingesteld (accountwaarden overschrijven velden op het hoogste niveau).
  • Command-callbacks worden gevalideerd met per-commando-tokens en falen gesloten wanneer tokencontroles mislukken.
  • Bereikbaarheidsvereiste: het callback-eindpunt moet bereikbaar zijn vanuit de Mattermost-server.
    • Stel callbackUrl niet in op localhost tenzij Mattermost op dezelfde host/netwerknamespace draait als OpenClaw.
    • Stel callbackUrl niet in op je Mattermost basis-URL tenzij die URL /api/channels/mattermost/command reverse-proxyt naar OpenClaw.
    • Een snelle controle is curl https://<gateway-host>/api/channels/mattermost/command; een GET zou 405 Method Not Allowed van OpenClaw moeten retourneren, niet 404.
  • Mattermost egress-allowlist-vereiste:
    • Als je callback gericht is op privé-/tailnet-/interne adressen, stel dan Mattermost ServiceSettings.AllowedUntrustedInternalConnections in om de callback-host/domein op te nemen.
    • Gebruik host-/domeinvermeldingen, geen volledige URL’s.
      • Goed: gateway.tailnet-name.ts.net
      • Fout: https://gateway.tailnet-name.ts.net

Omgevingsvariabelen (standaardaccount)

Stel deze in op de gatewayhost als je de voorkeur geeft aan omgevingsvariabelen:

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

Omgevingsvariabelen gelden alleen voor het standaardaccount (default). Andere accounts moeten configwaarden gebruiken.

Chatmodi

Mattermost reageert automatisch op DM’s. Kanaalgedrag wordt bepaald door chatmode:

  • oncall (standaard): reageer alleen wanneer @vermeld in kanalen.
  • onmessage: reageer op elk kanaalbericht.
  • onchar: reageer wanneer een bericht begint met een triggerprefix.

Configuratievoorbeeld:

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

Opmerkingen:

  • onchar reageert nog steeds op expliciete @-vermeldingen.
  • channels.mattermost.requireMention wordt gehonoreerd voor legacy-configs maar chatmode heeft de voorkeur.

Threading en sessies

Gebruik channels.mattermost.replyToMode om te bepalen of kanaal- en groepsantwoorden in het hoofdkanaal blijven of een thread starten onder de triggerpost.

  • off (standaard): antwoord alleen in een thread wanneer de inkomende post al in een thread staat.
  • first: voor posts op het hoogste niveau in kanalen/groepen, start een thread onder die post en routeer het gesprek naar een thread-scoped sessie.
  • all: zelfde gedrag als first voor Mattermost op dit moment.
  • Directe berichten negeren deze instelling en blijven zonder thread.

Configuratievoorbeeld:

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

Opmerkingen:

  • Thread-scoped sessies gebruiken het triggerpost-ID als thread-root.
  • first en all zijn momenteel equivalent omdat zodra Mattermost een thread-root heeft, vervolgchunks en media in dezelfde thread doorgaan.

Toegangscontrole (DM’s)

  • Standaard: channels.mattermost.dmPolicy = "pairing" (onbekende afzenders krijgen een koppelingscode).
  • Goedkeuren via:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • Openbare DM’s: channels.mattermost.dmPolicy="open" plus channels.mattermost.allowFrom=["*"].

Kanalen (groepen)

  • Standaard: channels.mattermost.groupPolicy = "allowlist" (mention-gated).
  • Sta afzenders toe met channels.mattermost.groupAllowFrom (gebruikers-ID’s aanbevolen).
  • @username-matching is veranderlijk en wordt alleen ingeschakeld wanneer channels.mattermost.dangerouslyAllowNameMatching: true.
  • Open kanalen: channels.mattermost.groupPolicy="open" (mention-gated).
  • Runtime-opmerking: als channels.mattermost volledig ontbreekt, valt de runtime terug op groupPolicy="allowlist" voor groepscontroles (zelfs als channels.defaults.groupPolicy is ingesteld).

Doelen voor uitgaande aflevering

Gebruik deze doelformaten met openclaw message send of cron/webhooks:

  • channel:<id> voor een kanaal
  • user:<id> voor een DM
  • @username voor een DM (opgelost via de Mattermost-API)

Kale ondoorzichtige ID’s (zoals 64ifufp...) zijn ambigu in Mattermost (gebruikers-ID vs. kanaal-ID).

OpenClaw lost ze gebruiker-eerst op:

  • Als het ID bestaat als gebruiker (GET /api/v4/users/<id> slaagt), stuurt OpenClaw een DM door het directe kanaal op te lossen via /api/v4/channels/direct.
  • Anders wordt het ID behandeld als een kanaal-ID.

Als je deterministisch gedrag nodig hebt, gebruik dan altijd de expliciete prefixen (user:<id> / channel:<id>).

Reacties (berichttool)

  • Gebruik message action=react met channel=mattermost.
  • messageId is het Mattermost post-ID.
  • emoji accepteert namen zoals thumbsup of :+1: (dubbele punten zijn optioneel).
  • Stel remove=true (boolean) in om een reactie te verwijderen.
  • Reactie toevoegen/verwijderen-events worden doorgestuurd als systeemevents naar de gerouteerde agentsessie.

Voorbeelden:

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

Configuratie:

  • channels.mattermost.actions.reactions: reactieacties in-/uitschakelen (standaard true).
  • Per-account-overschrijving: channels.mattermost.accounts.<id>.actions.reactions.

Interactieve knoppen (berichttool)

Stuur berichten met klikbare knoppen. Wanneer een gebruiker op een knop klikt, ontvangt de agent de selectie en kan reageren.

Schakel knoppen in door inlineButtons toe te voegen aan de kanaalmogelijkheden:

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

Gebruik message action=send met een buttons-parameter. Knoppen zijn een 2D-array (rijen van knoppen):

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

Knopvelden:

  • text (vereist): weergavelabel.
  • callback_data (vereist): waarde die teruggestuurd wordt bij klik (gebruikt als actie-ID).
  • style (optioneel): "default", "primary" of "danger".

Wanneer een gebruiker op een knop klikt:

  1. Alle knoppen worden vervangen door een bevestigingsregel (bijv. “Ja geselecteerd door @user”).
  2. De agent ontvangt de selectie als inkomend bericht en reageert.

Opmerkingen:

  • Knopcallbacks gebruiken HMAC-SHA256-verificatie (automatisch, geen configuratie nodig).
  • Mattermost verwijdert callback-data uit zijn API-antwoorden (beveiligingsfunctie), dus alle knoppen worden verwijderd bij klik — gedeeltelijke verwijdering is niet mogelijk.
  • Actie-ID’s met koppeltekens of underscores worden automatisch opgeschoond (Mattermost routeringslimitatie).

Configuratie:

  • channels.mattermost.capabilities: array van mogelijkheidsstrings. Voeg "inlineButtons" toe om de knoppentoolbeschrijving in de agent-systeemprompt in te schakelen.
  • channels.mattermost.interactions.callbackBaseUrl: optionele externe basis-URL voor knopcallbacks (bijv. https://gateway.example.com). Gebruik dit wanneer Mattermost de gateway niet direct kan bereiken op zijn bindhost.
  • In multi-account-opstellingen kun je hetzelfde veld ook instellen onder channels.mattermost.accounts.<id>.interactions.callbackBaseUrl.
  • Als interactions.callbackBaseUrl wordt weggelaten, leidt OpenClaw de callback-URL af van gateway.customBindHost + gateway.port, en valt terug op http://localhost:<port>.
  • Bereikbaarheidsregel: de knopcallback-URL moet bereikbaar zijn vanuit de Mattermost-server. localhost werkt alleen wanneer Mattermost en OpenClaw op dezelfde host/netwerknamespace draaien.
  • Als je callbackdoel privé/tailnet/intern is, voeg dan de host/het domein toe aan Mattermost ServiceSettings.AllowedUntrustedInternalConnections.

Directe API-integratie (externe scripts)

Externe scripts en webhooks kunnen knoppen rechtstreeks via de Mattermost REST API posten in plaats van via de message-tool van de agent. Gebruik waar mogelijk buildButtonAttachments() uit de extensie; als je ruwe JSON post, volg dan deze regels:

Payloadstructuur:

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

Kritische regels:

  1. Bijlagen gaan in props.attachments, niet op het hoogste niveau attachments (stilzwijgend genegeerd).
  2. Elke actie heeft type: "button" nodig — zonder dit worden klikken stilzwijgend genegeerd.
  3. Elke actie heeft een id-veld nodig — Mattermost negeert acties zonder ID’s.
  4. Actie-id moet alleen alfanumeriek zijn ([a-zA-Z0-9]). Koppeltekens en underscores breken de serverside actieroutering van Mattermost (retourneert 404). Verwijder ze voor gebruik.
  5. context.action_id moet overeenkomen met het id van de knop zodat het bevestigingsbericht de knopnaam toont (bijv. “Approve”) in plaats van een rauw ID.
  6. context.action_id is vereist — de interactie-handler retourneert 400 zonder dit.

HMAC-tokengeneratie:

De gateway verifieert knopklikken met HMAC-SHA256. Externe scripts moeten tokens genereren die overeenkomen met de verificatielogica van de gateway:

  1. Leid het geheim af van het bottoken: HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
  2. Bouw het contextobject met alle velden behalve _token.
  3. Serialiseer met gesorteerde sleutels en geen spaties (de gateway gebruikt JSON.stringify met gesorteerde sleutels, wat compacte uitvoer produceert).
  4. Onderteken: HMAC-SHA256(key=secret, data=serializedContext)
  5. Voeg de resulterende hex-digest toe als _token in de context.

Python-voorbeeld:

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}

Veelvoorkomende HMAC-valkuilen:

  • Python’s json.dumps voegt standaard spaties toe ({"key": "val"}). Gebruik separators=(",", ":") om overeen te komen met JavaScript’s compacte uitvoer ({"key":"val"}).
  • Onderteken altijd alle contextvelden (minus _token). De gateway verwijdert _token en ondertekent vervolgens al het resterende. Het ondertekenen van een subset veroorzaakt stille verificatiefout.
  • Gebruik sort_keys=True — de gateway sorteert sleutels voor het ondertekenen, en Mattermost kan contextvelden herschikken bij het opslaan van de payload.
  • Leid het geheim af van het bottoken (deterministisch), niet van willekeurige bytes. Het geheim moet hetzelfde zijn in het proces dat knoppen maakt en de gateway die verifieert.

Directory-adapter

De Mattermost-plugin bevat een directory-adapter die kanaal- en gebruikersnamen oplost via de Mattermost-API. Dit maakt #channel-name en @username doelen mogelijk in openclaw message send en cron/webhook-afleveringen.

Er is geen configuratie nodig — de adapter gebruikt het bottoken uit de accountconfiguratie.

Multi-account

Mattermost ondersteunt meerdere accounts onder 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" },
      },
    },
  },
}

Probleemoplossing

  • Geen antwoorden in kanalen: zorg ervoor dat de bot in het kanaal zit en vermeld hem (oncall), gebruik een triggerprefix (onchar), of stel chatmode: "onmessage" in.
  • Authenticatiefouten: controleer het bottoken, de basis-URL en of het account is ingeschakeld.
  • Multi-accountproblemen: omgevingsvariabelen gelden alleen voor het default-account.
  • Knoppen verschijnen als witte vakken: de agent stuurt mogelijk misvormde knopdata. Controleer of elke knop zowel text als callback_data velden heeft.
  • Knoppen renderen maar klikken doen niets: verifieer dat AllowedUntrustedInternalConnections in de Mattermost-serverconfiguratie 127.0.0.1 localhost bevat, en dat EnablePostActionIntegration true is in ServiceSettings.
  • Knoppen retourneren 404 bij klik: het knop-id bevat waarschijnlijk koppeltekens of underscores. De actieroutering van Mattermost breekt op niet-alfanumerieke ID’s. Gebruik alleen [a-zA-Z0-9].
  • Gateway logt invalid _token: HMAC-mismatch. Controleer of je alle contextvelden ondertekent (niet een subset), gesorteerde sleutels gebruikt en compacte JSON (geen spaties). Zie het HMAC-gedeelte hierboven.
  • Gateway logt missing _token in context: het _token-veld staat niet in de context van de knop. Zorg ervoor dat het wordt opgenomen bij het bouwen van de integratie-payload.
  • Bevestiging toont rauw ID in plaats van knopnaam: context.action_id komt niet overeen met het id van de knop. Stel beide in op dezelfde opgeschoonde waarde.
  • Agent weet niets over knoppen: voeg capabilities: ["inlineButtons"] toe aan de Mattermost-kanaalconfiguratie.