Guía11 min

Cómo crear un bot de Microsoft Teams con IA (2026)

Resumen

Un agente en Teams no es un chatbot suelto: es una app con un endpoint de mensajería, Activity de Bot Framework y ack HTTP 200 en menos de 15 segundos. Esta guía cubre @mention, hilos de canal, Adaptive Cards, mensajes proactivos y el checklist de producción.

MicrosoftOpenAI
Canal de Microsoft Teams con un agente de IA que responde en el hilo tras un ack HTTP

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

Un bot de Microsoft Teams con IA vive donde el equipo ya coordina trabajo. No sustituye a Telegram ni a WhatsApp: ahí el usuario es una persona; aquí el usuario es un chat 1:1, un group chat o un canal con hilos. Si mezclas canales en un solo webhook, empieza por la arquitectura multicanal. Esta guía es un solo canal, hecho bien.

La pieza que más se rompe no es el modelo. Es el contrato de Teams: un solo messaging endpoint, Activity de tipo message, y HTTP 200 en menos de 15 segundos. Si tardas más, Teams reintenta y duplicas respuestas.

Paso 1: app, App ID y un endpoint

Registra la app en Developer Portal for Teams y conecta un bot (Microsoft App ID + secreto). Lo que necesitas para un agente de lectura/respuesta:

  1. Un messaging endpoint HTTPS. Teams envía un JSON a esa URL y solo admite un endpoint de mensajería, según Conversations with an agent.
  2. Credenciales de bot (App ID y password) fuera del repo. El Bot Framework las usa para firmar el canal; cualquiera con el secreto publica como tu agente.
  3. Scopes en el manifest: personal para 1:1, groupchat y teams si va a un canal. Sin el scope, la instalación ni aparece.
  4. Instala la app en un equipo de prueba. En canal, el agente no ve mensajes hasta que lo @mencionan, salvo que pidas RSC para recibir todo.

Guarda MICROSOFT_APP_ID y MICROSOFT_APP_PASSWORD como secretos de entorno.

Paso 2: Activity, 15 segundos y cola

Cada mensaje es un Activity (type: message, channelId: msteams). El Bot Framework es explícito: el bot tiene 15 segundos para acusar con HTTP 200 en la mayoría de canales. Si no, llega un 504 GatewayTimeout. La doc de activity handlers añade el efecto práctico: si el turno tarda más de 15 s, Teams reenvía y ves requests duplicados.

El patrón correcto es ack inmediato y trabajo en cola:

// Teams SDK: el handler debe devolver control antes de 15 s
app.on("message", async ({ activity, send }) => {
  const job = {
    conversationId: activity.conversation.id,
    serviceUrl: activity.serviceUrl,
    tenantId: activity.conversation.tenantId,
    text: activity.text,
    fromId: activity.from.id,
  };
  await enqueue(job);
  await send("Lo miro y te respondo en este hilo.");
});

Si el LLM cabe en 15 segundos en tu p95, puedes responder inline. El día que una tool tarde 20 s, el mismo código duplica por retry. Diseña el ack primero. Dedup por activity.id.

Paso 3: 1:1 vs canal vs group chat

Los scopes no son cosmética:

ScopeQué llegaCómo responder
1:1 (personal)Cada mensaje del usuarioMulti-turno clásico
Group chatSolo @mention, salvo RSCCorto; no monopolices
Canal (teams)Solo @mention; hilos; hasta ~2000 personasConciso; Adaptive Card o 1:1 para recolectar datos

En canal, channel and group conversations lo deja claro: el agente no recibe el resto del hilo, ni cuando alguien responde sin @mention, ni cuando mencionan al equipo. Filtra app.OnMessage a menciones si no pediste RSC.

Los canales van en hilos. El contexto ya trae el thread id: send() sigue el hilo; reply() cita el inbound. Indexa memoria por ${tenantId}:${conversation.id}.

En canales privados el agente no puede publicar mensajes ni Adaptive Cards. No lo descubras en producción.

Flujo: @mention en Teams, HTTP 200 en menos de 15 s, cola, agente con tools y respuesta en el hilo

Paso 4: el agente, no el eco

Entre el Activity y el send() del worker vive el agente: system prompt, tools y memoria por conversación.

async function responder(job: Job) {
  const respuesta = await agente.responder({
    conversationId: job.conversationId,
    mensaje: job.text,
    tools: [buscarTicket, crearIssue],
  });

  await connector.postActivity(job.serviceUrl, job.conversationId, {
    type: "message",
    text: respuesta.slice(0, 8000),
    textFormat: "markdown",
  });
}

Tres decisiones ya tomadas: respuesta en el mismo hilo, tools con schema estricto —la mecánica está en function calling y en tools confiables— y un tope de tamaño. Teams limita el mensaje a ~100 KB UTF-16 (menciones y reacciones incluidas); Microsoft recomienda quedarse en 80 KB. Si te pasas, llega 413 MessageSizeTooBig. No mandes el dump del LLM.

Adaptive Cards van del agente al usuario, no al revés. Úsalas para aprobar un ticket o elegir un issue, no el día que todavía no tienes ack estable. Texto markdown basta para la v1.

Guarda serviceUrl + conversationId + tenantId de cada instalación. Sin eso no hay mensaje proactivo: notificaciones y cron viven fuera del handler. No puedes crear un group chat ni un canal nuevo con proactivo; sí un 1:1 o un hilo en un canal donde la app ya está instalada.

Costos y ruido

Teams no cobra el Activity inbound. El costo es el LLM más el hosting. El riesgo de factura no es el precio por @mention: es pedir RSC, escuchar todo el canal y reenviar 40 mensajes de contexto. Ventana de 10–20 turnos del hilo, resumen rodante, hechos durables (ticket, repo, owner) fuera del prompt.

Pon dos topes el día uno: máximo de inferencias por conversación por minuto, y máximo de tokens de entrada.

Checklist de producción

Checklist: App ID, endpoint único, ack < 15 s, cola, @mention, hilos, Adaptive Cards y dedup por activity.id

  1. App ID + password en entorno, nunca en el repo.
  2. Un solo messaging endpoint HTTPS.
  3. HTTP 200 en menos de 15 s; LLM y tools después del ack.
  4. Cola + worker; send / Connector desde el worker.
  5. En canal y group chat: solo @mention, salvo RSC consciente.
  6. Respuestas en el hilo (send / reply), no un mensaje suelto al canal.
  7. Dedup por activity.id; ignora actividades de tu propio bot.
  8. Memoria por conversation.id, no por equipo entero.
  9. Mensajes bajo 80 KB; Adaptive Cards para acciones, no para ensayos.
  10. Guarda tenantId + serviceUrl + conversationId si vas a proactivo.

Preguntas frecuentes

¿Necesito Azure Bot Service? El protocolo es Bot Framework. Puedes hostear el endpoint en Vercel, un VPS o Azure; Teams llama a tu HTTPS. El registro de App ID sí es de Microsoft.

¿Por qué no un Incoming Webhook? Un webhook entra; no lee @mentions ni hilos. Para un agente que responde, Activity + Connector.

¿Puedo usar el mismo código que Telegram? El núcleo del agente sí (prompt, tools, memoria). El adaptador no: Teams exige 15 s, Activity y scopes. Mezclar canales en un solo handler es el fallo que cubre la guía multicanal.

¿Copilot Studio o bot propio? Copilot Studio publica un agente gestionado a Teams. Esta guía es el bot que hosteas, con tools y cola. No mezcles los dos contratos el día uno.

El siguiente paso

Cuando el bot aguante un canal real, añade cola, retries e idempotencia como en la arquitectura de producción. El curso gratuito de instalación recorre el primer agente de punta a punta; el resto de piezas está en el hub de construcción.