Ir al contenido

Conecta OpenClaw con Microsoft Teams: Guía de instalación

“Abandonad toda esperanza, los que entráis aquí.”

Actualizado: 2026-01-21

Estado: el texto y los adjuntos en DM están soportados; el envío de archivos en canales o grupos requiere sharePointSiteId + permisos de Graph (ver Sending files in group chats). Las encuestas se envían mediante Adaptive Cards. Las acciones de mensaje exponen upload-file de forma explícita para envíos donde el archivo es lo primero.

Microsoft Teams se distribuye como un plugin y no viene incluido en la instalación core.

Cambio importante (2026.1.15): Microsoft Teams salió del core. Si lo usas, tienes que instalar el plugin.

La razón es sencilla: esto mantiene las instalaciones core más ligeras y permite que las dependencias de Microsoft Teams se actualicen de forma independiente.

Instala mediante la CLI (registro npm):

Ventana de terminal
openclaw plugins install @openclaw/msteams

Checkout local (si ejecutas desde un repo de git):

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

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

Detalles: Plugins

  1. Instala el plugin de Microsoft Teams.
  2. Crea un Azure Bot (App ID + client secret + tenant ID).
  3. Configura OpenClaw con esas credenciales.
  4. Expón /api/messages (puerto 3978 por defecto) mediante una URL pública o un túnel.
  5. Instala el paquete de la app de Teams e inicia el Gateway.

Configuración mínima:

{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
appPassword: "<APP_PASSWORD>",
tenantId: "<TENANT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}

Nota: los chats grupales están bloqueados por defecto (channels.msteams.groupPolicy: "allowlist"). Para permitir respuestas en grupo, configura channels.msteams.groupAllowFrom (o usa groupPolicy: "open" para permitir a cualquier miembro, restringido por menciones).

  • Hablar con OpenClaw mediante DMs de Teams, chats grupales o canales.
  • Mantener el enrutamiento determinista: las respuestas siempre vuelven al canal por el que llegaron.
  • Priorizar un comportamiento seguro en los canales (se requieren menciones a menos que se configure lo contrario).

Por defecto, Microsoft Teams tiene permiso para escribir actualizaciones de configuración activadas por /config set|unset (requiere commands.config: true).

Desactívalo con:

{
channels: { msteams: { configWrites: false } },
}

Acceso a DM

  • Por defecto: channels.msteams.dmPolicy = "pairing". Los remitentes desconocidos se ignoran hasta que los apruebes.
  • channels.msteams.allowFrom debe usar IDs de objeto de AAD estables.
  • Los UPN/nombres de pantalla pueden cambiar; la coincidencia directa está desactivada por defecto y solo se activa con channels.msteams.dangerouslyAllowNameMatching: true.
  • El asistente puede resolver nombres a IDs mediante Microsoft Graph cuando las credenciales lo permitan.

Acceso a grupos

  • Por defecto: channels.msteams.groupPolicy = "allowlist" (bloqueado a menos que añadas groupAllowFrom). Usa channels.defaults.groupPolicy para sobrescribir el valor por defecto si no está configurado.
  • channels.msteams.groupAllowFrom controla qué remitentes pueden activar acciones en chats de grupo o canales (si no se define, usa channels.msteams.allowFrom).
  • Configura groupPolicy: "open" para permitir a cualquier miembro (aunque por defecto sigue filtrado por menciones).
  • Para no permitir ningún canal, usa channels.msteams.groupPolicy: "disabled".

Ejemplo:

{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["user@org.com"],
},
},
}

Lista de permitidos para Teams + canales

  • Limita las respuestas en grupos/canales listando los equipos y canales bajo channels.msteams.teams.
  • Las claves deben usar IDs de equipo e IDs de conversación de canal estables.
  • Cuando groupPolicy="allowlist" y hay una lista de permitidos de equipos, solo se aceptan los equipos/canales listados (filtrados por mención).
  • El asistente de configuración acepta entradas de Team/Channel y las guarda por ti.
  • Al arrancar, OpenClaw resuelve los nombres de la lista de permitidos de equipos/canales y usuarios a IDs (si los permisos de Graph lo permiten) y registra el mapeo; los nombres no resueltos se mantienen tal cual, pero se ignoran para el enrutamiento por defecto a menos que actives channels.msteams.dangerouslyAllowNameMatching: true.

Ejemplo:

{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
  1. Instala el plugin de Microsoft Teams.
  2. Crea un Azure Bot (App ID + secreto + ID de inquilino).
  3. Crea un paquete de aplicación de Teams que haga referencia al bot e incluya los permisos RSC de abajo.
  4. Sube o instala la aplicación de Teams en un equipo (o en el ámbito personal para DMs).
  5. Configura msteams en ~/.openclaw/openclaw.json (o variables de entorno) e inicia el Gateway.
  6. El Gateway escucha el tráfico del webhook del Bot Framework en /api/messages por defecto.

Configuración de Azure Bot (Requisitos previos)

Sección titulada «Configuración de Azure Bot (Requisitos previos)»

Antes de configurar OpenClaw, necesitas crear un recurso de Azure Bot.

  1. Ve a Create Azure Bot

  2. Rellena la pestaña Basics:

    CampoValor
    Bot handleEl nombre de tu bot, ej., openclaw-msteams (debe ser único)
    SubscriptionSelecciona tu suscripción de Azure
    Resource groupCrea uno nuevo o usa uno existente
    Pricing tierFree para desarrollo/pruebas
    Type of AppSingle Tenant (recomendado - mira la nota de abajo)
    Creation typeCreate new Microsoft App ID

Aviso de obsolescencia: La creación de nuevos bots multi-inquilino quedó obsoleta después del 2025-07-31. Usa Single Tenant para bots nuevos.

  1. Haz clic en Review + create → Create (espera 1-2 minutos)
  1. Ve a tu recurso de Azure Bot → Configuration
  2. Copia el Microsoft App ID → este es tu appId
  3. Haz clic en Manage Password → ve a App Registration
  4. En Certificates & secrets → New client secret → copia el Value → este es tu appPassword
  5. Ve a Overview → copia el Directory (tenant) ID → este es tu tenantId

Paso 3: Configurar el endpoint de mensajería

Sección titulada «Paso 3: Configurar el endpoint de mensajería»
  1. En Azure Bot → Configuration
  2. Configura el Messaging endpoint con la URL de tu webhook:
    • Producción: https://tu-dominio.com/api/messages
    • Desarrollo local: Usa un túnel (mira la sección Desarrollo local más abajo)
  1. En Azure Bot → Channels
  2. Haz clic en Microsoft Teams → Configure → Save
  3. Acepta los Términos de Servicio

Teams no puede llegar a localhost. Usa un túnel para el desarrollo local:

Opción A: ngrok

Ventana de terminal
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages

Opción B: Tailscale Funnel

Ventana de terminal
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint

En lugar de crear manualmente un manifest en ZIP, puedes usar el Teams Developer Portal:

  1. Haz clic en + New app.
  2. Completa la información básica (nombre, descripción, información del desarrollador).
  3. Ve a App features → Bot.
  4. Selecciona Enter a bot ID manually y pega tu Azure Bot App ID.
  5. Marca los scopes: Personal, Team, Group Chat.
  6. Haz clic en Distribute → Download app package.
  7. En Teams: Apps → Manage your apps → Upload a custom app → selecciona el archivo ZIP.

Este método suele ser más sencillo que editar archivos JSON a mano.

Opción A: Azure Web Chat (verifica el webhook primero)

  1. En Azure Portal → ve a tu recurso Azure Bot → Test in Web Chat.
  2. Envía un mensaje; deberías recibir una respuesta.
  3. Esto confirma que tu endpoint de webhook funciona antes de configurar Teams.

Opción B: Teams (después de instalar la app)

  1. Instala la app de Teams (mediante sideload o el catálogo de tu organización).
  2. Busca el bot en Teams y envíale un mensaje directo (DM).
  3. Revisa los logs del Gateway para ver la actividad entrante.
  1. Instala el plugin de Microsoft Teams

    • Desde npm: openclaw plugins install @openclaw/msteams
    • Desde un directorio local: openclaw plugins install ./path/to/local/msteams-plugin
  2. Registro del bot

    • Crea un Azure Bot (mencionado arriba) y anota:
      • App ID
      • Client secret (App password)
      • Tenant ID (single-tenant)
  3. Manifest de la app de Teams

    • Incluye una entrada bot con botId = <App ID>.
    • Scopes: personal, team, groupChat.
    • supportsFiles: true (necesario para el manejo de archivos en el scope personal).
    • Añade los permisos RSC (detallados abajo).
    • Crea los iconos: outline.png (32x32) y color.png (192x192).
    • Comprime los tres archivos en un ZIP: manifest.json, outline.png, color.png.
  4. Configura OpenClaw

    {
    channels: {
    msteams: {
    enabled: true,
    appId: "<APP_ID>",
    appPassword: "<APP_PASSWORD>",
    tenantId: "<TENANT_ID>",
    webhook: { port: 3978, path: "/api/messages" },
    },
    },
    }

    También puedes usar variables de entorno en lugar de las claves de configuración:

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Endpoint del bot

    • Configura el Azure Bot Messaging Endpoint como:
      • https://<host>:3978/api/messages (o el puerto/ruta que hayas elegido).
  6. Ejecuta el Gateway

    • El canal de Teams se inicia automáticamente cuando el plugin está instalado y existe la configuración de msteams con las credenciales.

Acción de información de miembros (Member info action)

Sección titulada «Acción de información de miembros (Member info action)»

OpenClaw ofrece una acción member-info para Microsoft Teams conectada a Graph. Esto permite que los agentes y automatizaciones obtengan detalles de los miembros del canal (nombre visible, email, rol) directamente desde Microsoft Graph.

Requisitos:

  • Permiso RSC Member.Read.Group (ya incluido en el manifest recomendado).
  • Para búsquedas entre diferentes equipos: permiso de aplicación de Graph User.Read.All con consentimiento del administrador.

La acción se controla mediante channels.msteams.actions.memberInfo (activada por defecto cuando las credenciales de Graph están disponibles).

  • channels.msteams.historyLimit controla cuántos mensajes recientes de canales o grupos se incluyen en el prompt.
  • Si no se define, usa messages.groupChat.historyLimit. Ponlo en 0 para desactivarlo (por defecto es 50).
  • El historial del hilo obtenido se filtra mediante listas de permitidos de remitentes (allowFrom / groupAllowFrom), por lo que el contexto del hilo solo incluye mensajes de remitentes autorizados.
  • El historial de DM se puede limitar con channels.msteams.dmHistoryLimit (turnos de usuario). Ajustes por usuario: channels.msteams.dms["<user_id>"].historyLimit.

Estos son los permisos resourceSpecific existentes en el manifest de tu app de Teams. Solo se aplican dentro del equipo o chat donde la app esté instalada.

Para canales (scope de equipo):

  • ChannelMessage.Read.Group (Application) - recibe todos los mensajes del canal sin necesidad de @mención.
  • ChannelMessage.Send.Group (Application)
  • Member.Read.Group (Application)
  • Owner.Read.Group (Application)
  • ChannelSettings.Read.Group (Application)
  • TeamMember.Read.Group (Application)
  • TeamSettings.Read.Group (Application)

Para chats grupales:

  • ChatMessage.Read.Chat (Application) - recibe todos los mensajes del chat grupal sin necesidad de @mención.

Ejemplo mínimo y válido con los campos requeridos. Reemplaza los IDs y las URLs.

{
$schema: "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
manifestVersion: "1.23",
version: "1.0.0",
id: "00000000-0000-0000-0000-000000000000",
name: { short: "OpenClaw" },
developer: {
name: "Your Org",
websiteUrl: "https://example.com",
privacyUrl: "https://example.com/privacy",
termsOfUseUrl: "https://example.com/terms",
},
description: { short: "OpenClaw in Teams", full: "OpenClaw in Teams" },
icons: { outline: "outline.png", color: "color.png" },
accentColor: "#5B6DEF",
bots: [
{
botId: "11111111-1111-1111-1111-111111111111",
scopes: ["personal", "team", "groupChat"],
isNotificationOnly: false,
supportsCalling: false,
supportsVideo: false,
supportsFiles: true,
},
],
webApplicationInfo: {
id: "11111111-1111-1111-1111-111111111111",
},
authorization: {
permissions: {
resourceSpecific: [
{ name: "ChannelMessage.Read.Group", type: "Application" },
{ name: "ChannelMessage.Send.Group", type: "Application" },
{ name: "Member.Read.Group", type: "Application" },
{ name: "Owner.Read.Group", type: "Application" },
{ name: "ChannelSettings.Read.Group", type: "Application" },
{ name: "TeamMember.Read.Group", type: "Application" },
{ name: "TeamSettings.Read.Group", type: "Application" },
{ name: "ChatMessage.Read.Chat", type: "Application" },
],
},
},
}

Notas sobre el manifest (campos obligatorios)

Sección titulada «Notas sobre el manifest (campos obligatorios)»
  • bots[].botId y webApplicationInfo.id deben coincidir con el App ID del Azure Bot.
  • bots[].scopes debe incluir las superficies que planeas usar (personal, team, groupChat).
  • bots[].supportsFiles: true es necesario para el manejo de archivos en el scope personal.
  • authorization.permissions.resourceSpecific debe incluir lectura/envío en canales si quieres tráfico de canales.

Para actualizar una app de Teams ya instalada (por ejemplo, para añadir permisos RSC):

  1. Actualiza tu manifest.json con los nuevos ajustes.
  2. Incrementa el campo version (ej. 1.0.0 → 1.1.0).
  3. Vuelve a comprimir (zip) el manifest con los iconos (manifest.json, outline.png, color.png).
  4. Sube el nuevo zip:
    • Opción A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → busca tu app → Upload new version.
    • Opción B (Sideload): En Teams → Apps → Manage your apps → Upload a custom app.
  5. Para canales de equipo: Reinstala la app en cada equipo para que los nuevos permisos surtan efecto.
  6. Cierra Teams por completo y vuelve a abrirlo (no solo cierres la ventana) para limpiar los metadatos en caché de la app.

Con solo Teams RSC (app instalada, sin permisos de Graph API)

Sección titulada «Con solo Teams RSC (app instalada, sin permisos de Graph API)»

Funciona:

  • Leer y enviar contenido de texto en mensajes del canal.
  • Recibir archivos adjuntos en mensajes directos (DM).

NO funciona:

  • Acceder a contenido de imágenes o archivos en canales/grupos, ni descargar adjuntos de SharePoint/OneDrive.
  • Leer el historial de mensajes (más allá del evento del webhook en vivo).

Con Teams RSC + permisos de aplicación de Microsoft Graph

Sección titulada «Con Teams RSC + permisos de aplicación de Microsoft Graph»

Añade:

  • Descarga de contenidos alojados (imágenes) y archivos adjuntos guardados en SharePoint/OneDrive.
  • Lectura del historial de mensajes de canales/chats mediante Graph.
CapacidadPermisos RSCGraph API
Mensajes en tiempo realSí (vía webhook)No (solo polling)
Mensajes históricosNoSí (puedes consultar historial)
Complejidad de configuraciónSolo el manifest de la appRequiere consentimiento del admin + flujo de tokens
Funciona offlineNo (debe estar en ejecución)Sí (consulta en cualquier momento)

En resumen: RSC sirve para escuchar en tiempo real; Graph API es para acceso histórico. Para recuperar mensajes perdidos mientras estabas offline, necesitas Graph API con ChannelMessage.Read.All (requiere consentimiento del administrador).

Multimedia e historial habilitados por Graph (necesario para canales)

Sección titulada «Multimedia e historial habilitados por Graph (necesario para canales)»

Si necesitas imágenes o archivos en los canales o quieres obtener el historial de mensajes, tienes que activar los permisos de Microsoft Graph y conceder el consentimiento del administrador.

  1. En la App Registration de Entra ID (Azure AD), añade los siguientes Application permissions de Microsoft Graph:
    • ChannelMessage.Read.All (adjuntos de canal e historial)
    • Chat.Read.All o ChatMessage.Read.All (chats grupales)
  2. Concede el consentimiento del administrador para el tenant.
  3. Sube la versión del manifest de la app de Teams, vuelve a cargarla y reinstala la app en Teams.
  4. Cierra completamente y reinicia Teams para limpiar los metadatos de la app en caché.

Permiso adicional para menciones de usuarios: Las menciones @ funcionan de forma nativa para los usuarios que ya están en la conversación. Sin embargo, si quieres buscar y mencionar dinámicamente a usuarios que no están en la conversación actual, añade el permiso User.Read.All (Application) y concede el consentimiento del administrador.

Teams entrega los mensajes mediante un webhook HTTP. Si el procesamiento tarda demasiado (por ejemplo, por respuestas lentas de un LLM), podrías experimentar:

  • Gateway timeouts
  • Teams reintentando el envío del mensaje (causando duplicados)
  • Respuestas perdidas o descartadas
  • Errores de sincronización en el cliente

OpenClaw gestiona esto respondiendo rápido y enviando las respuestas de forma proactiva, pero las respuestas extremadamente lentas aún pueden causar problemas.

El markdown de Teams es más limitado que el de Slack o Discord:

  • El formato básico funciona: negrita, cursiva, código, enlaces
  • Es posible que el markdown complejo (tablas, listas anidadas) no se renderice correctamente
  • Se admiten Adaptive Cards para encuestas y envío de tarjetas personalizadas (ver más abajo)

Ajustes clave (consulta /gateway/configuration para patrones de canales compartidos):

  • channels.msteams.enabled: activa o desactiva el canal.
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId: credenciales del bot.
  • channels.msteams.webhook.port (por defecto 3978)
  • channels.msteams.webhook.path (por defecto /api/messages)
  • channels.msteams.dmPolicy: pairing | allowlist | open | disabled (por defecto: pairing)
  • channels.msteams.allowFrom: lista de permitidos para DM (se recomiendan AAD object IDs). El asistente resuelve los nombres a IDs durante la configuración si el acceso a Graph está disponible.
  • channels.msteams.dangerouslyAllowNameMatching: interruptor de emergencia para volver a activar la coincidencia por UPN/nombre de pantalla mutable y el enrutamiento directo por nombre de equipo/canal.
  • channels.msteams.textChunkLimit: tamaño del fragmento de texto de salida.
  • channels.msteams.chunkMode: length (por defecto) o newline para dividir por líneas en blanco (límites de párrafo) antes de fragmentar por longitud.
  • channels.msteams.mediaAllowHosts: lista de hosts permitidos para adjuntos entrantes (por defecto los dominios de Microsoft/Teams).
  • channels.msteams.mediaAuthAllowHosts: lista de permitidos para adjuntar cabeceras de Authorization en reintentos de multimedia (por defecto hosts de Graph + Bot Framework).
  • channels.msteams.requireMention: requiere mención @ en canales/grupos (por defecto true).
  • channels.msteams.replyStyle: thread | top-level (ver Reply Style).
  • channels.msteams.teams.<teamId>.replyStyle: anulación por equipo.
  • channels.msteams.teams.<teamId>.requireMention: anulación por equipo.
  • channels.msteams.teams.<teamId>.tools: anulaciones de política de herramientas por equipo (allow/deny/alsoAllow) usadas cuando falta una anulación de canal.
  • channels.msteams.teams.<teamId>.toolsBySender: anulaciones de política de herramientas por remitente dentro de un equipo (admite el comodín "*").
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: anulación por canal.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: anulación por canal.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools: anulaciones de política de herramientas por canal (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: anulaciones de política de herramientas por remitente dentro de un canal (admite el comodín "*").
  • Las claves de toolsBySender deben usar prefijos explícitos: id:, e164:, username:, name: (las claves antiguas sin prefijo todavía se mapean solo a id:).
  • channels.msteams.actions.memberInfo: activa o desactiva la acción de información de miembros respaldada por Graph (por defecto: activado cuando las credenciales de Graph están disponibles.
  • channels.msteams.sharePointSiteId: ID del sitio de SharePoint para la subida de archivos en chats grupales/canales (ver Sending files in group chats).
  • Las claves de sesión siguen el formato estándar de agente (ver /concepts/session):
    • Los mensajes directos comparten la sesión principal (agent:<agentId>:<mainKey>).
    • Los mensajes de canal o grupo usan el ID de conversación:
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Teams introdujo hace poco dos estilos de interfaz para los canales sobre el mismo modelo de datos:

EstiloDescripciónreplyStyle recomendado
Posts (clásico)Los mensajes aparecen como tarjetas con respuestas anidadas debajothread (por defecto)
Threads (tipo Slack)Los mensajes fluyen de forma lineal, de manera similar a Slacktop-level

El problema: La API de Teams no indica qué estilo de interfaz utiliza un canal. Si usas el replyStyle equivocado:

  • thread en un canal estilo Threads → las respuestas aparecen anidadas de forma extraña.
  • top-level en un canal estilo Posts → las respuestas aparecen como publicaciones independientes en lugar de estar dentro del hilo.

Solución: Configura el replyStyle por canal basándote en cómo esté configurado cada uno:

{
channels: {
msteams: {
replyStyle: "thread",
teams: {
"19:abc...@thread.tacv2": {
channels: {
"19:xyz...@thread.tacv2": {
replyStyle: "top-level",
},
},
},
},
},
},
}

Limitaciones actuales:

  • DMs: Las imágenes y los archivos adjuntos funcionan a través de las API de archivos del bot de Teams.
  • Canales/grupos: Los adjuntos se guardan en el almacenamiento de M365 (SharePoint/OneDrive). El payload del webhook solo incluye un fragmento HTML, no los bytes reales del archivo. Se requieren permisos de la Graph API para descargar adjuntos de canales.
  • Para envíos explícitos de archivos, usa action=upload-file con media / filePath / path; el campo opcional message se convierte en el texto o comentario que lo acompaña, y filename sobrescribe el nombre del archivo subido.

Sin permisos de Graph, los mensajes de canal con imágenes se recibirán solo como texto (el bot no puede acceder al contenido de la imagen). Por defecto, OpenClaw solo descarga contenido multimedia de hostnames de Microsoft/Teams. Puedes cambiar esto con channels.msteams.mediaAllowHosts (usa ["*"] para permitir cualquier host). Los encabezados de autorización solo se adjuntan para los hosts en channels.msteams.mediaAuthAllowHosts (por defecto son los hosts de Graph + Bot Framework). Mantén esta lista restringida y evita sufijos multi-tenant.

Los bots pueden enviar archivos en DMs usando el flujo FileConsentCard (ya integrado). Sin embargo, enviar archivos en chats grupales o canales requiere una configuración adicional:

ContextoCómo se envían los archivosConfiguración necesaria
DMsFileConsentCard → usuario acepta → bot subeFunciona de inmediato
Chats grupales/canalesSubida a SharePoint → compartir enlaceRequiere sharePointSiteId + permisos de Graph
Imágenes (cualquier contexto)Inline codificado en Base64Funciona de inmediato

¿Por qué los chats grupales necesitan SharePoint?

Sección titulada «¿Por qué los chats grupales necesitan SharePoint?»

Los bots no tienen una unidad de OneDrive personal (el endpoint /me/drive de la Graph API no funciona para identidades de aplicación). Para enviar archivos en chats grupales o canales, el bot sube el archivo a un sitio de SharePoint y crea un enlace para compartir.

  1. Añade permisos de la Graph API en Entra ID (Azure AD) → App Registration:

    • Sites.ReadWrite.All (Application) - para subir archivos a SharePoint.
    • Chat.Read.All (Application) - opcional, permite enlaces para compartir por usuario.
  2. Concede consentimiento de administrador para el tenant.

  3. Obtén el ID de tu sitio de SharePoint:

    Ventana de terminal
    # Via Graph Explorer or curl with a valid token:
    curl -H "Authorization: Bearer $TOKEN" \
    "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
    # Example: for a site at "contoso.sharepoint.com/sites/BotFiles"
    curl -H "Authorization: Bearer $TOKEN" \
    "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
    # Response includes: "id": "contoso.sharepoint.com,guid1,guid2"
  4. Configura OpenClaw:

    {
    channels: {
    msteams: {
    // ... other config ...
    sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
    },
    },
    }
PermisoComportamiento al compartir
Solo Sites.ReadWrite.AllEnlace para toda la organización (cualquiera puede entrar)
Sites.ReadWrite.All + Chat.Read.AllEnlace por usuario (solo miembros del chat pueden entrar)

El uso compartido por usuario es más seguro, ya que solo los participantes del chat pueden acceder al archivo. Si falta el permiso Chat.Read.All, el bot usará por defecto el uso compartido para toda la organización.

EscenarioResultado
Chat grupal + archivo + sharePointSiteId listoSube a SharePoint, envía enlace para compartir
Chat grupal + archivo + sin sharePointSiteIdIntenta subir a OneDrive (puede fallar), solo texto
Chat personal + archivoFlujo FileConsentCard (funciona sin SharePoint)
Cualquier contexto + imagenInline codificado en Base64 (funciona sin SharePoint)

Los archivos subidos se guardan en una carpeta llamada /OpenClawShared/ dentro de la biblioteca de documentos por defecto del sitio de SharePoint configurado.

OpenClaw envía las encuestas de Teams como Adaptive Cards (no existe una API nativa de encuestas para Teams).

  • CLI: openclaw message poll --channel msteams --target conversation:<id> ...
  • Los votos los registra el Gateway en ~/.openclaw/msteams-polls.json.
  • El Gateway debe permanecer online para registrar los votos.
  • Las encuestas aún no publican resúmenes de resultados automáticamente (revisa el archivo de almacenamiento si es necesario).

AI Setup Assistant

Envía cualquier JSON de Adaptive Card a usuarios o conversaciones de Teams usando la herramienta message o la CLI.

El parámetro card acepta un objeto JSON de Adaptive Card. Cuando proporcionas card, el texto del mensaje es opcional.

Agent tool:

{
action: "send",
channel: "msteams",
target: "user:<id>",
card: {
type: "AdaptiveCard",
version: "1.5",
body: [{ type: "TextBlock", text: "Hello!" }],
},
}

CLI:

Ventana de terminal
openclaw message send --channel msteams \
--target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'

Consulta la documentación de Adaptive Cards para ver el esquema de las tarjetas y ejemplos. Para detalles sobre el formato del destino, revisa Formatos de destino a continuación.

Los destinos de MSTeams usan prefijos para distinguir entre usuarios y conversaciones:

Tipo de destinoFormatoEjemplo
Usuario (por ID)user:<aad-object-id>user:40a1a0ed-4ff2-4164-a219-55518990c197
Usuario (por nombre)user:<display-name>user:John Smith (requiere Graph API)
Grupo/canalconversation:<conversation-id>conversation:19:abc123...@thread.tacv2
Grupo/canal (raw)<conversation-id>19:abc123...@thread.tacv2 (si contiene @thread)

Ejemplos de CLI:

Ventana de terminal
# Send to a user by ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# Send to a user by display name (triggers Graph API lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# Send to a group chat or channel
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# Send an Adaptive Card to a conversation
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'

Ejemplos de Agent tool:

{
action: "send",
channel: "msteams",
target: "user:John Smith",
message: "Hello!",
}
{
action: "send",
channel: "msteams",
target: "conversation:19:abc...@thread.tacv2",
card: {
type: "AdaptiveCard",
version: "1.5",
body: [{ type: "TextBlock", text: "Hello" }],
},
}

Nota: Sin el prefijo user:, los nombres se resuelven por defecto como grupos o equipos. Usa siempre user: cuando quieras contactar a personas por su nombre de pantalla.

Los mensajes proactivos solo son posibles después de que un usuario haya interactuado, ya que guardamos las referencias de la conversación en ese momento.

Te recomiendo revisar /gateway/configuration para entender cómo configurar dmPolicy y el filtrado por allowlist.

El parámetro de consulta groupId en las URLs de Teams NO es el ID del equipo que se usa para la configuración. Extrae los IDs directamente de la ruta de la URL:

URL del Team:

https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team ID (URL-decode this)

URL del Channel:

https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Channel ID (URL-decode this)

Para la configuración:

  • Team ID = segmento de la ruta después de /team/ (decodificado de la URL, por ejemplo, 19:Bk4j...@thread.tacv2)
  • Channel ID = segmento de la ruta después de /channel/ (decodificado de la URL)
  • Debes ignorar el parámetro de consulta groupId
  • Asegúrate de usar siempre el ID decodificado para evitar fallos en el Gateway

Los bots tienen un soporte limitado en los canales privados:

CaracterísticaCanales estándarCanales privados
Instalación del botSíLimitada
Mensajes en tiempo real (webhook)SíPuede no funcionar
Permisos RSCSíPuede comportarse distinto
@mencionesSíSi el bot es accesible
Historial de Graph APISíSí (con permisos)

Soluciones alternativas si los canales privados no funcionan:

  1. Usa canales estándar para las interacciones con el bot
  2. Usa DMs: los usuarios siempre pueden escribir al bot directamente
  3. Usa Graph API para el acceso al historial (requiere ChannelMessage.Read.All)
  • Las imágenes no se muestran en los canales: Faltan permisos de Graph o el consentimiento del administrador. Reinstala la app de Teams y cierra y abre Teams por completo.
  • No hay respuestas en el canal: las menciones son obligatorias por defecto; configura channels.msteams.requireMention=false o ajústalo por equipo o canal.
  • Conflicto de versiones (Teams sigue mostrando el manifest antiguo): elimina y vuelve a añadir la app, y cierra Teams del todo para refrescar.
  • 401 Unauthorized desde el webhook: Es el resultado esperado si haces pruebas manuales sin un Azure JWT; significa que el endpoint es accesible pero la autenticación falló. Usa Azure Web Chat para probarlo correctamente.
  • “Icon file cannot be empty”: El manifest hace referencia a archivos de iconos que tienen 0 bytes. Crea iconos PNG válidos (32x32 para outline.png, 192x192 para color.png).
  • “webApplicationInfo.Id already in use”: La app todavía está instalada en otro equipo o chat. Búscala y desinstálala primero, o espera de 5 a 10 minutos para que se propague el cambio.
  • “Something went wrong” al subir: Intenta subirla a través de https://admin.teams.microsoft.com, abre las DevTools del navegador (F12) → pestaña Network, y revisa el cuerpo de la respuesta para ver el error real.
  • Fallo al hacer sideload: Prueba con “Subir una aplicación al catálogo de aplicaciones de tu organización” en lugar de “Subir una aplicación personalizada”; esto suele saltarse las restricciones de sideload.
  1. Verifica que webApplicationInfo.id coincida exactamente con el App ID de tu bot
  2. Vuelve a subir la app y reinstálala en el equipo o chat
  3. Revisa si el administrador de tu organización ha bloqueado los permisos RSC
  4. Confirma que estás usando el scope correcto: ChannelMessage.Read.Group para equipos, ChatMessage.Read.Chat para chats grupales
  • Channels Overview — Todos los canales compatibles
  • Pairing — Flujo de emparejamiento y autenticación de DM
  • Groups — Comportamiento de chats grupales y gestión de menciones
  • Channel Routing — Enrutamiento de sesiones para mensajes
  • Security — Modelo de acceso y protección
OpenClaw

OpenClaw Expert

Sigues atascado?

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