---
read_when:
    - Configuration de Mattermost
    - Débogage du routage Mattermost
summary: Configuration du bot Mattermost et configuration d’OpenClaw
title: Mattermost
x-i18n:
    generated_at: "2026-04-23T13:57:52Z"
    model: gpt-5.4
    provider: openai
    source_hash: d9421ae903caed5c9dc3b19ca8558725f11bbe553a20bd4d3f0fb6e7eecccd92
    source_path: channels/mattermost.md
    workflow: 15
---

# Mattermost

Statut : plugin intégré (jeton de bot + événements WebSocket). Les canaux, groupes et messages privés sont pris en charge.
Mattermost est une plateforme de messagerie d’équipe auto-hébergeable ; consultez le site officiel à l’adresse
[mattermost.com](https://mattermost.com) pour les détails du produit et les téléchargements.

## Plugin intégré

Mattermost est livré comme plugin intégré dans les versions actuelles d’OpenClaw, donc les
builds packagés normaux n’ont pas besoin d’une installation séparée.

Si vous utilisez une ancienne build ou une installation personnalisée qui exclut Mattermost,
installez-le manuellement :

Installer via la CLI (registre npm) :

```bash
openclaw plugins install @openclaw/mattermost
```

Checkout local (lors d’une exécution depuis un dépôt git) :

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

Détails : [Plugins](/fr/tools/plugin)

## Configuration rapide

1. Assurez-vous que le plugin Mattermost est disponible.
   - Les versions packagées actuelles d’OpenClaw l’intègrent déjà.
   - Les installations anciennes/personnalisées peuvent l’ajouter manuellement avec les commandes ci-dessus.
2. Créez un compte bot Mattermost et copiez le **jeton de bot**.
3. Copiez l’**URL de base** Mattermost (par ex. `https://chat.example.com`).
4. Configurez OpenClaw et démarrez la Gateway.

Configuration minimale :

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

## Commandes slash natives

Les commandes slash natives sont activées sur option. Lorsqu’elles sont activées, OpenClaw enregistre les commandes slash `oc_*` via
l’API Mattermost et reçoit les POST de rappel sur le serveur HTTP de la Gateway.

```json5
{
  channels: {
    mattermost: {
      commands: {
        native: true,
        nativeSkills: true,
        callbackPath: "/api/channels/mattermost/command",
        // À utiliser lorsque Mattermost ne peut pas joindre la Gateway directement (proxy inverse/URL publique).
        callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
      },
    },
  },
}
```

Remarques :

- `native: "auto"` est désactivé par défaut pour Mattermost. Définissez `native: true` pour l’activer.
- Si `callbackUrl` est omis, OpenClaw en dérive une à partir de l’hôte/port de la Gateway + `callbackPath`.
- Pour les configurations multi-comptes, `commands` peut être défini au niveau supérieur ou sous
  `channels.mattermost.accounts.<id>.commands` (les valeurs du compte remplacent les champs de niveau supérieur).
- Les rappels de commande sont validés avec les jetons par commande renvoyés par
  Mattermost lorsque OpenClaw enregistre les commandes `oc_*`.
- Les rappels slash échouent de manière fermée lorsque l’enregistrement a échoué, que le démarrage a été partiel, ou
  que le jeton de rappel ne correspond à aucune des commandes enregistrées.
- Exigence d’accessibilité : le point de terminaison de rappel doit être accessible depuis le serveur Mattermost.
  - Ne définissez pas `callbackUrl` sur `localhost` sauf si Mattermost s’exécute sur le même hôte/espace de noms réseau qu’OpenClaw.
  - Ne définissez pas `callbackUrl` sur votre URL de base Mattermost sauf si cette URL proxyfie en inverse `/api/channels/mattermost/command` vers OpenClaw.
  - Une vérification rapide consiste à exécuter `curl https://<gateway-host>/api/channels/mattermost/command` ; un GET doit renvoyer `405 Method Not Allowed` depuis OpenClaw, et non `404`.
- Exigence de liste d’autorisation de sortie Mattermost :
  - Si votre rappel cible des adresses privées/tailnet/internes, définissez
    `ServiceSettings.AllowedUntrustedInternalConnections` de Mattermost pour inclure l’hôte/domaine du rappel.
  - Utilisez des entrées hôte/domaine, pas des URL complètes.
    - Bon : `gateway.tailnet-name.ts.net`
    - Mauvais : `https://gateway.tailnet-name.ts.net`

## Variables d’environnement (compte par défaut)

Définissez-les sur l’hôte de la Gateway si vous préférez des variables d’environnement :

- `MATTERMOST_BOT_TOKEN=...`
- `MATTERMOST_URL=https://chat.example.com`

Les variables d’environnement s’appliquent uniquement au compte **par défaut** (`default`). Les autres comptes doivent utiliser des valeurs de configuration.

`MATTERMOST_URL` ne peut pas être défini depuis un `.env` d’espace de travail ; consultez [Fichiers `.env` d’espace de travail](/fr/gateway/security).

## Modes de discussion

Mattermost répond automatiquement aux messages privés. Le comportement dans les canaux est contrôlé par `chatmode` :

- `oncall` (par défaut) : répond uniquement lorsque le bot est @mentionné dans les canaux.
- `onmessage` : répond à chaque message de canal.
- `onchar` : répond lorsqu’un message commence par un préfixe de déclenchement.

Exemple de configuration :

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

Remarques :

- `onchar` répond toujours aux @mentions explicites.
- `channels.mattermost.requireMention` est pris en compte pour les configurations héritées, mais `chatmode` est préférable.

## Fils de discussion et sessions

Utilisez `channels.mattermost.replyToMode` pour contrôler si les réponses dans les canaux et groupes restent dans le
canal principal ou démarrent un fil sous le post déclencheur.

- `off` (par défaut) : répond dans un fil uniquement si le post entrant est déjà dans un fil.
- `first` : pour les posts de canal/groupe de niveau supérieur, démarre un fil sous ce post et route la
  conversation vers une session limitée à ce fil.
- `all` : même comportement que `first` pour Mattermost aujourd’hui.
- Les messages privés ignorent ce paramètre et restent sans fil.

Exemple de configuration :

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

Remarques :

- Les sessions limitées à un fil utilisent l’identifiant du post déclencheur comme racine du fil.
- `first` et `all` sont actuellement équivalents car une fois que Mattermost a une racine de fil,
  les fragments de suivi et les médias continuent dans ce même fil.

## Contrôle d’accès (messages privés)

- Par défaut : `channels.mattermost.dmPolicy = "pairing"` (les expéditeurs inconnus reçoivent un code d’appairage).
- Approuver via :
  - `openclaw pairing list mattermost`
  - `openclaw pairing approve mattermost <CODE>`
- Messages privés publics : `channels.mattermost.dmPolicy="open"` plus `channels.mattermost.allowFrom=["*"]`.

## Canaux (groupes)

- Par défaut : `channels.mattermost.groupPolicy = "allowlist"` (contrôlé par mention).
- Autorisez les expéditeurs avec `channels.mattermost.groupAllowFrom` (identifiants utilisateur recommandés).
- Les remplacements de mention par canal se trouvent sous `channels.mattermost.groups.<channelId>.requireMention`
  ou `channels.mattermost.groups["*"].requireMention` pour une valeur par défaut.
- La correspondance `@username` est mutable et n’est activée que lorsque `channels.mattermost.dangerouslyAllowNameMatching: true`.
- Canaux ouverts : `channels.mattermost.groupPolicy="open"` (contrôlé par mention).
- Remarque d’exécution : si `channels.mattermost` est complètement absent, l’exécution revient à `groupPolicy="allowlist"` pour les vérifications de groupe (même si `channels.defaults.groupPolicy` est défini).

Exemple :

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

## Cibles pour la livraison sortante

Utilisez ces formats de cible avec `openclaw message send` ou Cron/Webhooks :

- `channel:<id>` pour un canal
- `user:<id>` pour un message privé
- `@username` pour un message privé (résolu via l’API Mattermost)

Les identifiants opaques bruts (comme `64ifufp...`) sont **ambiguës** dans Mattermost (identifiant utilisateur ou identifiant de canal).

OpenClaw les résout en donnant **la priorité à l’utilisateur** :

- Si l’identifiant existe comme utilisateur (`GET /api/v4/users/<id>` réussit), OpenClaw envoie un **message privé** en résolvant le canal direct via `/api/v4/channels/direct`.
- Sinon, l’identifiant est traité comme un **identifiant de canal**.

Si vous avez besoin d’un comportement déterministe, utilisez toujours les préfixes explicites (`user:<id>` / `channel:<id>`).

## Nouvelle tentative du canal de message privé

Lorsqu’OpenClaw envoie vers une cible de message privé Mattermost et doit d’abord résoudre le canal direct, il
réessaie par défaut les échecs transitoires de création du canal direct.

Utilisez `channels.mattermost.dmChannelRetry` pour ajuster ce comportement globalement pour le plugin Mattermost,
ou `channels.mattermost.accounts.<id>.dmChannelRetry` pour un seul compte.

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

Remarques :

- Cela s’applique uniquement à la création du canal de message privé (`/api/v4/channels/direct`), pas à tous les appels d’API Mattermost.
- Les nouvelles tentatives s’appliquent aux échecs transitoires tels que les limites de débit, les réponses 5xx, ainsi que les erreurs réseau ou de délai d’attente.
- Les erreurs client 4xx autres que `429` sont traitées comme permanentes et ne sont pas réessayées.

## Streaming d’aperçu

Mattermost diffuse la réflexion, l’activité des outils et le texte de réponse partiel dans un seul **post d’aperçu brouillon** qui se finalise sur place lorsque la réponse finale peut être envoyée en toute sécurité. L’aperçu se met à jour sur le même identifiant de post au lieu d’inonder le canal avec des messages par fragment. Les finales média/erreur annulent les modifications d’aperçu en attente et utilisent la livraison normale au lieu de publier un post d’aperçu jetable.

Activez-le via `channels.mattermost.streaming` :

```json5
{
  channels: {
    mattermost: {
      streaming: "partial", // off | partial | block | progress
    },
  },
}
```

Remarques :

- `partial` est le choix habituel : un post d’aperçu unique qui est modifié à mesure que la réponse grandit, puis finalisé avec la réponse complète.
- `block` utilise des fragments brouillons de style ajout dans le post d’aperçu.
- `progress` affiche un aperçu d’état pendant la génération et ne publie la réponse finale qu’à la fin.
- `off` désactive le streaming d’aperçu.
- Si le flux ne peut pas être finalisé sur place (par exemple si le post a été supprimé en cours de flux), OpenClaw revient à l’envoi d’un nouveau post final afin que la réponse ne soit jamais perdue.
- Les charges utiles de réflexion seule sont supprimées des posts de canal, y compris le texte qui arrive sous la forme d’un bloc de citation `> Reasoning:`. Définissez `/reasoning on` pour voir la réflexion dans d’autres surfaces ; le post final Mattermost conserve uniquement la réponse.
- Consultez [Streaming](/fr/concepts/streaming#preview-streaming-modes) pour la matrice de correspondance des canaux.

## Réactions (outil de message)

- Utilisez `message action=react` avec `channel=mattermost`.
- `messageId` est l’identifiant du post Mattermost.
- `emoji` accepte des noms comme `thumbsup` ou `:+1:` (les deux-points sont facultatifs).
- Définissez `remove=true` (booléen) pour supprimer une réaction.
- Les événements d’ajout/suppression de réaction sont transférés comme événements système vers la session d’agent routée.

Exemples :

```
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
```

Configuration :

- `channels.mattermost.actions.reactions` : active/désactive les actions de réaction (true par défaut).
- Remplacement par compte : `channels.mattermost.accounts.<id>.actions.reactions`.

## Boutons interactifs (outil de message)

Envoyez des messages avec des boutons cliquables. Lorsqu’un utilisateur clique sur un bouton, l’agent reçoit la
sélection et peut répondre.

Activez les boutons en ajoutant `inlineButtons` aux capacités du canal :

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

Utilisez `message action=send` avec un paramètre `buttons`. Les boutons sont un tableau 2D (lignes de boutons) :

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

Champs des boutons :

- `text` (obligatoire) : libellé affiché.
- `callback_data` (obligatoire) : valeur renvoyée lors du clic (utilisée comme identifiant d’action).
- `style` (facultatif) : `"default"`, `"primary"` ou `"danger"`.

Lorsqu’un utilisateur clique sur un bouton :

1. Tous les boutons sont remplacés par une ligne de confirmation (par ex. "✓ **Yes** selected by @user").
2. L’agent reçoit la sélection sous forme de message entrant et répond.

Remarques :

- Les rappels de bouton utilisent la vérification HMAC-SHA256 (automatique, aucune configuration nécessaire).
- Mattermost retire les données de rappel de ses réponses API (fonctionnalité de sécurité), donc tous les boutons
  sont supprimés au clic — une suppression partielle n’est pas possible.
- Les identifiants d’action contenant des tirets ou des soulignements sont assainis automatiquement
  (limitation de routage Mattermost).

Configuration :

- `channels.mattermost.capabilities` : tableau de chaînes de capacités. Ajoutez `"inlineButtons"` pour
  activer la description de l’outil de boutons dans le prompt système de l’agent.
- `channels.mattermost.interactions.callbackBaseUrl` : URL de base externe facultative pour les
  rappels de bouton (par exemple `https://gateway.example.com`). Utilisez-la lorsque Mattermost ne peut pas
  joindre la Gateway directement à son hôte de liaison.
- Dans les configurations multi-comptes, vous pouvez également définir le même champ sous
  `channels.mattermost.accounts.<id>.interactions.callbackBaseUrl`.
- Si `interactions.callbackBaseUrl` est omis, OpenClaw dérive l’URL de rappel à partir de
  `gateway.customBindHost` + `gateway.port`, puis retombe sur `http://localhost:<port>`.
- Règle d’accessibilité : l’URL de rappel du bouton doit être accessible depuis le serveur Mattermost.
  `localhost` fonctionne uniquement lorsque Mattermost et OpenClaw s’exécutent sur le même hôte/espace de noms réseau.
- Si votre cible de rappel est privée/tailnet/interne, ajoutez son hôte/domaine à
  `ServiceSettings.AllowedUntrustedInternalConnections` de Mattermost.

### Intégration directe de l’API (scripts externes)

Les scripts externes et les Webhooks peuvent publier des boutons directement via l’API REST Mattermost
au lieu de passer par l’outil `message` de l’agent. Utilisez `buildButtonAttachments()` du
plugin lorsque c’est possible ; si vous publiez du JSON brut, suivez ces règles :

**Structure de charge utile :**

```json5
{
  channel_id: "<channelId>",
  message: "Choisissez une option :",
  props: {
    attachments: [
      {
        actions: [
          {
            id: "mybutton01", // alphanumérique uniquement — voir ci-dessous
            type: "button", // obligatoire, sinon les clics sont ignorés silencieusement
            name: "Approuver", // libellé affiché
            style: "primary", // facultatif : "default", "primary", "danger"
            integration: {
              url: "https://gateway.example.com/mattermost/interactions/default",
              context: {
                action_id: "mybutton01", // doit correspondre à l’identifiant du bouton (pour la recherche du nom)
                action: "approve",
                // ... tout champ personnalisé ...
                _token: "<hmac>", // voir la section HMAC ci-dessous
              },
            },
          },
        ],
      },
    ],
  },
}
```

**Règles critiques :**

1. Les pièces jointes vont dans `props.attachments`, pas dans `attachments` au niveau supérieur (ignoré silencieusement).
2. Chaque action doit avoir `type: "button"` — sans cela, les clics sont absorbés silencieusement.
3. Chaque action doit avoir un champ `id` — Mattermost ignore les actions sans identifiant.
4. L’`id` de l’action doit être **strictement alphanumérique** (`[a-zA-Z0-9]`). Les tirets et soulignements cassent
   le routage d’action côté serveur de Mattermost (renvoie 404). Supprimez-les avant utilisation.
5. `context.action_id` doit correspondre à l’`id` du bouton afin que le message de confirmation affiche le
   nom du bouton (par ex. "Approuver") au lieu d’un identifiant brut.
6. `context.action_id` est obligatoire — le gestionnaire d’interaction renvoie 400 sans lui.

**Génération de jeton HMAC :**

La Gateway vérifie les clics sur les boutons avec HMAC-SHA256. Les scripts externes doivent générer des jetons
qui correspondent à la logique de vérification de la Gateway :

1. Dérivez le secret à partir du jeton de bot :
   `HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)`
2. Construisez l’objet context avec tous les champs **sauf** `_token`.
3. Sérialisez avec des **clés triées** et **sans espaces** (la Gateway utilise `JSON.stringify`
   avec des clés triées, ce qui produit une sortie compacte).
4. Signez : `HMAC-SHA256(key=secret, data=serializedContext)`
5. Ajoutez le condensat hexadécimal résultant comme `_token` dans le context.

Exemple Python :

```python
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}
```

Pièges HMAC fréquents :

- `json.dumps` de Python ajoute des espaces par défaut (`{"key": "val"}`). Utilisez
  `separators=(",", ":")` pour correspondre à la sortie compacte de JavaScript (`{"key":"val"}`).
- Signez toujours **tous** les champs du context (moins `_token`). La Gateway retire `_token` puis
  signe tout le reste. Signer un sous-ensemble provoque un échec de vérification silencieux.
- Utilisez `sort_keys=True` — la Gateway trie les clés avant la signature, et Mattermost peut
  réordonner les champs du context lors du stockage de la charge utile.
- Dérivez le secret à partir du jeton de bot (déterministe), pas à partir d’octets aléatoires. Le secret
  doit être le même dans le processus qui crée les boutons et dans la Gateway qui vérifie.

## Adaptateur d’annuaire

Le plugin Mattermost inclut un adaptateur d’annuaire qui résout les noms de canaux et d’utilisateurs
via l’API Mattermost. Cela active les cibles `#channel-name` et `@username` dans
`openclaw message send` et les livraisons Cron/Webhook.

Aucune configuration n’est nécessaire — l’adaptateur utilise le jeton de bot de la configuration du compte.

## Multi-compte

Mattermost prend en charge plusieurs comptes sous `channels.mattermost.accounts` :

```json5
{
  channels: {
    mattermost: {
      accounts: {
        default: { name: "Principal", botToken: "mm-token", baseUrl: "https://chat.example.com" },
        alerts: { name: "Alertes", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" },
      },
    },
  },
}
```

## Dépannage

- Pas de réponses dans les canaux : assurez-vous que le bot est dans le canal et mentionnez-le (`oncall`), utilisez un préfixe de déclenchement (`onchar`), ou définissez `chatmode: "onmessage"`.
- Erreurs d’authentification : vérifiez le jeton de bot, l’URL de base et si le compte est activé.
- Problèmes multi-comptes : les variables d’environnement s’appliquent uniquement au compte `default`.
- Les commandes slash natives renvoient `Unauthorized: invalid command token.` : OpenClaw
  n’a pas accepté le jeton de rappel. Causes typiques :
  - l’enregistrement des commandes slash a échoué ou ne s’est achevé que partiellement au démarrage
  - le rappel atteint la mauvaise Gateway/le mauvais compte
  - Mattermost a encore d’anciennes commandes pointant vers une cible de rappel précédente
  - la Gateway a redémarré sans réactiver les commandes slash
- Si les commandes slash natives cessent de fonctionner, vérifiez les journaux pour
  `mattermost: failed to register slash commands` ou
  `mattermost: native slash commands enabled but no commands could be registered`.
- Si `callbackUrl` est omis et que les journaux avertissent que le rappel a été résolu vers
  `http://127.0.0.1:18789/...`, cette URL n’est probablement accessible que lorsque
  Mattermost s’exécute sur le même hôte/espace de noms réseau qu’OpenClaw. Définissez plutôt une
  `commands.callbackUrl` explicite et accessible de l’extérieur.
- Les boutons apparaissent comme des cases blanches : l’agent envoie peut-être des données de bouton mal formées. Vérifiez que chaque bouton comporte à la fois les champs `text` et `callback_data`.
- Les boutons s’affichent mais les clics ne font rien : vérifiez que `AllowedUntrustedInternalConnections` dans la configuration du serveur Mattermost inclut `127.0.0.1 localhost`, et que `EnablePostActionIntegration` est `true` dans ServiceSettings.
- Les boutons renvoient 404 au clic : l’`id` du bouton contient probablement des tirets ou des soulignements. Le routeur d’action de Mattermost ne fonctionne pas avec des identifiants non alphanumériques. Utilisez uniquement `[a-zA-Z0-9]`.
- La Gateway journalise `invalid _token` : incompatibilité HMAC. Vérifiez que vous signez tous les champs du context (pas un sous-ensemble), que vous utilisez des clés triées, et du JSON compact (sans espaces). Voir la section HMAC ci-dessus.
- La Gateway journalise `missing _token in context` : le champ `_token` n’est pas dans le context du bouton. Assurez-vous qu’il est inclus lors de la construction de la charge utile d’intégration.
- La confirmation affiche l’identifiant brut au lieu du nom du bouton : `context.action_id` ne correspond pas à l’`id` du bouton. Définissez les deux à la même valeur assainie.
- L’agent ne connaît pas les boutons : ajoutez `capabilities: ["inlineButtons"]` à la configuration du canal Mattermost.

## Liens associés

- [Vue d’ensemble des canaux](/fr/channels) — tous les canaux pris en charge
- [Appairage](/fr/channels/pairing) — authentification des messages privés et flux d’appairage
- [Groupes](/fr/channels/groups) — comportement du chat de groupe et contrôle par mention
- [Routage des canaux](/fr/channels/channel-routing) — routage des sessions pour les messages
- [Sécurité](/fr/gateway/security) — modèle d’accès et durcissement
