Developer and self-hosted
Mattermost
Stato: Plugin scaricabile (token del bot + eventi WebSocket). Sono supportati canali, gruppi e DM. Mattermost è una piattaforma di messaggistica per team self-hostable; consulta il sito ufficiale su mattermost.com per dettagli sul prodotto e download.
Installazione
Installa Mattermost prima di configurare il canale:
registro npm
openclaw plugins install @openclaw/mattermost
checkout locale
openclaw plugins install ./path/to/local/mattermost-plugin
Dettagli: Plugin
Configurazione rapida
Verifica che il Plugin sia disponibile
Le versioni pacchettizzate attuali di OpenClaw lo includono già. Le installazioni precedenti/personalizzate possono aggiungerlo manualmente con i comandi sopra.
Crea un bot Mattermost
Crea un account bot Mattermost e copia il token del bot.
Copia l'URL di base
Copia l'URL di base di Mattermost (ad es. https://chat.example.com).
Configura OpenClaw e avvia il Gateway
Configurazione minima:
{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
},
},
}
Comandi slash nativi
I comandi slash nativi sono opzionali. Quando sono abilitati, OpenClaw registra i comandi slash oc_* tramite l'API Mattermost e riceve POST di callback sul server HTTP del 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",
},
},
},
}
Note sul comportamento
native: "auto"è disabilitato per impostazione predefinita per Mattermost. Impostanative: trueper abilitarlo.- Se
callbackUrlviene omesso, OpenClaw ne deriva uno da host/porta del Gateway +callbackPath. - Per configurazioni multi-account,
commandspuò essere impostato al livello superiore o sottochannels.mattermost.accounts.<id>.commands(i valori dell'account sovrascrivono i campi di livello superiore). - Le callback dei comandi sono convalidate con i token per-comando restituiti da Mattermost quando OpenClaw registra i comandi
oc_*. - OpenClaw aggiorna la registrazione corrente dei comandi Mattermost prima di accettare ogni callback, così i token obsoleti di comandi slash eliminati o rigenerati smettono di essere accettati senza riavviare il Gateway.
- La convalida della callback fallisce in modo chiuso se l'API Mattermost non può confermare che il comando sia ancora corrente; le convalide non riuscite vengono memorizzate brevemente nella cache, le ricerche concorrenti vengono accorpate e gli avvii di nuove ricerche sono limitati per frequenza per comando per contenere la pressione di replay.
- Le callback slash falliscono in modo chiuso quando la registrazione non è riuscita, l'avvio è stato parziale o il token della callback non corrisponde al token registrato del comando risolto (un token valido per un comando non può raggiungere la convalida upstream per un comando diverso).
Requisito di raggiungibilità
L'endpoint di callback deve essere raggiungibile dal server Mattermost.
- Non impostare
callbackUrlsulocalhosta meno che Mattermost non sia in esecuzione sullo stesso host/spazio dei nomi di rete di OpenClaw. - Non impostare
callbackUrlsull'URL di base di Mattermost a meno che quell'URL non faccia reverse proxy di/api/channels/mattermost/commandverso OpenClaw. - Un controllo rapido è
curl https://<gateway-host>/api/channels/mattermost/command; una GET dovrebbe restituire405 Method Not Allowedda OpenClaw, non404.
Allowlist egress di Mattermost
Se la callback punta a indirizzi privati/tailnet/interni, imposta ServiceSettings.AllowedUntrustedInternalConnections di Mattermost per includere l'host/dominio della callback.
Usa voci host/dominio, non URL completi.
- Corretto:
gateway.tailnet-name.ts.net - Errato:
https://gateway.tailnet-name.ts.net
Variabili d'ambiente (account predefinito)
Impostale sull'host del Gateway se preferisci le variabili d'ambiente:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
Modalità chat
Mattermost risponde automaticamente ai DM. Il comportamento dei canali è controllato da chatmode:
oncall (predefinito)
Risponde nei canali solo quando viene @menzionato.
onmessage
Risponde a ogni messaggio del canale.
onchar
Risponde quando un messaggio inizia con un prefisso trigger.
Esempio di configurazione:
{
channels: {
mattermost: {
chatmode: "onchar",
oncharPrefixes: [">", "!"],
},
},
}
Note:
oncharrisponde comunque alle @menzioni esplicite.channels.mattermost.requireMentionè rispettato per le configurazioni legacy, machatmodeè preferito.
Threading e sessioni
Usa channels.mattermost.replyToMode per controllare se le risposte in canali e gruppi restano nel canale principale o avviano un thread sotto il post che le ha attivate.
off(predefinito): risponde in un thread solo quando il post in ingresso è già in un thread.first: per post di canale/gruppo di livello superiore, avvia un thread sotto quel post e instrada la conversazione a una sessione con ambito thread.all: stesso comportamento difirstper Mattermost oggi.- I messaggi diretti ignorano questa impostazione e restano senza thread.
Esempio di configurazione:
{
channels: {
mattermost: {
replyToMode: "all",
},
},
}
Note:
- Le sessioni con ambito thread usano l'id del post che ha attivato la conversazione come radice del thread.
firsteallsono attualmente equivalenti perché, una volta che Mattermost ha una radice del thread, i chunk successivi e i media continuano nello stesso thread.
Controllo degli accessi (DM)
- Predefinito:
channels.mattermost.dmPolicy = "pairing"(i mittenti sconosciuti ricevono un codice di abbinamento). - Approva tramite:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- DM pubblici:
channels.mattermost.dmPolicy="open"piùchannels.mattermost.allowFrom=["*"].
Canali (gruppi)
- Predefinito:
channels.mattermost.groupPolicy = "allowlist"(con gating tramite menzione). - Inserisci i mittenti in allowlist con
channels.mattermost.groupAllowFrom(ID utente consigliati). - Le sostituzioni per-canale delle menzioni si trovano sotto
channels.mattermost.groups.<channelId>.requireMentionochannels.mattermost.groups["*"].requireMentionper un valore predefinito. - La corrispondenza
@usernameè mutabile ed è abilitata solo quandochannels.mattermost.dangerouslyAllowNameMatching: true. - Canali aperti:
channels.mattermost.groupPolicy="open"(con gating tramite menzione). - Nota runtime: se
channels.mattermostè completamente assente, il runtime ripiega sugroupPolicy="allowlist"per i controlli sui gruppi (anche sechannels.defaults.groupPolicyè impostato).
Esempio:
{
channels: {
mattermost: {
groupPolicy: "open",
groups: {
"*": { requireMention: true },
"team-channel-id": { requireMention: false },
},
},
},
}
Destinazioni per la consegna in uscita
Usa questi formati di destinazione con openclaw message send o cron/Webhook:
channel:<id>per un canaleuser:<id>per un DM@usernameper un DM (risolto tramite l'API Mattermost)
Nuovo tentativo per canale DM
Quando OpenClaw invia a una destinazione DM Mattermost e deve prima risolvere il canale diretto, riprova per impostazione predefinita gli errori transitori di creazione del canale diretto.
Usa channels.mattermost.dmChannelRetry per regolare globalmente questo comportamento per il Plugin Mattermost, oppure channels.mattermost.accounts.<id>.dmChannelRetry per un account.
{
channels: {
mattermost: {
dmChannelRetry: {
maxRetries: 3,
initialDelayMs: 1000,
maxDelayMs: 10000,
timeoutMs: 30000,
},
},
},
}
Note:
- Si applica solo alla creazione del canale DM (
/api/v4/channels/direct), non a ogni chiamata API Mattermost. - I nuovi tentativi si applicano a errori transitori come limiti di frequenza, risposte 5xx ed errori di rete o timeout.
- Gli errori client 4xx diversi da
429sono trattati come permanenti e non vengono riprovati.
Streaming dell'anteprima
Mattermost trasmette pensieri, attività degli strumenti e testo parziale della risposta in un unico post di anteprima bozza che viene finalizzato sul posto quando la risposta finale è sicura da inviare. L'anteprima si aggiorna sullo stesso id del post invece di riempire il canale con messaggi per chunk. I finali con media/errori annullano le modifiche di anteprima in sospeso e usano la consegna normale invece di scaricare un post di anteprima usa e getta.
Abilita tramite channels.mattermost.streaming:
{
channels: {
mattermost: {
streaming: "partial", // off | partial | block | progress
},
},
}
Modalità di streaming
partialè la scelta abituale: un post di anteprima che viene modificato man mano che la risposta cresce, poi finalizzato con la risposta completa.blockusa chunk di bozza in stile append all'interno del post di anteprima.progressmostra un'anteprima di stato durante la generazione e pubblica solo la risposta finale al completamento.offdisabilita lo streaming dell'anteprima.
Note sul comportamento dello streaming
- Se lo stream non può essere finalizzato sul posto (ad esempio il post è stato eliminato a metà stream), OpenClaw ripiega sull'invio di un nuovo post finale, così la risposta non viene mai persa.
- I payload solo di ragionamento vengono soppressi dai post del canale, incluso il testo che arriva come blockquote
> Reasoning:. Imposta/reasoning onper vedere il ragionamento in altre superfici; il post finale di Mattermost mantiene solo la risposta. - Consulta Streaming per la matrice di mapping dei canali.
Reazioni (strumento messaggi)
- Usa
message action=reactconchannel=mattermost. messageIdè l'id del post Mattermost.emojiaccetta nomi comethumbsupo:+1:(i due punti sono facoltativi).- Imposta
remove=true(booleano) per rimuovere una reazione. - Gli eventi di aggiunta/rimozione delle reazioni vengono inoltrati come eventi di sistema alla sessione dell'agente instradata.
Esempi:
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
Configurazione:
channels.mattermost.actions.reactions: abilita/disabilita le azioni di reazione (predefinito true).- Sostituzione per-account:
channels.mattermost.accounts.<id>.actions.reactions.
Pulsanti interattivi (strumento messaggi)
Invia messaggi con pulsanti cliccabili. Quando un utente fa clic su un pulsante, l'agente riceve la selezione e può rispondere.
Abilita i pulsanti aggiungendo inlineButtons alle capacità del canale:
{
channels: {
mattermost: {
capabilities: ["inlineButtons"],
},
},
}
Usa message action=send con un parametro buttons. I pulsanti sono un array 2D (righe di pulsanti):
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
Campi dei pulsanti:
textstringrequiredEtichetta visualizzata.
callback_datastringrequiredValore restituito al clic (usato come ID dell'azione).
style"default" | "primary" | "danger"Stile del pulsante.
Quando un utente fa clic su un pulsante:
Pulsanti sostituiti con conferma
Tutti i pulsanti vengono sostituiti con una riga di conferma (ad esempio, "✓ Sì selezionato da @user").
L'agente riceve la selezione
L'agente riceve la selezione come messaggio in ingresso e risponde.
Note di implementazione
- Le callback dei pulsanti usano la verifica HMAC-SHA256 (automatica, nessuna configurazione necessaria).
- Mattermost rimuove i dati di callback dalle risposte della sua API (funzionalità di sicurezza), quindi tutti i pulsanti vengono rimossi al clic: la rimozione parziale non è possibile.
- Gli ID azione contenenti trattini o trattini bassi vengono sanificati automaticamente (limitazione del routing di Mattermost).
Configurazione e raggiungibilità
channels.mattermost.capabilities: array di stringhe di capacità. Aggiungi"inlineButtons"per abilitare la descrizione dello strumento dei pulsanti nel prompt di sistema dell'agente.channels.mattermost.interactions.callbackBaseUrl: URL base esterno opzionale per le callback dei pulsanti (ad esempiohttps://gateway.example.com). Usalo quando Mattermost non può raggiungere direttamente il Gateway presso il suo host di bind.- Nelle configurazioni multi-account, puoi anche impostare lo stesso campo sotto
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - Se
interactions.callbackBaseUrlviene omesso, OpenClaw deriva l'URL di callback dagateway.customBindHost+gateway.port, quindi ripiega suhttp://localhost:<port>. - Regola di raggiungibilità: l'URL di callback del pulsante deve essere raggiungibile dal server Mattermost.
localhostfunziona solo quando Mattermost e OpenClaw sono in esecuzione sullo stesso host/spazio dei nomi di rete. - Se la destinazione della callback è privata/tailnet/interna, aggiungi il relativo host/dominio a
ServiceSettings.AllowedUntrustedInternalConnectionsdi Mattermost.
Integrazione API diretta (script esterni)
Script esterni e Webhook possono pubblicare pulsanti direttamente tramite l'API REST di Mattermost invece di passare dallo strumento message dell'agente. Usa buildButtonAttachments() dal plugin quando possibile; se pubblichi JSON grezzo, segui queste regole:
Struttura del payload:
{
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
},
},
},
],
},
],
},
}
Generazione del token HMAC
Il Gateway verifica i clic sui pulsanti con HMAC-SHA256. Gli script esterni devono generare token che corrispondano alla logica di verifica del Gateway:
Deriva il segreto dal token del bot
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
Crea l'oggetto di contesto
Crea l'oggetto di contesto con tutti i campi tranne _token.
Serializza con chiavi ordinate
Serializza con chiavi ordinate e senza spazi (il Gateway usa JSON.stringify con chiavi ordinate, producendo output compatto).
Firma il payload
HMAC-SHA256(key=secret, data=serializedContext)
Aggiungi il token
Aggiungi il digest esadecimale risultante come _token nel contesto.
Esempio Python:
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}
Errori comuni con HMAC
json.dumpsdi Python aggiunge spazi per impostazione predefinita ({"key": "val"}). Usaseparators=(",", ":")per corrispondere all'output compatto di JavaScript ({"key":"val"}).- Firma sempre tutti i campi di contesto (meno
_token). Il Gateway rimuove_token, quindi firma tutto ciò che resta. Firmare un sottoinsieme causa un errore di verifica silenzioso. - Usa
sort_keys=True: il Gateway ordina le chiavi prima della firma, e Mattermost può riordinare i campi di contesto quando memorizza il payload. - Deriva il segreto dal token del bot (deterministico), non da byte casuali. Il segreto deve essere lo stesso tra il processo che crea i pulsanti e il Gateway che verifica.
Adattatore di directory
Il plugin Mattermost include un adattatore di directory che risolve i nomi di canali e utenti tramite l'API di Mattermost. Questo abilita destinazioni #channel-name e @username in openclaw message send e nelle consegne Cron/Webhook.
Non è necessaria alcuna configurazione: l'adattatore usa il token del bot dalla configurazione dell'account.
Multi-account
Mattermost supporta più account sotto 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" },
},
},
},
}
Risoluzione dei problemi
Nessuna risposta nei canali
Assicurati che il bot sia nel canale e menzionalo (oncall), usa un prefisso di attivazione (onchar) oppure imposta chatmode: "onmessage".
Errori di autenticazione o multi-account
- Controlla il token del bot, l'URL base e se l'account è abilitato.
- Problemi multi-account: le variabili env si applicano solo all'account
default.
I comandi slash nativi non riescono
Unauthorized: invalid command token.: OpenClaw non ha accettato il token di callback. Cause tipiche:- la registrazione del comando slash non è riuscita o è stata completata solo parzialmente all'avvio
- la callback sta raggiungendo il Gateway/account errato
- Mattermost ha ancora vecchi comandi che puntano a una destinazione di callback precedente
- il Gateway è stato riavviato senza riattivare i comandi slash
- Se i comandi slash nativi smettono di funzionare, controlla nei log
mattermost: failed to register slash commandsomattermost: native slash commands enabled but no commands could be registered. - Se
callbackUrlviene omesso e i log avvisano che la callback è stata risolta inhttp://127.0.0.1:18789/..., quell'URL è probabilmente raggiungibile solo quando Mattermost è in esecuzione sullo stesso host/spazio dei nomi di rete di OpenClaw. Imposta invece uncommands.callbackUrlesplicito raggiungibile dall'esterno.
Problemi con i pulsanti
- I pulsanti appaiono come riquadri bianchi: l'agente potrebbe inviare dati dei pulsanti non validi. Controlla che ogni pulsante abbia entrambi i campi
textecallback_data. - I pulsanti vengono visualizzati, ma i clic non fanno nulla: verifica che
AllowedUntrustedInternalConnectionsnella configurazione del server Mattermost includa127.0.0.1 localhoste cheEnablePostActionIntegrationsiatruein ServiceSettings. - I pulsanti restituiscono 404 al clic: l'
iddel pulsante probabilmente contiene trattini o trattini bassi. Il router delle azioni di Mattermost si interrompe con ID non alfanumerici. Usa solo[a-zA-Z0-9]. - I log del Gateway mostrano
invalid _token: mancata corrispondenza HMAC. Controlla di firmare tutti i campi di contesto (non un sottoinsieme), usa chiavi ordinate e usa JSON compatto (senza spazi). Vedi la sezione HMAC sopra. - I log del Gateway mostrano
missing _token in context: il campo_tokennon è nel contesto del pulsante. Assicurati che sia incluso durante la creazione del payload di integrazione. - La conferma mostra l'ID grezzo invece del nome del pulsante:
context.action_idnon corrisponde all'iddel pulsante. Impostali entrambi sullo stesso valore sanificato. - L'agente non conosce i pulsanti: aggiungi
capabilities: ["inlineButtons"]alla configurazione del canale Mattermost.
Correlati
- Routing dei canali - routing delle sessioni per i messaggi
- Panoramica dei canali - tutti i canali supportati
- Gruppi - comportamento delle chat di gruppo e controllo tramite menzione
- Associazione - autenticazione DM e flusso di associazione
- Sicurezza - modello di accesso e rafforzamento