Hace ya unos meses, a mi novia le surgió la necesidad de llevar un seguimiento de sus ciclos. Gracias a la infraestructura que tengo, se me ocurrió crear su propio asistente personal, alojado y almacenado de forma privada en mis propios servidores, con control total de qué datos llevamos al día y qué trackeamos.

Todo esto viene por la necesidad de tomar una medicación diaria y no fallar ningún día, y qué mejor forma que un mensaje programado y diario al teléfono. Con esto ya no solo nos aseguramos de que no falle, sino que podamos llevar un control y consultar dudas con sus datos personalizados al 100%.

Contexto técnico

Antes de entrar en el flujo, un par de piezas que hay que tener claras:

    • Todo corre en n8n autoalojado en mis servidores.
    • La comunicación con el usuario es vía un bot de Telegram (creado con BotFather).
    • Los datos se guardan en Data Tables propias locales, por cada ciclo.
    • El agente de IA usa Opencode GO con un modelo principal y uno de fallback con Opencode Zen.

Con esto en mente, vamos al detalle de cada camino del flujo.

Funcionamiento flujo n8n

Vamos a explicar cómo funciona y en qué consiste el flujo de n8n, al detalle y paso a paso.

Lo primero de todo, y lo más importante y sencillo, es el recordatorio. Este no puede fallar bajo ningún concepto: es el encargado de, todos los días a las 22:00, enviar el mensaje al chat de Telegram con el recordatorio y los botones para responder al bot.


¿Qué función tiene cada botón? Aquí te dejo un resumen rápido, pero más adelante se explicará más a fondo.

    • "Tomada" indica que se tomó la medicación.
    • "Días" le dice cuántos días del ciclo en curso lleva.
    • "Me bajó" el usuario indica el fin de ciclo.
    • "Me equivoqué" control por si el usuario se equivoca y pulsa "Tomada" más de una vez.

Ahora pasamos al flujo que controla la respuesta y lleva la lógica real de este asistente.

Lo primero de todo es cómo obtenemos sus respuestas; para esto usamos Telegram Trigger. Esta función se conecta a uno de mis bots de Telegram creados previamente con BotFather y está constantemente escuchando los mensajes que se envían en el chat de mi novia.

Cuando le llega un mensaje o callback query, el trigger se activa y lo procesa. A partir de ahí, el flujo se ramifica en varias rutas controladas por condiciones IF: según el contenido de la respuesta, se evalúa cada condición y se sigue una ruta u otra. Sin embargo, hay un camino que se ejecuta siempre, sí o sí.

Creación y selección de BD: este es un punto de control. Aquí simplemente se mira si la base de datos base está creada; si no está creada, se crea; si está creada, se sigue y se inserta una línea con la respuesta del usuario.

El segundo camino en paralelo que sigue es el de los comandos del bot; si el usuario manda un comando, el flujo sigue este camino. ¿Qué hacen estos comandos?

      • /help, como su nombre indica, es un comando de ayuda que lo que hace es mandar un mensaje con todas las funcionalidades del bot y cómo funciona.
      • /start, este es otro comando de control: si necesitas que el bot te vuelva a enviar el mensaje recordatorio por algún motivo, este comando te lo reenvía.

El tercer camino o rama que comprueba en paralelo el flujo es el agente de IA. Este camino solo se ejecuta en dos casos: primero, cuando le llega cualquier mensaje; y segundo, cuando le llega el callback query de "Tomada", que indica que se tomó la pastilla.

¿Esto por qué es así? Esto se configuró así ya que, si es "Tomada" y estamos en los días de flujo, el bot deberá preguntar si sigues sangrando o no, hasta que pares, para así saber la duración del mismo. ¿Por qué a cualquier mensaje? Porque si el usuario quiere hacer una pregunta, el bot le debe responder y dar una contestación siempre.

Continuando con los nodos, como puedes ver, tiene una base de datos llamada Semáforo; esto es una base de datos que se encarga de gestionar una flag para indicar en Telegram cuando el bot está pensando y procesando tu solicitud, y cuando no, esto se refleja con el mitico "escribiendo..." en la parte superior del chat. Esto lo hice ya que, dependiendo de la solicitud y su complejidad, el agente puede tardar más o menos en dar una respuesta.

El agente de IA, como puedes ver, está compuesto de dos modelos de IA conectados a Opencode: un modelo principal con GLM y un modelo fallback conectado a Zen, una simple memory —esta lleva un historial de los últimos 5 mensajes del chat— y, por último, todas las tools necesarias para consultar las Data Tables que almacenan toda la información de sus ciclos. Ahora mismo tenemos un historial de 4 meses almacenado.

¿Con esto qué puede hacer? Pues puede hacer preguntas de lo que quiera, ya sea de los ciclos actuales o anteriores. Ahora mismo el control que llevamos es tanto de la duración del ciclo por días como de la duración de sangrado: "Flujo" (true/false) y "Cantidad" (string).

Un ejemplo muy bueno puede ser simplemente que le digas que te haga un resumen de tus últimos ciclos.

Te preguntarás, ¿cómo haces para que responda como tú quieras?

El truco de todo esto es tener un buen System prompt.

¿Qué es el System prompt? El System prompt es el conjunto de instrucciones que le das al modelo de IA antes de que empiece a conversar con el usuario final. Aquí es donde yo le defino todo el contexto y le digo cómo quiero que responda y cómo quiero que se comporte. Esto se lo lee siempre antes de responder, y así siempre sabe cómo responder y cómo hacerlo.

Ahora solo nos queda ver la última rama de este flujo. Este camino es el principal y es el que siguen todos mis callbacks querys, es decir, los botones que te da el bot para responder, dicho de una manera simple.

Este flujo tiene cuatro caminos:

    • "Días": este camino hace un cálculo muy sencillo, hace una cuenta de las veces que aparece la palabra "Tomada" en la base de datos y luego muestra el total. Con este cálculo tan simple, ya tenemos el total de días que lleva, ya que en la base de datos solo puede haber un "Tomada" por día. Por último, te envía un mensaje con el resultado.
    • "Me bajó": este camino ejecuta dos flujos en paralelo. Uno hace un recuento de cuántos días te duró el ciclo. El otro se encarga de archivar el ciclo que acaba de terminar: toma la fecha actual (el día en que acabaste el ciclo) y renombra la Data Table activa con esa fecha, guardándola así en el historial. A partir de ahí entra en juego la lógica inicial de la base de datos: al día siguiente, al no encontrar ninguna Data Table base activa, el flujo crea una nueva antes de insertar el primer registro y empezar con el ciclo actual.
    • "Me equivoqué": este es un camino de control por si el usuario se equivocó y avisó más de una vez; esto lo que hace es eliminar la última línea de la Data Table.
    • "Tomada": este sería el camino final; después de dar False en los dos módulos IF anteriores, iría al final y ejecutaría un código que se encarga de generar un mensaje con una frase, que yo configuré distinta para cada día, de forma aleatoria, para así hacer la respuesta no tan repetitiva.

Como puedes ver, es una lógica muy simple, pero que en los meses que lleva usándose nunca falló, que al final es lo más importante.

Con esto ya finalizamos: en todo este proceso te expliqué y viste cómo funciona mi flujo de n8n, y cómo puedes crear un asistente simple que te ayude a monitorizar recordatorios.

Es algo simple, pero demuestra que con n8n se pueden construir soluciones muy personalizadas y útiles sin depender de servicios de terceros. La misma lógica recordatorio, respuesta del usuario, agente de IA con memoria y contexto se podría adaptar a otro caso completamente distinto: un asistente de hábitos, un bot de soporte interno, un seguimiento de tareas...

Al final, el flujo es solo la estructura; el "para qué" lo pones tú.

¿Dudas sobre el flujo o quieres adaptarlo a tu caso? Escríbeme por LinkedIn o al correo que tienes en el pie de la web.

También puedes ver más proyectos como este en mi portfolio.