Ir al contenido

Conecta Mattermost a OpenClaw: Guía de configuración rápida

Mattermost se distribuye como un plugin y no viene incluido en la instalación principal.

Instálalo mediante la CLI (registro npm):

Ventana de terminal
openclaw plugins install @openclaw/mattermost

Instalación local (si usas un repositorio de git):

Ventana de terminal
openclaw plugins install ./path/to/local/mattermost-plugin

Si eliges Mattermost durante la configuración y se detecta un repositorio de git, OpenClaw te ofrecerá la ruta de instalación local automáticamente.

Detalles: Plugins

  1. Instala el plugin de Mattermost.
  2. Crea una cuenta de bot en Mattermost y copia el bot token.
  3. Copia la base URL de Mattermost (ej., https://chat.example.com).
  4. Configura OpenClaw e inicia el gateway.

Configuración mínima:

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

Los slash commands nativos son opcionales. Al activarlos, OpenClaw registra los comandos oc_* a través de la API de Mattermost y recibe callbacks POST en el servidor 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",
},
},
},
}

Notas:

  • native: "auto" está desactivado por defecto en Mattermost. Cambia a native: true para activarlo.
  • Si omites callbackUrl, OpenClaw genera una basada en el host/puerto del gateway + callbackPath.
  • En configuraciones multicuenta, puedes definir commands en el nivel superior o en channels.mattermost.accounts.<id>.commands (los valores de cuenta sobrescriben los campos generales).
  • Los callbacks de los comandos se validan con tokens por comando y la petición fallará si la comprobación del token no es correcta.
  • Requisito de conectividad: el servidor de Mattermost debe poder llegar al endpoint del callback.
    • No uses localhost en callbackUrl a menos que Mattermost y OpenClaw compartan el mismo host o espacio de nombres de red.
    • No uses tu URL base de Mattermost en callbackUrl a menos que ese dominio actúe como reverse proxy de /api/channels/mattermost/command hacia OpenClaw.
    • Una comprobación rápida es curl https://<gateway-host>/api/channels/mattermost/command; un GET debería devolver 405 Method Not Allowed desde OpenClaw, no un 404.
  • Requisito de lista de permitidos (egress allowlist) en Mattermost:
    • Si tu callback apunta a direcciones privadas, tailnet o internas, configura ServiceSettings.AllowedUntrustedInternalConnections en Mattermost para incluir el host o dominio del callback.
    • Usa nombres de host o dominios, no la URL completa.
      • Correcto: gateway.tailnet-name.ts.net
      • Incorrecto: https://gateway.tailnet-name.ts.net

Configura estas variables en el host del gateway si prefieres usar variables de entorno:

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

Estas variables solo se aplican a la cuenta por defecto (default). Otras cuentas deben usar los valores del archivo de configuración.

Mattermost responde a los DMs automáticamente. El comportamiento en los canales se controla mediante chatmode:

  • oncall (predeterminado): responde solo cuando te mencionan con @ en los canales.
  • onmessage: responde a cada mensaje del canal.
  • onchar: responde cuando un mensaje comienza con un prefijo activador.

Ejemplo de configuración:

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

Notas:

  • onchar sigue respondiendo a las menciones explícitas con @.
  • Se respeta channels.mattermost.requireMention para configuraciones antiguas, pero es preferible usar chatmode.

Usa channels.mattermost.replyToMode para controlar si las respuestas en canales y grupos se mantienen en el canal principal o inician un hilo debajo de la publicación original.

  • off (predeterminado): solo responde en un hilo cuando el mensaje entrante ya forma parte de uno.
  • first: para publicaciones de nivel superior en canales o grupos, inicia un hilo debajo de esa publicación y dirige la conversación a una sesión con alcance de hilo.
  • all: mismo comportamiento que first actualmente en Mattermost.
  • Los mensajes directos ignoran este ajuste y no usan hilos.

Ejemplo de configuración:

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

Notas:

  • Las sesiones con alcance de hilo usan el ID de la publicación original como raíz del hilo.
  • first y all son equivalentes por ahora porque una vez que Mattermost tiene una raíz de hilo, los fragmentos de seguimiento y archivos multimedia continúan en ese mismo hilo.
  • Predeterminado: channels.mattermost.dmPolicy = "pairing" (los remitentes desconocidos reciben un código de emparejamiento).
  • Aprobar mediante:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • DMs públicos: channels.mattermost.dmPolicy="open" más channels.mattermost.allowFrom=["*"].
  • Predeterminado: channels.mattermost.groupPolicy = "allowlist" (restringido por mención).
  • Autoriza remitentes con channels.mattermost.groupAllowFrom (se recomiendan IDs de usuario).
  • La coincidencia por @username es mutable y solo se activa cuando channels.mattermost.dangerouslyAllowNameMatching: true.
  • Canales abiertos: channels.mattermost.groupPolicy="open" (restringido por mención).
  • Nota de ejecución: si falta channels.mattermost por completo, el sistema vuelve a groupPolicy="allowlist" para las comprobaciones de grupo (incluso si channels.defaults.groupPolicy está configurado).

Usa estos formatos de destino con openclaw message send o con cron/webhooks:

  • channel:<id> para un canal
  • user:<id> para un DM
  • @username para un DM (se resuelve mediante la API de Mattermost)

Los IDs puros (como 64ifufp...) son ambiguos en Mattermost (ID de usuario vs ID de canal).

OpenClaw los resuelve priorizando al usuario:

  • Si el ID existe como usuario (si GET /api/v4/users/<id> tiene éxito), OpenClaw envía un DM resolviendo el canal directo a través de /api/v4/channels/direct.
  • De lo contrario, el ID se trata como un ID de canal.

Si necesitas un comportamiento determinista, te recomiendo usar siempre los prefijos explícitos (user:<id> / channel:<id>).

Cuando OpenClaw envía a un destino de DM en Mattermost y necesita resolver el canal directo primero, reintenta por defecto los fallos temporales en la creación del canal directo.

Usa channels.mattermost.dmChannelRetry para ajustar este comportamiento de forma global para el plugin de Mattermost, o channels.mattermost.accounts.<id>.dmChannelRetry para una cuenta específica.

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

Notas:

  • Esto se aplica solo a la creación de canales DM (/api/v4/channels/direct), no a todas las llamadas de la API de Mattermost.
  • Los reintentos se aplican a fallos temporales como límites de tasa, respuestas 5xx y errores de red o de tiempo de espera.
  • Los errores de cliente 4xx que no sean 429 se consideran permanentes y no se reintentan.
  • Usa message action=react con channel=mattermost.
  • messageId es el ID del post de Mattermost.
  • emoji acepta nombres como thumbsup o :+1: (los dos puntos son opcionales).
  • Establece remove=true (booleano) para eliminar una reacción.
  • Los eventos de añadir o eliminar reacciones se reenvían como eventos de sistema a la sesión del agente enrutado.

Ejemplos:

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

Configuración:

  • channels.mattermost.actions.reactions: activa o desactiva las acciones de reacción (por defecto es true).
  • Sobrescritura por cuenta: channels.mattermost.accounts.<id>.actions.reactions.

Botones interactivos (herramienta de mensaje)

Sección titulada «Botones interactivos (herramienta de mensaje)»

Envía mensajes con botones en los que se puede hacer clic. Cuando tú o cualquier usuario pulsa un botón, el agente recibe la selección y puede responder de inmediato.

Activa los botones añadiendo inlineButtons a las capacidades del canal:

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

Usa message action=send con un parámetro buttons. Los botones se definen como un array 2D (filas de botones):

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

Campos de los botones:

  • text (obligatorio) y callback_data (obligatorio): el primero es la etiqueta visual y el segundo es el valor que se envía de vuelta al hacer clic (usado como ID de la acción).
  • style (opcional): puedes elegir entre "default", "primary" o "danger".

Cuando alguien hace clic en un botón:

  1. Todos los botones se reemplazan por una línea de confirmación (por ejemplo, ”✓ Yes seleccionado por @user”).
  2. El agente recibe la selección como un mensaje entrante y genera una respuesta.

Notas importantes:

  • Los callbacks de los botones utilizan verificación HMAC-SHA256 de forma automática, así que no necesitas configurar nada para la seguridad. Además, Mattermost elimina los datos de callback de sus respuestas de API, por lo que todos los botones desaparecen al hacer clic (no se pueden quitar de uno en uno).
  • Los IDs de acción que contengan guiones o guiones bajos se limpian automáticamente debido a una limitación en el enrutamiento de Mattermost.

Configuración:

  • channels.mattermost.capabilities: array de strings de capacidad. Añade "inlineButtons" para que la descripción de la herramienta de botones aparezca en el system prompt del agente.
  • channels.mattermost.interactions.callbackBaseUrl: URL base externa opcional para los callbacks (por ejemplo https://gateway.example.com). Úsala si Mattermost no puede conectar directamente con el Gateway en su host de enlace.
  • En instalaciones con varias cuentas, puedes configurar este mismo campo en channels.mattermost.accounts.<id>.interactions.callbackBaseUrl.
  • Si no defines interactions.callbackBaseUrl, OpenClaw calculará la URL usando gateway.customBindHost + gateway.port, o usará http://localhost:<port> como último recurso.
  • Regla de conectividad: la URL de callback debe ser accesible desde el servidor de Mattermost. localhost solo te servirá si Mattermost y OpenClaw comparten el mismo host o red.
  • Si tu destino de callback es interno o privado (como una tailnet), recuerda añadir el host a ServiceSettings.AllowedUntrustedInternalConnections en la configuración de Mattermost.

Integración directa con la API (scripts externos)

Sección titulada «Integración directa con la API (scripts externos)»

Si usas scripts externos o webhooks, puedes publicar botones directamente con la API REST de Mattermost sin pasar por la herramienta message del agente. Te recomiendo usar buildButtonAttachments() de la extensión si es posible. Si prefieres enviar el JSON puro, sigue estas reglas:

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

Reglas críticas:

  1. Los adjuntos deben ir en props.attachments. Si los pones en el nivel superior attachments, Mattermost los ignorará sin avisar.
  2. Cada acción necesita obligatoriamente type: "button" e id. Sin estos campos, los clics no funcionarán.
  3. El id de la acción debe ser solo alfanumérico ([a-zA-Z0-9]). Los guiones o guiones bajos provocan errores 404 en el servidor de Mattermost.
  4. context.action_id es obligatorio y debe coincidir con el id del botón para que el mensaje de confirmación muestre el nombre correcto (ej. “Approve”).
  5. Si falta context.action_id, el manejador de interacciones devolverá un error 400.
  6. Asegúrate de que el Gateway sea accesible desde la red donde corre Mattermost.

Generación del token HMAC:

El Gateway valida los clics mediante HMAC-SHA256. Tus scripts deben generar tokens que sigan esta lógica:

  1. Deriva el secreto usando el token del bot: HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken).
  2. Prepara el objeto de contexto con todos tus campos, pero excluye el campo _token.
  3. Serializa el objeto con las claves ordenadas alfabéticamente y sin espacios (formato compacto de JSON).
  4. Firma el resultado: HMAC-SHA256(key=secret, data=serializedContext) y añade el digest hexadecimal como _token.

Ejemplo en 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}

Errores comunes con HMAC:

  • Python añade espacios en json.dumps por defecto. Usa separators=(",", ":") para que coincida con la salida de JavaScript.
  • Debes firmar todos los campos del contexto. Si firmas solo una parte, la verificación fallará silenciosamente en el Gateway.
  • No olvides sort_keys=True, ya que el Gateway siempre ordena las claves antes de verificar la firma.
  • El secreto debe derivarse siempre del token del bot para que sea consistente entre quien crea el botón y el Gateway que lo valida.

AI Setup Assistant

  • Configuración del Gateway
  • Gestión de permisos en Mattermost
  • Personalización de respuestas del agente

El plugin de Mattermost incluye un adaptador de directorio que resuelve nombres de canales y usuarios a través de la API de Mattermost. Esto permite usar objetivos como #nombre-del-canal y @nombre-de-usuario en openclaw message send y en entregas de cron/webhook.

No necesitas realizar ninguna configuración adicional: el adaptador utiliza el token del bot que ya definiste en la configuración de la cuenta.

Mattermost admite el uso de varias cuentas bajo la clave 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" },
},
},
},
}
  • No hay respuestas en los canales: asegúrate de que el bot esté en el canal y menciónalo (oncall), usa un prefijo de activación (onchar) o configura chatmode: "onmessage".
  • Errores de autenticación: revisa el token del bot y la URL base, además de confirmar si la cuenta está habilitada.
  • Problemas con múltiples cuentas: las variables de entorno solo se aplican a la cuenta default.
  • Los botones aparecen como cuadros blancos: es posible que el agent esté enviando datos de botones malformados. Comprueba que cada botón incluya los campos text y callback_data.
  • Los botones aparecen pero al hacer clic no pasa nada: verifica que AllowedUntrustedInternalConnections en la configuración del servidor de Mattermost incluya 127.0.0.1 localhost y que EnablePostActionIntegration esté en true dentro de ServiceSettings.
  • Los botones devuelven un error 404 al hacer clic: es probable que el id del botón contenga guiones o guiones bajos. El router de acciones de Mattermost falla con IDs que no sean alfanuméricos. Usa solo [a-zA-Z0-9].
  • El Gateway registra invalid _token: error de coincidencia de HMAC. Revisa que firmes todos los campos de contexto (no solo una parte) y que uses tanto claves ordenadas como JSON compacto (sin espacios). Consulta la sección de HMAC anterior.
  • El Gateway registra missing _token in context: el campo _token no está en el contexto del botón. Asegúrate de incluirlo al construir el payload de integración.
  • La confirmación muestra el ID sin procesar en lugar del nombre del botón: context.action_id no coincide con el id del botón. Configura ambos con el mismo valor saneado.
  • El agent no reconoce los botones: añade capabilities: ["inlineButtons"] a la configuración del canal de Mattermost.
  • Channels Overview — todos los canales soportados
  • Pairing — flujo de autenticación y vinculación (pairing) por DM
  • Groups — comportamiento en chats grupales y menciones
  • Channel Routing — enrutamiento de sesiones para mensajes
  • Security — modelo de acceso y endurecimiento de seguridad
OpenClaw

OpenClaw Expert

Sigues atascado?

Si esta pagina no resolvio tu caso, pregunta a OpenClaw Expert para pasos concretos.