Developer and self-hosted

Mattermost

Status: downloadbare Plugin (bottoken + WebSocket-gebeurtenissen). Kanalen, groepen en DM's worden ondersteund. Mattermost is een zelf te hosten platform voor teamberichten; zie de officiële site op mattermost.com voor productdetails en downloads.

Installeren

Installeer Mattermost voordat je het kanaal configureert:

npm registry

openclaw plugins install @openclaw/mattermost

Local checkout

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

Details: Plugins

Snelle configuratie

  • Ensure plugin is available

    Huidige verpakte OpenClaw-releases bundelen het al. Oudere/aangepaste installaties kunnen het handmatig toevoegen met de bovenstaande commando's.

  • Create a Mattermost bot

    Maak een Mattermost-botaccount en kopieer de bottoken.

  • Copy the base URL

    Kopieer de Mattermost-basis-URL (bijv. https://chat.example.com).

  • Configure OpenClaw and start the gateway

    Minimale configuratie:

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

    Native slashcommando's zijn opt-in. Wanneer ze zijn ingeschakeld, registreert OpenClaw oc_*-slashcommando's via de Mattermost-API en ontvangt het callback-POST's op de HTTP-server van de Gateway.

    {
      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" staat standaard uitgeschakeld voor Mattermost. Stel native: true in om dit in te schakelen.
    • Als callbackUrl wordt weggelaten, leidt OpenClaw er een af uit de Gateway-host/-poort + callbackPath.
    • Voor configuraties met meerdere accounts kan commands op het hoogste niveau worden ingesteld of onder channels.mattermost.accounts.<id>.commands (accountwaarden overschrijven velden op het hoogste niveau).
    • Commandocallbacks worden gevalideerd met de tokens per commando die Mattermost retourneert wanneer OpenClaw oc_*-commando's registreert.
    • OpenClaw vernieuwt de huidige Mattermost-commandoregistratie voordat elke callback wordt geaccepteerd, zodat verouderde tokens van verwijderde of opnieuw gegenereerde slashcommando's niet meer worden geaccepteerd zonder herstart van de Gateway.
    • Callbackvalidatie faalt gesloten als de Mattermost-API niet kan bevestigen dat het commando nog actueel is; mislukte validaties worden kort gecachet, gelijktijdige lookups worden samengevoegd en nieuwe lookupstarts worden per commando beperkt in snelheid om replaydruk te begrenzen.
    • Slashcallbacks falen gesloten wanneer registratie is mislukt, het opstarten gedeeltelijk was, of de callbacktoken niet overeenkomt met de geregistreerde token van het opgeloste commando (een token die geldig is voor het ene commando kan geen upstreamvalidatie voor een ander commando bereiken).
    Reachability requirement

    Het callback-eindpunt moet bereikbaar zijn vanaf de Mattermost-server.

    • Stel callbackUrl niet in op localhost, tenzij Mattermost op dezelfde host/netwerknamespace als OpenClaw draait.
    • Stel callbackUrl niet in op je Mattermost-basis-URL, tenzij die URL /api/channels/mattermost/command via een reverse proxy naar OpenClaw doorstuurt.
    • Een snelle controle is curl https://<gateway-host>/api/channels/mattermost/command; een GET moet 405 Method Not Allowed van OpenClaw retourneren, niet 404.
    Mattermost egress allowlist

    Als je callback privé-/tailnet-/interne adressen target, stel dan Mattermost ServiceSettings.AllowedUntrustedInternalConnections in zodat de callbackhost/het callbackdomein is opgenomen.

    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 Gateway-host als je liever env vars gebruikt:

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

    Chatmodi

    Mattermost reageert automatisch op DM's. Kanaalgedrag wordt beheerd door chatmode:

    oncall (default)

    Reageer alleen wanneer er in kanalen een @vermelding is.

    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 gerespecteerd voor legacyconfiguraties, maar chatmode heeft de voorkeur.

    Threads en sessies

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

    • off (standaard): antwoord alleen in een thread wanneer de binnenkomende post er al in staat.
    • first: start voor posts op het hoogste niveau in kanalen/groepen een thread onder die post en routeer het gesprek naar een thread-gebonden sessie.
    • all: hetzelfde gedrag als first voor Mattermost vandaag.
    • Direct messages negeren deze instelling en blijven zonder thread.

    Configuratievoorbeeld:

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

    Opmerkingen:

    • Thread-gebonden sessies gebruiken de activerende post-id als threadroot.
    • first en all zijn momenteel equivalent, omdat zodra Mattermost een threadroot 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 &lt;CODE&gt;
    • Openbare DM's: channels.mattermost.dmPolicy="open" plus channels.mattermost.allowFrom=["*"].

    Kanalen (groepen)

    • Standaard: channels.mattermost.groupPolicy = "allowlist" (afgeschermd door vermeldingen).
    • Zet afzenders op de allowlist met channels.mattermost.groupAllowFrom (gebruikers-ID's aanbevolen).
    • Vermeldingsoverschrijvingen per kanaal staan onder channels.mattermost.groups.<channelId>.requireMention of channels.mattermost.groups["*"].requireMention voor een standaardwaarde.
    • @username-matching is veranderlijk en alleen ingeschakeld wanneer channels.mattermost.dangerouslyAllowNameMatching: true.
    • Open kanalen: channels.mattermost.groupPolicy="open" (afgeschermd door vermeldingen).
    • Runtime-opmerking: als channels.mattermost volledig ontbreekt, valt runtime terug op groupPolicy="allowlist" voor groepscontroles (zelfs als channels.defaults.groupPolicy is ingesteld).

    Voorbeeld:

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

    Targets voor uitgaande aflevering

    Gebruik deze targetindelingen 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)

    Opnieuw proberen voor DM-kanaal

    Wanneer OpenClaw verzendt naar een Mattermost-DM-target en eerst het directe kanaal moet oplossen, probeert het standaard tijdelijke fouten bij het aanmaken van directe kanalen opnieuw.

    Gebruik channels.mattermost.dmChannelRetry om dat gedrag globaal af te stemmen voor de Mattermost-Plugin, of channels.mattermost.accounts.<id>.dmChannelRetry voor één account.

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

    Opmerkingen:

    • Dit geldt alleen voor het aanmaken van DM-kanalen (/api/v4/channels/direct), niet voor elke Mattermost-API-aanroep.
    • Nieuwe pogingen gelden voor tijdelijke fouten zoals rate limits, 5xx-responsen en netwerk- of time-outfouten.
    • 4xx-clientfouten anders dan 429 worden als permanent behandeld en worden niet opnieuw geprobeerd.

    Preview-streaming

    Mattermost streamt denkwerk, toolactiviteit en gedeeltelijke antwoordtekst naar één conceptpreviewpost die op zijn plek wordt definitief gemaakt wanneer het definitieve antwoord veilig kan worden verzonden. De preview wordt bijgewerkt op dezelfde post-id in plaats van het kanaal te spammen met berichten per chunk. Definitieve media-/foutberichten annuleren wachtende previewbewerkingen en gebruiken normale aflevering in plaats van een wegwerppreviewpost te flushen.

    Inschakelen via channels.mattermost.streaming:

    {
      channels: {
        mattermost: {
          streaming: "partial", // off | partial | block | progress
        },
      },
    }
    
    Streaming modes
    • partial is de gebruikelijke keuze: één previewpost die wordt bewerkt terwijl het antwoord groeit en daarna wordt afgerond met het volledige antwoord.
    • block gebruikt conceptchunks in append-stijl binnen de previewpost.
    • progress toont een statuspreview tijdens het genereren en plaatst pas het definitieve antwoord bij voltooiing.
    • off schakelt preview-streaming uit.
    Streaming behavior notes
    • Als de stream niet op zijn plek kan worden afgerond (bijvoorbeeld omdat de post halverwege de stream is verwijderd), valt OpenClaw terug op het verzenden van een nieuwe definitieve post zodat het antwoord nooit verloren gaat.
    • Payloads die alleen redenering bevatten, worden onderdrukt in kanaalposts, inclusief tekst die binnenkomt als een > Reasoning:-blockquote. Stel /reasoning on in om denkwerk in andere oppervlakken te zien; de definitieve Mattermost-post houdt alleen het antwoord.
    • Zie Streaming voor de kanaalmappingmatrix.

    Reacties (berichtentool)

    • Gebruik message action=react met channel=mattermost.
    • messageId is de Mattermost-post-id.
    • emoji accepteert namen zoals thumbsup of :+1: (dubbele punten zijn optioneel).
    • Stel remove=true (boolean) in om een reactie te verwijderen.
    • Gebeurtenissen voor toevoegen/verwijderen van reacties worden als systeemgebeurtenissen doorgestuurd 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).
    • Overschrijving per account: channels.mattermost.accounts.<id>.actions.reactions.

    Interactieve knoppen (berichtentool)

    Verzend berichten met aanklikbare knoppen. Wanneer een gebruiker op een knop klikt, ontvangt de agent de selectie en kan deze 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 knoppen):

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

    Knopvelden:

    textstringrequired

    Weergavelabel.

    callback_datastringrequired

    Waarde die bij klikken wordt teruggestuurd (gebruikt als actie-ID).

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

    Knopstijl.

    Wanneer een gebruiker op een knop klikt:

  • Knoppen vervangen door bevestiging

    Alle knoppen worden vervangen door een bevestigingsregel (bijv. "✓ Ja geselecteerd door @user").

  • Agent ontvangt de selectie

    De agent ontvangt de selectie als een inkomend bericht en reageert.

  • Implementatienotities
    • Knop-callbacks gebruiken HMAC-SHA256-verificatie (automatisch, geen configuratie nodig).
    • Mattermost verwijdert callbackgegevens uit zijn API-antwoorden (beveiligingsfunctie), dus alle knoppen worden bij klikken verwijderd - gedeeltelijke verwijdering is niet mogelijk.
    • Actie-ID's met koppeltekens of underscores worden automatisch opgeschoond (routeringsbeperking van Mattermost).
    Configuratie en bereikbaarheid
    • channels.mattermost.capabilities: array met capability-strings. Voeg "inlineButtons" toe om de beschrijving van de knoppentool in de systeemprompt van de agent in te schakelen.
    • channels.mattermost.interactions.callbackBaseUrl: optionele externe basis-URL voor knop-callbacks (bijvoorbeeld https://gateway.example.com). Gebruik dit wanneer Mattermost de gateway niet rechtstreeks kan bereiken op de host waaraan deze is gebonden.
    • In multi-accountconfiguraties kun je hetzelfde veld ook instellen onder channels.mattermost.accounts.<id>.interactions.callbackBaseUrl.
    • Als interactions.callbackBaseUrl is weggelaten, leidt OpenClaw de callback-URL af uit gateway.customBindHost + gateway.port, en valt daarna terug op http://localhost:<port>.
    • Bereikbaarheidsregel: de knop-callback-URL moet bereikbaar zijn vanaf 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 plaatsen via de Mattermost REST API in plaats van via de message-tool van de agent. Gebruik waar mogelijk buildButtonAttachments() uit de Plugin; als je onbewerkte JSON plaatst, 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
                  },
                },
              },
            ],
          },
        ],
      },
    }
    

    HMAC-token genereren

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

  • Leid het geheim af uit het bottoken

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

  • Bouw het contextobject

    Bouw het contextobject met alle velden behalve _token.

  • Serialiseer met gesorteerde sleutels

    Serialiseer met gesorteerde sleutels en zonder spaties (de gateway gebruikt JSON.stringify met gesorteerde sleutels, wat compacte uitvoer produceert).

  • Onderteken de payload

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

  • Voeg het token toe

    Voeg de resulterende hex-digest toe als _token in de context.

  • Python-voorbeeld:

    
    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 de compacte uitvoer van JavaScript ({"key":"val"}).
    • Onderteken altijd alle contextvelden (minus _token). De gateway verwijdert _token en ondertekent daarna alles wat overblijft. Het ondertekenen van een subset veroorzaakt een stille verificatiefout.
    • Gebruik sort_keys=True - de gateway sorteert sleutels vóór ondertekening, en Mattermost kan contextvelden opnieuw ordenen bij het opslaan van de payload.
    • Leid het geheim af uit het bottoken (deterministisch), niet uit 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-leveringen.

    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 dat de bot in het kanaal zit en vermeld hem (oncall), gebruik een triggerprefix (onchar), of stel chatmode: "onmessage" in.

    Authenticatie- of multi-accountfouten
    • Controleer het bottoken, de basis-URL en of het account is ingeschakeld.
    • Multi-accountproblemen: env-vars zijn alleen van toepassing op het default-account.
    Native slash-commands mislukken
    • Unauthorized: invalid command token.: OpenClaw heeft het callbacktoken niet geaccepteerd. Typische oorzaken:
      • registratie van slash-command is mislukt of slechts gedeeltelijk voltooid bij het opstarten
      • de callback bereikt de verkeerde gateway/het verkeerde account
      • Mattermost heeft nog oude commands die naar een eerder callbackdoel wijzen
      • de gateway is opnieuw gestart zonder slash-commands opnieuw te activeren
    • Als native slash-commands niet meer werken, controleer dan de logs op mattermost: failed to register slash commands of mattermost: native slash commands enabled but no commands could be registered.
    • Als callbackUrl is weggelaten en logs waarschuwen dat de callback is omgezet naar http://127.0.0.1:18789/..., is die URL waarschijnlijk alleen bereikbaar wanneer Mattermost op dezelfde host/netwerknamespace draait als OpenClaw. Stel in plaats daarvan een expliciete extern bereikbare commands.callbackUrl in.
    Knopproblemen
    • Knoppen verschijnen als witte vakken: de agent stuurt mogelijk verkeerd gevormde knopgegevens. Controleer dat elke knop zowel text- als callback_data-velden heeft.
    • Knoppen worden weergegeven 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 klikken: de knop-id bevat waarschijnlijk koppeltekens of underscores. De actierouter van Mattermost breekt bij niet-alfanumerieke ID's. Gebruik alleen [a-zA-Z0-9].
    • Gateway-logs invalid _token: HMAC komt niet overeen. Controleer dat je alle contextvelden ondertekent (niet een subset), gesorteerde sleutels gebruikt en compacte JSON gebruikt (geen spaties). Zie de HMAC-sectie hierboven.
    • Gateway-logs missing _token in context: het _token-veld staat niet in de context van de knop. Zorg dat het wordt opgenomen bij het bouwen van de integratiepayload.
    • Bevestiging toont onbewerkte ID in plaats van knopnaam: context.action_id komt niet overeen met de id van de knop. Stel beide in op dezelfde opgeschoonde waarde.
    • Agent weet niet van knoppen: voeg capabilities: ["inlineButtons"] toe aan de Mattermost-kanaalconfiguratie.

    Gerelateerd