Microsoft Teams (plugin)
“Abandonen toda esperanza quienes entren aquí.”Actualizado: 2026-01-21 Estado: se admiten texto + archivos adjuntos en mensajes directos; el envío de archivos en canales/grupos requiere
sharePointSiteId + permisos de Graph (consulte Envío de archivos en chats grupales). Las encuestas se envían mediante Adaptive Cards.
Plugin requerido
Microsoft Teams se distribuye como un plugin y no viene incluido con la instalación principal. Cambio disruptivo (2026.1.15): MS Teams salió del núcleo. Si lo usa, debe instalar el plugin. Explicación: mantiene las instalaciones del núcleo más ligeras y permite que las dependencias de MS Teams se actualicen de forma independiente. Instalar vía CLI (registro npm):Configuración rápida (principiante)
- Instale el plugin de Microsoft Teams.
- Cree un Azure Bot (App ID + secreto del cliente + ID de tenant).
- Configure OpenClaw con esas credenciales.
- Exponga
/api/messages(puerto 3978 por defecto) mediante una URL pública o un túnel. - Instale el paquete de la app de Teams e inicie el gateway.
channels.msteams.groupPolicy: "allowlist"). Para permitir respuestas en grupos, configure channels.msteams.groupAllowFrom (o use groupPolicy: "open" para permitir a cualquier miembro, con mención obligatoria).
Objetivos
- Comunicarse con OpenClaw mediante mensajes directos de Teams, chats grupales o canales.
- Mantener un enrutamiento determinista: las respuestas siempre vuelven al canal por el que llegaron.
- Usar por defecto un comportamiento seguro del canal (menciones requeridas salvo que se configure lo contrario).
Escrituras de configuración
De forma predeterminada, Microsoft Teams puede escribir actualizaciones de configuración activadas por/config set|unset (requiere commands.config: true).
Deshabilitar con:
Control de acceso (mensajes directos + grupos)
Acceso a mensajes directos- Predeterminado:
channels.msteams.dmPolicy = "pairing". Los remitentes desconocidos se ignoran hasta ser aprobados. channels.msteams.allowFromacepta IDs de objetos AAD, UPNs o nombres para mostrar. El asistente resuelve nombres a IDs mediante Microsoft Graph cuando las credenciales lo permiten.
- Predeterminado:
channels.msteams.groupPolicy = "allowlist"(bloqueado a menos que agreguegroupAllowFrom). Usechannels.defaults.groupPolicypara anular el valor predeterminado cuando no esté configurado. channels.msteams.groupAllowFromcontrola qué remitentes pueden activar en chats/canales grupales (usa como respaldochannels.msteams.allowFrom).- Configure
groupPolicy: "open"para permitir a cualquier miembro (aún con mención obligatoria por defecto). - Para permitir ningún canal, configure
channels.msteams.groupPolicy: "disabled".
- Limite respuestas por grupo/canal listando equipos y canales bajo
channels.msteams.teams. - Las claves pueden ser IDs o nombres de equipos; las claves de canal pueden ser IDs de conversación o nombres.
- Cuando
groupPolicy="allowlist"y existe una lista de permitidos de equipos, solo se aceptan los equipos/canales listados (con mención obligatoria). - El asistente de configuración acepta entradas
Team/Channely las almacena por usted. - Al iniciar, OpenClaw resuelve nombres de equipos/canales y listas de permitidos de usuarios a IDs (cuando los permisos de Graph lo permiten) y registra el mapeo; las entradas no resueltas se conservan tal como se escribieron.
Cómo funciona
- Instale el plugin de Microsoft Teams.
- Cree un Azure Bot (App ID + secreto + ID de tenant).
- Cree un paquete de app de Teams que haga referencia al bot e incluya los permisos RSC a continuación.
- Cargue/instale la app de Teams en un equipo (o en ámbito personal para mensajes directos).
- Configure
msteamsen~/.openclaw/openclaw.json(o variables de entorno) e inicie el gateway. - El gateway escucha tráfico de webhook de Bot Framework en
/api/messagespor defecto.
Configuración del Azure Bot (Requisitos previos)
Antes de configurar OpenClaw, debe crear un recurso de Azure Bot.Paso 1: Crear Azure Bot
- Vaya a Crear Azure Bot
-
Complete la pestaña Basics:
Campo Valor Bot handle Nombre de su bot, p. ej., openclaw-msteams(debe ser único)Subscription Seleccione su suscripción de Azure Resource group Cree uno nuevo o use uno existente Pricing tier Free para dev/pruebas Type of App Single Tenant (recomendado; ver nota abajo) Creation type Create new Microsoft App ID
Aviso de deprecación: La creación de nuevos bots multi-tenant se deprecó después del 2025-07-31. Use Single Tenant para nuevos bots.
- Haga clic en Review + create → Create (espere ~1-2 minutos)
Paso 2: Obtener credenciales
- Vaya a su recurso de Azure Bot → Configuration
- Copie Microsoft App ID → este es su
appId - Haga clic en Manage Password → vaya al App Registration
- En Certificates & secrets → New client secret → copie el Value → este es su
appPassword - Vaya a Overview → copie Directory (tenant) ID → este es su
tenantId
Paso 3: Configurar el endpoint de mensajería
- En Azure Bot → Configuration
- Establezca Messaging endpoint en la URL de su webhook:
- Producción:
https://your-domain.com/api/messages - Desarrollo local: use un túnel (consulte Desarrollo local abajo)
- Producción:
Paso 4: Habilitar el canal de Teams
- En Azure Bot → Channels
- Haga clic en Microsoft Teams → Configure → Save
- Acepte los Términos del servicio
Desarrollo local (túneles)
Teams no puede alcanzarlocalhost. Use un túnel para desarrollo local:
Opción A: ngrok
Portal para desarrolladores de Teams (alternativa)
En lugar de crear manualmente un ZIP de manifiesto, puede usar el Portal para desarrolladores de Teams:- Haga clic en + New app
- Complete la información básica (nombre, descripción, info del desarrollador)
- Vaya a App features → Bot
- Seleccione Enter a bot ID manually y pegue el App ID de su Azure Bot
- Marque los ámbitos: Personal, Team, Group Chat
- Haga clic en Distribute → Download app package
- En Teams: Apps → Manage your apps → Upload a custom app → seleccione el ZIP
Prueba del bot
Opción A: Azure Web Chat (verifique primero el webhook)- En Azure Portal → su recurso de Azure Bot → Test in Web Chat
- Envíe un mensaje: debería ver una respuesta
- Esto confirma que su endpoint de webhook funciona antes de configurar Teams
- Instale la app de Teams (sideload o catálogo de la organización)
- Busque el bot en Teams y envíe un mensaje directo
- Revise los logs del gateway para actividad entrante
Configuración (mínima solo texto)
-
Instale el plugin de Microsoft Teams
- Desde npm:
openclaw plugins install @openclaw/msteams - Desde un checkout local:
openclaw plugins install ./extensions/msteams
- Desde npm:
-
Registro del bot
- Cree un Azure Bot (ver arriba) y anote:
- App ID
- Secreto del cliente (contraseña de la app)
- Tenant ID (single-tenant)
- Cree un Azure Bot (ver arriba) y anote:
-
Manifiesto de la app de Teams
- Incluya una entrada
botconbotId = <App ID>. - Ámbitos:
personal,team,groupChat. supportsFiles: true(requerido para manejo de archivos en ámbito personal).- Agregue permisos RSC (abajo).
- Cree íconos:
outline.png(32x32) ycolor.png(192x192). - Comprima los tres archivos juntos:
manifest.json,outline.png,color.png.
- Incluya una entrada
-
Configure OpenClaw
También puede usar variables de entorno en lugar de claves de configuración:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Endpoint del bot
- Establezca el Messaging Endpoint del Azure Bot en:
https://<host>:3978/api/messages(o su ruta/puerto elegido).
- Establezca el Messaging Endpoint del Azure Bot en:
-
Ejecute el gateway
- El canal de Teams se inicia automáticamente cuando el plugin está instalado y existe la configuración
msteamscon credenciales.
- El canal de Teams se inicia automáticamente cuando el plugin está instalado y existe la configuración
Contexto de historial
channels.msteams.historyLimitcontrola cuántos mensajes recientes de canal/grupo se envuelven en el prompt.- Usa como respaldo
messages.groupChat.historyLimit. Configure0para deshabilitar (predeterminado 50). - El historial de mensajes directos puede limitarse con
channels.msteams.dmHistoryLimit(turnos por usuario). Anulaciones por usuario:channels.msteams.dms["<user_id>"].historyLimit.
Permisos RSC actuales de Teams (manifiesto)
Estos son los resourceSpecific permissions existentes en nuestro manifiesto de la app de Teams. Solo aplican dentro del equipo/chat donde está instalada la app. Para canales (ámbito de equipo):ChannelMessage.Read.Group(Application) - recibir todos los mensajes del canal sin @mentionChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
ChatMessage.Read.Chat(Application) - recibir todos los mensajes del chat grupal sin @mention
Ejemplo de manifiesto de Teams (redactado)
Ejemplo mínimo y válido con los campos requeridos. Reemplace IDs y URLs.Advertencias del manifiesto (campos imprescindibles)
bots[].botIddebe coincidir con el App ID del Azure Bot.webApplicationInfo.iddebe coincidir con el App ID del Azure Bot.bots[].scopesdebe incluir las superficies que planea usar (personal,team,groupChat).bots[].supportsFiles: truees requerido para manejo de archivos en ámbito personal.authorization.permissions.resourceSpecificdebe incluir lectura/envío de canales si desea tráfico de canales.
Actualizar una app existente
Para actualizar una app de Teams ya instalada (p. ej., para agregar permisos RSC):- Actualice su
manifest.jsoncon la nueva configuración - Incremente el campo
version(p. ej.,1.0.0→1.1.0) - Vuelva a comprimir el manifiesto con los íconos (
manifest.json,outline.png,color.png) - Cargue el nuevo zip:
- Opción A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → busque su app → Upload new version
- Opción B (Sideload): En Teams → Apps → Manage your apps → Upload a custom app
- Para canales de equipo: Reinstale la app en cada equipo para que los nuevos permisos surtan efecto
- Cierre completamente y vuelva a abrir Teams (no solo cerrar la ventana) para limpiar la caché de metadatos de la app
Capacidades: solo RSC vs Graph
Con solo Teams RSC (app instalada, sin permisos de Graph API)
Funciona:- Leer contenido de texto de mensajes de canal.
- Enviar contenido de texto de mensajes de canal.
- Recibir archivos adjuntos personales (DM).
- Contenido de imágenes o archivos en canales/grupos (la carga solo incluye un stub HTML).
- Descargar adjuntos almacenados en SharePoint/OneDrive.
- Leer historial de mensajes (más allá del evento de webhook en vivo).
Con Teams RSC + permisos de aplicación de Microsoft Graph
Agrega:- Descarga de contenidos alojados (imágenes pegadas en mensajes).
- Descarga de archivos adjuntos almacenados en SharePoint/OneDrive.
- Lectura del historial de mensajes de canal/chat vía Graph.
RSC vs Graph API
| Capacidad | Permisos RSC | Graph API |
|---|---|---|
| Mensajes en tiempo real | Sí (vía webhook) | No (solo sondeo) |
| Mensajes históricos | No | Sí (se puede consultar historial) |
| Complejidad de configuración | Solo manifiesto de la app | Requiere consentimiento de admin + flujo de tokens |
| Funciona sin conexión | No (debe estar en ejecución) | Sí (consultar en cualquier momento) |
ChannelMessage.Read.All (requiere consentimiento de administrador).
Medios + historial habilitados con Graph (requerido para canales)
Si necesita imágenes/archivos en canales o desea obtener historial de mensajes, debe habilitar permisos de Microsoft Graph y otorgar consentimiento de administrador.- En Entra ID (Azure AD) App Registration, agregue permisos de Application de Microsoft Graph:
ChannelMessage.Read.All(adjuntos de canal + historial)Chat.Read.AlloChatMessage.Read.All(chats grupales)
- Otorgue consentimiento de administrador para el tenant.
- Aumente la versión del manifiesto de la app de Teams, vuelva a cargarla y reinstale la app en Teams.
- Cierre completamente y vuelva a abrir Teams para limpiar la caché de metadatos de la app.
User.Read.All (Application) y concede el consentimiento de administrador.
Limitaciones conocidas
Tiempos de espera del webhook
Teams entrega mensajes mediante webhook HTTP. Si el procesamiento tarda demasiado (p. ej., respuestas lentas del LLM), puede ver:- Tiempos de espera del gateway
- Reintentos de Teams (causando duplicados)
- Respuestas perdidas
Formato
El markdown de Teams es más limitado que Slack o Discord:- El formato básico funciona: negrita, cursiva,
code, enlaces - El markdown complejo (tablas, listas anidadas) puede no renderizarse correctamente
- Adaptive Cards son compatibles para encuestas y envíos arbitrarios de tarjetas (ver abajo)
Configuración
Ajustes clave (consulte/gateway/configuration para patrones de canales compartidos):
channels.msteams.enabled: habilitar/deshabilitar el canal.channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: credenciales del bot.channels.msteams.webhook.port(predeterminado3978)channels.msteams.webhook.path(predeterminado/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(predeterminado: emparejamiento)channels.msteams.allowFrom: lista de permitidos para mensajes directos (IDs de objeto AAD, UPNs o nombres para mostrar). El asistente resuelve nombres a IDs durante la configuración cuando hay acceso a Graph.channels.msteams.textChunkLimit: tamaño de fragmento de texto saliente.channels.msteams.chunkMode:length(predeterminado) onewlinepara dividir en líneas en blanco (límites de párrafo) antes del troceado por longitud.channels.msteams.mediaAllowHosts: lista de permitidos de hosts de adjuntos entrantes (predeterminado: dominios de Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: lista de permitidos para adjuntar encabezados Authorization en reintentos de medios (predeterminado: hosts de Graph + Bot Framework).channels.msteams.requireMention: requerir @mention en canales/grupos (predeterminado true).channels.msteams.replyStyle:thread | top-level(consulte Estilo de respuesta).channels.msteams.teams.<teamId>.replyStyle: anulación por equipo.channels.msteams.teams.<teamId>.requireMention: anulación por equipo.channels.msteams.teams.<teamId>.tools: anulaciones predeterminadas de política de herramientas por equipo (allow/deny/alsoAllow) usadas cuando falta una anulación de canal.channels.msteams.teams.<teamId>.toolsBySender: anulaciones predeterminadas de política de herramientas por equipo y remitente ("*"comodín compatible).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 canal y remitente ("*"comodín compatible).channels.msteams.sharePointSiteId: ID del sitio de SharePoint para cargas de archivos en chats/canales grupales (consulte Envío de archivos en chats grupales).
Enrutamiento y sesiones
- Las claves de sesión siguen el formato estándar del agente (consulte /concepts/session):
- Los mensajes directos comparten la sesión principal (
agent:<agentId>:<mainKey>). - Los mensajes de canal/grupo usan el id de conversación:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Los mensajes directos comparten la sesión principal (
Estilo de respuesta: Hilos vs Publicaciones
Teams introdujo recientemente dos estilos de UI de canal sobre el mismo modelo de datos subyacente:| Estilo | Descripción | replyStyle recomendado |
|---|---|---|
| Publicaciones (clásico) | Los mensajes aparecen como tarjetas con respuestas en hilo debajo | thread (predeterminado) |
| Hilos (tipo Slack) | Los mensajes fluyen linealmente, más como Slack | top-level |
replyStyle incorrecto:
threaden un canal con estilo Hilos → las respuestas aparecen anidadas de forma incómodatop-levelen un canal con estilo Publicaciones → las respuestas aparecen como publicaciones de nivel superior separadas en lugar de en hilo
replyStyle por canal según cómo esté configurado el canal:
Adjuntos e imágenes
Limitaciones actuales:- Mensajes directos: Imágenes y archivos adjuntos funcionan mediante las APIs de archivos del bot de Teams.
- Canales/grupos: Los adjuntos viven en el almacenamiento M365 (SharePoint/OneDrive). La carga del webhook solo incluye un stub HTML, no los bytes reales del archivo. Se requieren permisos de Graph API para descargar adjuntos de canales.
channels.msteams.mediaAllowHosts (use ["*"] para permitir cualquier host).
Los encabezados Authorization solo se adjuntan para hosts en channels.msteams.mediaAuthAllowHosts (predeterminado: hosts de Graph + Bot Framework). Mantenga esta lista estricta (evite sufijos multi-tenant).
Envío de archivos en chats grupales
Los bots pueden enviar archivos en mensajes directos usando el flujo FileConsentCard (integrado). Sin embargo, enviar archivos en chats/canales grupales requiere configuración adicional:| Contexto | Cómo se envían los archivos | Configuración necesaria |
|---|---|---|
| Mensajes directos | FileConsentCard → el usuario acepta → el bot carga | Funciona fuera de la caja |
| Chats/canales grupales | Carga a SharePoint → enlace compartido | Requiere sharePointSiteId + permisos de Graph |
| Imágenes (cualquier contexto) | Inline codificado en Base64 | Funciona fuera de la caja |
Por qué los chats grupales necesitan SharePoint
Los bots no tienen una unidad personal de OneDrive (el endpoint de Graph/me/drive no funciona para identidades de aplicación). Para enviar archivos en chats/canales grupales, el bot carga a un sitio de SharePoint y crea un enlace de uso compartido.
Configuración
-
Agregue permisos de Graph API en Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) - cargar archivos a SharePointChat.Read.All(Application) - opcional, habilita enlaces de uso compartido por usuario
- Otorgue consentimiento de administrador para el tenant.
-
Obtenga el ID de su sitio de SharePoint:
-
Configure OpenClaw:
Comportamiento de uso compartido
| Permiso | Comportamiento de uso compartido |
|---|---|
Sites.ReadWrite.All solamente | Enlace de uso compartido a nivel de organización (cualquiera en la org puede acceder) |
Sites.ReadWrite.All + Chat.Read.All | Enlace de uso compartido por usuario (solo miembros del chat pueden acceder) |
Chat.Read.All, el bot recurre al uso compartido a nivel de organización.
Comportamiento de respaldo
| Escenario | Resultado |
|---|---|
Chat grupal + archivo + sharePointSiteId configurado | Carga a SharePoint, envía enlace compartido |
Chat grupal + archivo + sin sharePointSiteId | Intenta carga a OneDrive (puede fallar), envía solo texto |
| Chat personal + archivo | Flujo FileConsentCard (funciona sin SharePoint) |
| Cualquier contexto + imagen | Inline codificado en Base64 (funciona sin SharePoint) |
Ubicación de almacenamiento de archivos
Los archivos cargados se almacenan en una carpeta/OpenClawShared/ en la biblioteca de documentos predeterminada del sitio de SharePoint configurado.
Encuestas (Adaptive Cards)
OpenClaw envía encuestas de Teams como Adaptive Cards (no existe una API nativa de encuestas de Teams).- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - Los votos se registran por el gateway en
~/.openclaw/msteams-polls.json. - El gateway debe permanecer en línea para registrar votos.
- Las encuestas aún no publican automáticamente resúmenes de resultados (inspeccione el archivo de almacenamiento si es necesario).
Adaptive Cards (arbitrarias)
Envíe cualquier JSON de Adaptive Card a usuarios o conversaciones de Teams usando la herramienta o CLImessage.
El parámetro card acepta un objeto JSON de Adaptive Card. Cuando se proporciona card, el texto del mensaje es opcional.
Herramienta del agente:
Formatos de destino
Los destinos de MSTeams usan prefijos para distinguir entre usuarios y conversaciones:| Tipo de destino | Formato | Ejemplo |
|---|---|---|
| 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/canal | conversation:<conversation-id> | conversation:19:[email protected] |
| Grupo/canal (raw) | <conversation-id> | 19:[email protected] (si contiene @thread) |
user:, los nombres se resuelven por defecto a grupos/equipos. Use siempre user: cuando apunte a personas por nombre para mostrar.
Mensajería proactiva
- Los mensajes proactivos solo son posibles después de que un usuario haya interactuado, porque almacenamos referencias de conversación en ese punto.
- Consulte
/gateway/configurationparadmPolicyy el control por lista de permitidos.
IDs de equipo y canal (error común)
El parámetro de consultagroupId en las URLs de Teams NO es el ID de equipo usado para la configuración. Extraiga los IDs desde la ruta de la URL:
URL del equipo:
- ID de equipo = segmento de ruta después de
/team/(decodificado de URL, p. ej.,19:[email protected]) - ID de canal = segmento de ruta después de
/channel/(decodificado de URL) - Ignore el parámetro de consulta
groupId
Canales privados
Los bots tienen soporte limitado en canales privados:| Función | Canales estándar | Canales privados |
|---|---|---|
| Instalación del bot | Sí | Limitado |
| Mensajes en tiempo real (webhook) | Sí | Puede no funcionar |
| Permisos RSC | Sí | Pueden comportarse distinto |
| @mentions | Sí | Si el bot es accesible |
| Historial por Graph API | Sí | Sí (con permisos) |
- Use canales estándar para interacciones con el bot
- Use mensajes directos: los usuarios siempre pueden escribirle al bot directamente
- Use Graph API para acceso histórico (requiere
ChannelMessage.Read.All)
Problemas comunes
Problemas comunes
- Las imágenes no se muestran en canales: faltan permisos de Graph o consentimiento de administrador. Reinstale la app de Teams y cierre/abra completamente Teams.
- Sin respuestas en canal: las menciones son obligatorias por defecto; configure
channels.msteams.requireMention=falseo ajuste por equipo/canal. - Desajuste de versión (Teams aún muestra el manifiesto antiguo): quite y vuelva a agregar la app y cierre completamente Teams para refrescar.
- 401 Unauthorized desde el webhook: esperado al probar manualmente sin JWT de Azure; indica que el endpoint es alcanzable pero falló la autenticación. Use Azure Web Chat para probar correctamente.
Errores al cargar el manifiesto
- “Icon file cannot be empty”: El manifiesto referencia íconos de 0 bytes. Cree íconos PNG válidos (32x32 para
outline.png, 192x192 paracolor.png). - “webApplicationInfo.Id already in use”: La app aún está instalada en otro equipo/chat. Encuéntrela y desinstálela primero, o espere 5-10 minutos para la propagación.
- “Something went wrong” al cargar: Cargue mediante https://admin.teams.microsoft.com en su lugar, abra las DevTools del navegador (F12) → pestaña Network, y revise el cuerpo de la respuesta para el error real.
- Fallo de sideload: Intente “Upload an app to your org’s app catalog” en lugar de “Upload a custom app”; a menudo evita restricciones de sideload.
Permisos RSC no funcionan
- Verifique que
webApplicationInfo.idcoincida exactamente con el App ID de su bot - Vuelva a cargar la app y reinstálela en el equipo/chat
- Verifique si el admin de su organización bloqueó los permisos RSC
- Confirme que usa el ámbito correcto:
ChannelMessage.Read.Grouppara equipos,ChatMessage.Read.Chatpara chats grupales
Referencias
- Crear Azure Bot - Guía de configuración de Azure Bot
- Portal para desarrolladores de Teams - crear/administrar apps de Teams
- Esquema del manifiesto de apps de Teams
- Recibir mensajes de canal con RSC
- Referencia de permisos RSC
- Manejo de archivos del bot de Teams (canal/grupo requiere Graph)
- Mensajería proactiva