tva
← Insights

Cómo escalar un asistente de IA en Telegram: de uso personal a equipo

Ya construiste un asistente de IA en Telegram para uso personal: Claude, GPT u otro LLM envuelto detrás de un bot corriendo en tu propio servidor. Funciona bien en solitario. Ahora quieres compartirlo con tu equipo: desarrolladores, asesores o especialistas que se beneficiarían de tener acceso bajo demanda al mismo asistente. El camino de un solo usuario a un equipo pequeño tiene más partes móviles de lo que la documentación suele mencionar.

Esta guía cubre cada paso: cómo recolectar los IDs de Telegram de tus compañeros, cómo extender el allow-list de manera que sobreviva la distinción entre restart y recreate en Docker, cómo abrir el tipo correcto de grupo, cómo configurar la detección de triggers para que el bot no haga spam, y cómo resolver el trade-off de privacidad que sorprende a la mayoría de los equipos.

Lo que vas a necesitar

  • Un bot de Telegram funcional que ya procese mensajes para al menos un usuario (tú)
  • Acceso SSH o shell al servidor donde corre el container del bot
  • Los nombres de usuario de Telegram de los miembros del equipo que quieres agregar
  • Acceso a BotFather (la misma cuenta de Telegram con la que creaste el bot originalmente)
  • Aproximadamente veinte minutos para el trabajo técnico, más tiempo de coordinación asíncrona con los miembros del equipo

Qué resuelve esta guía

  • Los miembros del equipo no pueden activar tu bot — "a mí me funciona, a ellos no"
  • Los cambios en el allow-list parecen aplicarse, pero el bot sigue ignorando a los nuevos usuarios después de un restart
  • El bot hace spam en grupos: responde a todos los mensajes en lugar de solo a los relevantes
  • Comportamiento confuso de los triggers: ¿cuándo debe responder el bot? ¿Solo con @mención? ¿Con una palabra clave? ¿Al responder a un mensaje suyo?
  • Preocupaciones de privacidad sobre filtraciones de memoria entre usuarios que no anticipaste

Paso 1: Recolecta el ID numérico de Telegram de cada miembro del equipo

El allow-list de tu asistente de IA en Telegram usa IDs numéricos de usuario como clave, no nombres de usuario ni nombres de perfil. Los nombres de usuario pueden cambiar; el ID numérico es estable durante toda la vida de la cuenta. Necesitas este ID para cada persona que quieras agregar.

La forma más fácil: pídele a cada miembro del equipo que inicie una conversación con @userinfobot (un bot público de utilidad). El primer mensaje que reciben contiene su ID numérico — algo como 100000001. Que lo copien y te lo envíen por DM.

Alternativas si @userinfobot está bloqueado o no está disponible en tu región:

  • Usa los logs de tu propio bot. Agrega temporalmente una línea de "registrar todos los intentos" al middleware de allow-list de tu bot, pídele al miembro del equipo que envíe un mensaje a tu bot, y lee el ID de usuario desde los logs del container. Elimina esa línea de logging después de recolectar el ID.
  • Lee desde un mensaje de grupo. Si el usuario ya escribió en un grupo donde está tu bot, el campo from.id de ese mensaje contiene su ID numérico — accesible a través del endpoint getUpdates del bot.

Guarda los IDs recolectados en un lugar seguro: una nota, un gestor de contraseñas, o directamente en tu archivo .env. Trátalos como direcciones de correo electrónico: identifican a una persona específica y pueden cruzarse con perfiles públicos de Telegram.

Paso 2: Extiende el allow-list de tu bot

La mayoría de los frameworks para bots de Telegram — aiogram, python-telegram-bot, Telegraf, grammY — implementan las comprobaciones de allow-list como middleware. Cada update entrante se filtra por el ID del remitente antes de que se ejecute cualquier handler. Los remitentes no autorizados se descartan silenciosamente: tu bot recibe sus mensajes internamente pero nunca responde.

El allow-list normalmente vive en una variable de entorno, que se carga en el container a través de env_file: en tu docker-compose.yml:

BOT_ALLOWED_USERS=100000001,100000002,100000003
BOT_OPERATOR_ID=100000001

Se usan dos formatos comúnmente:

  • Lista CSV: BOT_ALLOWED_USERS=111,222,333. El código de configuración del bot la parsea como list[int].
  • Array JSON: BOT_ALLOWED_USERS=[111,222,333]. Se usa cuando el parser de configuración espera JSON para tipos complejos.

Si tu bot usa Python y pydantic-settings para la configuración, el formato de array JSON es la opción más segura — incluso con un solo usuario, prefiere BOT_ALLOWED_USERS=[100000001] en lugar de BOT_ALLOWED_USERS=100000001. El motivo se detalla en la subsección de pydantic más adelante, pero la versión corta es que el formato JSON evita una ambigüedad del parser que puede hacer que tu container crashee al iniciar.

Paso 3: Reinicia tu container de la forma correcta

Aquí es donde la mayoría de las actualizaciones del allow-list fallan silenciosamente. Editas el .env, ejecutas docker compose restart tu-bot, ves que el container vuelve a levantarse — y los nuevos usuarios todavía no pueden activar el bot. El cambio "no se aplicó".

El motivo: docker compose restart solo detiene y arranca el container existente. No lo recrea. Las variables de entorno — incluyendo todo lo que viene de env_file: — se inyectan en el container en el momento de creación, no de arranque. Un restart conserva el snapshot original de las variables de entorno. Tu archivo .env editado es irrelevante para un container que solo se reinició.

El comando correcto:

docker compose up -d --force-recreate --no-deps tu-servicio-bot

Qué hace cada flag:

  • --force-recreate detiene el container anterior, lo elimina y crea uno nuevo con la spec actual de Compose — incluyendo el contenido actualizado del env_file:.
  • --no-deps evita que Compose también recree los servicios de los que depende tu bot (bases de datos, colas de mensajes). Si tu bot no tiene depends_on, este flag no hace nada, pero no causa problemas.
  • -d ejecuta el container recreado en modo detached, para que tu terminal vuelva inmediatamente.

Verifica que la recreación fue exitosa comprobando el uptime del container:

docker ps --filter name=tu-bot --format "{{.Status}}"
# Esperado: "Up 10 seconds" (no "Up 4 hours")

Si el estado muestra el mismo uptime largo de antes, la recreación no ocurrió — revisa si hay typos en el nombre del servicio o si ejecutaste el comando desde el directorio correcto.

Este patrón aplica a cualquier servicio de Docker Compose cuya configuración viva en un env-file: API gateways, workers, scrapers, agentes de monitoreo. La misma trampa te espera cada vez. Hemos documentado patrones más amplios para gestionar muchos containers de este tipo en nuestra guía de health-checks rutinarios para infraestructura con Docker.

pydantic-settings: una trampa del parser que debes conocer

Si la capa de configuración Python de tu bot usa pydantic-settings — la biblioteca estándar para configuraciones con Pydantic v2 — y declaras tu allow-list como list[int], te vas a encontrar con un problema del parser que vale la pena entender antes de que te pique.

pydantic-settings trata los tipos complejos (list, dict, tuple) como JSON-codificados por defecto. Cuando lee BOT_ALLOWED_USERS=111,222 desde tu env-file, primero intenta json.loads("111,222"). Eso falla con JSONDecodeError: Extra data porque un CSV plano no es JSON válido. Tu container crashea al iniciar con un SettingsError: error parsing value for field.

Si tienes un BeforeValidator personalizado en el campo que sabe parsear CSV, puede que asumas que se ejecuta primero e intercepta el string crudo antes del intento de decodificación JSON. No es así. pydantic-settings aplica el paso de decodificación JSON antes de cualquier validador a nivel de campo para los tipos complejos.

Tienes dos soluciones:

Solución rápida — sintaxis de array JSON en el env-file:

BOT_ALLOWED_USERS=[100000001,100000002,100000003]

Esto es JSON válido. pydantic-settings lo decodifica directamente en una lista de enteros. No se necesita ningún validador. El trade-off es puramente cosmético: corchetes alrededor de la lista.

Solución permanente — anotar el campo con NoDecode:

from pydantic_settings import NoDecode
from pydantic import BeforeValidator
from typing import Annotated

def parse_csv(v):
    if isinstance(v, str):
        return [int(x.strip()) for x in v.split(",")]
    return v

class Settings(BaseSettings):
    bot_allowed_users: Annotated[list[int], NoDecode, BeforeValidator(parse_csv)]

NoDecode suprime el paso de decodificación JSON por completo. Tu BeforeValidator recibe el string crudo y lo parsea como CSV. Esta es la solución más limpia si tienes control sobre el código de configuración.

El problema subyacente está documentado en pydantic-settings issue #157, con discusión relacionada en #184 y #570. El comportamiento es consistente en todas las versiones publicadas de pydantic-settings (v2.x). Si no controlas el código de configuración — por ejemplo, usas un framework de bots de terceros — usa la solución alternativa con sintaxis de array JSON.

Paso 4: Crea un grupo de Telegram con tu bot y tu equipo

Telegram tiene dos tipos de grupos para este caso de uso:

  • Grupo regular: hasta 200 miembros, modelo de administración simple, sin funciones avanzadas. Ideal para equipos pequeños.
  • Supergrupo: hasta 200.000 miembros, permisos de administrador granulares, discusiones por hilos, historial de mensajes persistente. Convierte un grupo regular en supergrupo más adelante si creces hasta necesitarlo.

Para flujos de trabajo de equipos de hasta una docena de personas, un grupo regular es suficiente. Los pasos:

  • En tu app de Telegram, toca "Nuevo grupo" y selecciona a los miembros del equipo de tus contactos
  • Ponle al grupo un nombre descriptivo: "Proyecto X — Asistente de IA", "Workspace Bot de Ingeniería", etc.
  • Una vez creado, abre la configuración del grupo, toca "Agregar miembro", busca el nombre de usuario de tu bot (@nombre_de_tu_bot) y agrégalo
  • Promueve el bot a administrador solo si necesita realizar acciones de administrador (eliminar mensajes, fijar mensajes). Para un uso de preguntas y respuestas puro, el estado de miembro regular es suficiente

Si gestionas varios bots específicos por proyecto en múltiples equipos (nosotros mantenemos varios en infraestructura compartida), los patrones multi-tenant que usamos están documentados en nuestra guía de stack de desarrollo Docker multi-tenant.

Paso 5: Configura la detección de triggers

Por defecto, un bot de Telegram en un grupo solo recibe los mensajes que lo mencionan explícitamente (@nombre_de_tu_bot), responden a sus mensajes, o usan un slash-command. Telegram llama a esto "Privacy Mode", y está habilitado por defecto — una configuración sensata que evita el spam accidental del bot.

Pero para un asistente de IA en Telegram que debe responder a preguntas naturales ("Oye bot, ¿cuál es el estado del deploy?" sin una mención explícita), el Privacy Mode es demasiado restrictivo. Tienes dos caminos:

Camino A: Mantener el Privacy Mode activado y enseñar a tu equipo a usar @menciones. Simple, no requiere cambios de configuración. El bot solo ve lo que debería responder. Desventaja: fricción. Los miembros del equipo se olvidan del @ y el bot no responde.

Camino B: Deshabilitar el Privacy Mode e implementar tu propia lógica de triggers. Abre BotFather, envía /setprivacy, elige tu bot y configúralo en Disable. El bot ahora recibe todos los mensajes del grupo. Tú implementas la comprobación de "¿debo responder?" por tu cuenta.

Un conjunto de triggers práctico que usamos en producción:

  • Mensaje directo: siempre responder — le estás hablando al bot de tú a tú
  • @mención en un grupo: siempre responder — invocación explícita
  • Respuesta a un mensaje del bot: siempre responder — continuación de un hilo que el bot inició
  • Mensaje en el grupo que contiene la palabra de activación del bot: responder. La palabra de activación suele ser el apodo del bot o el nombre del proyecto, detectada con una regex de word-boundary para que "asesor" no active accidentalmente al bot cuando alguien escribe "asesoría"
  • Todo lo demás: registrar silenciosamente en un archivo de conversación, sin respuesta

La parte del registro silencioso importa. Aunque el bot no responda, sigue viendo el flujo de la conversación en el grupo. Registrar cada mensaje en un archivo por chat le da al bot contexto futuro: cuando alguien finalmente lo @menciona con una pregunta como "¿qué decidimos?", el bot tiene la conversación reciente disponible como contexto para razonar.

La implementación depende de tu framework. En aiogram, un único handler de mensajes ejecuta las cinco comprobaciones antes de decidir si llamar a tu LLM y responder. En Telegraf o grammY, el patrón es idéntico: un handler bot.on('message') que filtra explícitamente antes de reaccionar.

Paso 6: Resuelve el trade-off de privacidad

Aquí está la pregunta que la mayoría de los equipos no considera hasta que se convierte en un problema: ¿tu bot mantiene memoria separada por usuario, por grupo, o de forma global en todas las conversaciones?

Tres patrones son comunes:

  • Memoria por chat: el bot inicia una sesión nueva para cada conversación. El DM con el usuario A es independiente del DM con el usuario B, y ambos son independientes del grupo X. Privacidad máxima. Desventaja: el bot no recuerda el contexto entre sesiones, lo que limita su utilidad como "asistente que conoce nuestro proyecto"
  • Memoria por usuario: el bot mantiene hilos de memoria separados por usuario, pero los comparte entre los DMs y las menciones en grupo del mismo usuario. Un punto intermedio razonable
  • Memoria global: el bot tiene una sesión a la que contribuyen todas las conversaciones. Máximo contexto compartido: los DMs y las conversaciones de grupo construyen la misma memoria a largo plazo. Desventaja: filtraciones de privacidad. Algo confidencial que un miembro del equipo le dice al bot en un DM puede aparecer en una respuesta grupal a la pregunta de otro miembro

Cada patrón es válido. Cada uno tiene trade-offs con los que tu equipo necesita estar de acuerdo antes de habilitar el acceso multiusuario.

Si eliges memoria global — nosotros lo hacemos en equipos de confianza donde compartir contexto es parte del valor — sé explícito con tu equipo antes de que empiecen a usar el bot: "Todo lo que le cuentes a este bot puede aparecer en respuestas visibles para todo el grupo. Trátalo como un workspace compartido, no como un confidente privado."

Si eliges memoria por chat, renuncias al razonamiento cruzado ("¿qué decidimos la semana pasada sobre X?"), pero evitas por completo el riesgo de filtraciones.

Esta es una decisión de diseño con consecuencias sociales reales, no un parámetro técnico que puedas cambiar después sin alinearte con todo el equipo. Discutimos trade-offs similares en nuestro análisis más amplio sobre skills de agentes de IA para flujos de trabajo específicos, donde las configuraciones de contexto compartido aparecen en cada proyecto que ejecutamos.

Escalar tu asistente de IA en Telegram más allá de un equipo pequeño

El patrón de allow-list en env-file funciona bien para equipos de hasta aproximadamente veinte o treinta usuarios. Más allá de eso, las entradas hardcodeadas se vuelven problemáticas: cada incorporación requiere un commit de git (si tu env se gestiona con SOPS o una capa similar de gestión de secretos), un deploy y una recreación del container.

Patrones que escalan mejor:

  • Allow-list respaldado por base de datos: los usuarios viven en una tabla SQL, el bot lee y cachea la lista al arrancar y la refresca periódicamente (o mediante un webhook ante cambios de usuario). Dar de alta a un usuario se convierte en un INSERT — sin necesidad de deploy
  • Acceso basado en membresía de grupo: en lugar de autorizar usuarios individuales, permite a cualquier usuario que sea miembro de un grupo de Telegram específico (o un conjunto pequeño de grupos). La membresía al grupo se convierte en el límite de acceso. La API getChatMember de Telegram confirma la membresía antes de cada invocación
  • Basado en canal: para asistentes de solo lectura (resúmenes diarios, alertas, digests de monitoreo), usa un canal de Telegram en lugar de un grupo. Los canales tienen un modelo de permisos diferente: solo los administradores publican, el resto lee. Útil cuando hay una distribución de uno a muchos en lugar de conversación bidireccional

Para flujos de trabajo de equipos pequeños — desarrolladores, asesores, especialistas ocasionales — el patrón de allow-list en env-file es suficiente. Nosotros lo usamos en la mayor parte de nuestra infraestructura interna y tratamos la variante respaldada por base de datos como una refactorización que hacemos una vez que un proyecto claramente supera la forma más simple.

Checklist final

Antes de que tu equipo empiece a usar el bot, verifica:

  • Los IDs numéricos de Telegram de todos los miembros del equipo recolectados y agregados al allow-list
  • El formato del allow-list coincide con lo que espera tu parser de configuración — array JSON si pydantic-settings está en el stack
  • El container fue recreado (no solo reiniciado) para que las nuevas variables de entorno se carguen en un container nuevo
  • El grupo de Telegram fue creado con el bot agregado como miembro (y promovido a administrador si necesita permisos de administrador)
  • El Privacy Mode en BotFather está configurado según tu estrategia de triggers — deshabilitado solo si implementaste tu propia lógica de filtrado
  • La lógica de triggers en el código de tu bot está alineada con el Privacy Mode (no deshabilites el Privacy Mode sin filtrar, o el bot responderá a todos los mensajes del grupo)
  • El modelo de memoria (por chat / por usuario / global) fue elegido y comunicado al equipo
  • Las expectativas de privacidad se establecieron explícitamente con los miembros del equipo antes de que empiecen a usar el bot

Si estás construyendo un asistente específico para un proyecto desde cero y quieres entender cómo encaja la infraestructura del bot, nuestro artículo complementario sobre cómo construir un asistente de IA específico para un proyecto via Telegram cubre los fundamentos. Para la infraestructura de email que suele acompañar este tipo de setups — notificaciones, rutas de escalación, registros de auditoría — consulta nuestro artículo sobre configuración de buzón específico para un proyecto con DKIM y DMARC.

Si estás operando este tipo de infraestructura de asistente de IA en Telegram para clientes o tu propio equipo y quieres ayuda con el despliegue, contáctanos. Construimos y operamos este tipo de setups como parte de nuestro trabajo en proyectos.


Artículos relacionados

Artículos relacionados