Guía9 min

Telegram Mini App con IA: cómo crear el agente dentro del chat

Resumen

Una Telegram Mini App es una web app que corre dentro de Telegram: el bot lanza la interfaz, la app recibe el usuario por initData y el backend valida la firma antes de llamar al LLM. Esta guía práctica cubre cómo configurar la Mini App con BotFather, los siete mecanismos de lanzamiento, el patrón bot + backend + modelo con Telegram.WebApp.initData, los límites de la WebView, y un checklist para poner el agente en producción sin romper la validación.

Telegram
Interfaz de una Telegram Mini App con un agente de IA dentro del chat de Telegram

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 Telegram con IA te responde con texto. Una Telegram Mini App te da más: una interfaz completa —botones, formularios, gráficas, pagos— que corre dentro de Telegram y le pasa datos reales al agente. En la práctica es un embudo más corto: el usuario no sale de la app de mensajería para usar tu producto.

En esta guía montas el patrón completo: bot + Mini App + backend + LLM. No es difícil, pero hay una pieza que todos se saltan la primera vez y debe ser tu primera línea de código: la validación de initData. Empieza por el tutorial de bots de Telegram con IA si lo que quieres es un bot de chat con tools; aquí el entregable es una web app incrustada.

Qué es una Mini App y por qué usarla con IA

Una Mini App es una página web normal (HTML, CSS, JavaScript, cualquier framework) que Telegram abre en una WebView dentro del chat. El SDK inyecta window.Telegram.WebApp con todo lo que necesitas: identidad del usuario, tema visual, haptic feedback, botón flotante y la posibilidad de cerrar la app devolviendo datos al bot.

CriterioBot de textoTelegram Mini App
InterfazMarkdown, botones inlineWebView: HTML/CSS/JS completo
Entrada del usuarioMensajes, callbacksFormularios, gestos, haptics, voz
Contexto del usuariofrom en cada updateWebAppInitData firmada
Modelo mentalConversaciónProducto/agente con UX
CurvaHorasDías (frontend + backend)

La ventaja frente a un bot de texto es la densidad de datos: el agente no adivina lo que el usuario quiere entre mensajes sueltos, lo recibe en un formulario estructurado. La ventaja frente a una web app suelta es la distribución: el punto de entrada vive en Telegram, sin instalar nada.

1. Crear la Mini App con BotFather

Todo arranca por el bot. Con @BotFather:

  1. /newbot y eliges nombre y username.
  2. /mybots → tu bot → Bot Settings → Configure Mini App.
  3. Escribes la URL HTTPS de tu app. En desarrollo usa un túnel (ngrok, Cloudflare Tunnel) o https://localhost con certificado válido.
  4. BotFather te devuelve el URL del bot (t.me/tu_bot/app) y el deep link con parámetros.

Regla de oro: Telegram solo abre Mini Apps desde HTTPS. Las excepciones son localhost y 127.0.0.1 para desarrollo; un HTTP directo simplemente no abre.

Para que la app aparezca en el bot puedes configurar el menú como botón de lanzamiento con la Bot API:

Flujo de una Telegram Mini App: usuario, Telegram, backend y LLM

curl -s "https://api.telegram.org/bot<TOKEN>/setChatMenuButton" \
  -H "Content-Type: application/json" \
  -d '{"menu_button":{"type":"web_app","text":"Abrir app","web_app":{"url":"https://tu-app.com"}}}'

Tienes siete vías de lanzamiento: botón del menú, botones del teclado, botones inline, enlace directo (t.me/tu_bot/app), botón principal del perfil del bot, inline mode y attachment menu. El patrón de producto más robusto casi siempre es menú + inline buttons: el menú da descubrimiento y el inline da contexto, porque el usuario lanza la app desde el hilo de la conversación.

2. Inicializar la app y pedir los datos del usuario

Cargas el SDK oficial o lo inyectas con un script, y en index.html el arranque mínimo es:

<script src="https://telegram.org/js/telegram-web-app.js"></script>
<script>
  const tg = window.Telegram.WebApp;
  tg.ready();   // avisa a Telegram que la app cargó
  tg.expand();  // aprovecha todo el alto disponible
  document.getElementById("user").textContent =
    tg.initDataUnsafe?.user?.first_name ?? "invitado";
</script>

La app arranca colapsada: llama a expand() para rellenar la pantalla. La regla de oro de seguridad: no confíes en initDataUnsafe. Es para leer rápido en el navegador; la fuente de verdad es tg.initData enviado al servidor y validado allí.

const response = await fetch("https://api.tu-app.com/agente", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ initData: tg.initData, prompt: form.value }),
});

3. Validar initData en el backend (obligatorio)

Todo lo que llega del cliente puede ser falso: otro programa puede fabricar un initData con query_id, user y hash inventados. Telegram firma los datos con el token del bot y tú debes verificar la firma antes de usar el usuario para cualquier cosa.

Firma en Node.js:

import { createHmac } from "node:crypto";

function validateInitData(initData, botToken) {
  const params = new URLSearchParams(initData);
  const hash = params.get("hash");
  params.delete("hash");
  const dataCheckString = [...params.entries()]
    .map(([k, v]) => `${k}=${v}`)
    .sort((a, b) => a.localeCompare(b))
    .join("\n");
  const secretKey = createHmac("sha256", "WebAppData")
    .update(botToken).digest();
  const expectedHash = createHmac("sha256", secretKey)
    .update(dataCheckString).digest("hex");
  return expectedHash === hash;
}

El procedimiento oficial es: los campos se ordenan alfabéticamente como clave=valor separados por \n (el campo hash se excluye), la clave secreta es HMAC_SHA256(token, "WebAppData") y el hash recibido debe coincidir con HMAC_SHA256(data_check_string, secret_key).

Tres detalles que se suelen olvidar:

  • auth_date no es opcional: rechaza firmas antiguas (p. ej. más de 24 h) para evitar replay attacks.
  • El hash se compara en hexadecimal, sin base64.
  • Si un tercero debe validar los datos sin conocer tu token, Telegram permite verificar con firma Ed25519 y una clave pública oficial.

Validación de initData con firma HMAC del lado del servidor

Una vez validado, query_id identifica la sesión y user trae id, nombre y foto. Ese user.id es tu clave de tenant: perfil, historial, límites de uso.

4. Conectar el LLM

Dentro de la app, el patrón es el mismo que en cualquier agente: el backend recibe el prompt + initData validado, llama al modelo (OpenAI, Anthropic, Gemini o un modelo local), y responde. La única diferencia relevante es el estado: en vez de mantener memoria en el chat, puedes guardar el contexto por user.id en una base de datos y usar la Mini App como formulario de entrada.

// POST /agente — ya validaste initData y tienes user.id
const messages = [
  { role: "system", content: "Eres un asistente financiero en español." },
  ...(await getHistory(userId)),
  { role: "user", content: prompt },
];
const completion = await model.chat.completions.create({
  model: "gpt-4.1-mini",
  messages,
});
const reply = completion.choices[0].message.content;
await saveHistory(userId, prompt, reply);
return res.json({ reply, buttons: extractActions(reply) });

Puedes devolver texto plano, tarjetas con acciones (MainButton para confirmar una compra, HapticFeedback para validar gestos) o iniciar un pago con Telegram Stars — el equivalente a comprar dentro de la Mini App sin fricción. Para comparar costos entre canales de mensajería, el análisis de agentes en WhatsApp vs Telegram tiene los números de migas.

5. Límites y trampas de la WebView

La Mini App no es un navegador de escritorio. Planifica desde el día uno con esto en mente:

LímiteRealidad
HTTPSObligatorio fuera de localhost
AlmacenamientolocalStorage por origen; DeviceStorage/SecureStorage desde Bot API 9.0
Enlaces externosNavegación fuera de la app se pide con openLink
TecladoLos campos de texto compiten con el teclado del dispositivo; usa MainButton para el envío

En la práctica, los problemas más comunes al operar una Mini App con IA son tres: validar mal (o no validar) initData, asumir que initDataUnsafe es seguro, y no manejar el cierre de la app — si el usuario cierra la WebView a mitad de una llamada al LLM, el backend debe poder terminar el trabajo o responder cuando el bot escriba el resultado.

Checklist de producción

  • Mini App configurada en BotFather con URL HTTPS válida
  • Menú del bot apuntando a web_app + inline button de contexto
  • tg.ready() y tg.expand() al arrancar
  • initData enviado al backend en cada llamada autenticada
  • Validación HMAC-SHA256 server-side (nunca en el cliente)
  • auth_date comprobado contra ventana de validez
  • Estado por user.id (no por query_id, que es por sesión)
  • Manejo del cierre de la WebView: el trabajo tardío no depende del cliente
  • Errores en español y visibles dentro de la app
  • Haptics y tema (colorScheme, themeParams) respetados

FAQ

¿Puedo usar una Mini App para un agente de ventas? Sí, de los mejores casos: catálogo en la Mini App, el LLM asesora, MainButton confirma y el pago con Stars cierra el ciclo sin salir de Telegram.

¿Cuánto cuesta? La Mini App no tiene costo de plataforma; pagas hosting y uso del modelo. Comparado con WhatsApp, sin costo por mensaje de entrada.

¿Necesito un framework especial? No. React, Vue, Svelte o HTML plano funcionan; solo usa el SDK y respeta las variables CSS --tg-* del tema.

¿Qué pasa en Telegram Desktop? Se abre en una WebView del cliente; prueba en móvil y desktop porque el viewport y el teclado cambian la UX.