Software IA a medida
Una clínica pierde citas porque nadie coge el WhatsApp a las ocho de la tarde. Construimos un micro-SaaS que contesta, consulta el calendario real del negocio y reserva — y que sabe callarse cuando el cliente se enfada. Este es el desglose técnico de cómo y, sobre todo, por qué.
Una clínica dental, un taller o una academia tienen el mismo problema y ninguno tiene departamento de tecnología para resolverlo: la gente pregunta por WhatsApp y nadie contesta fuera de horario. La consulta se enfría, el cliente llama a otro sitio, y la pérdida nunca aparece en ningún informe porque nadie la mide.
Las soluciones existentes fallan por los dos extremos. Los chatbots de reglas exigen que alguien configure árboles de conversación que se rompen a la primera pregunta imprevista. Las plataformas de atención al cliente serias cuestan más que el margen mensual del negocio y presuponen un equipo que las opere.
Talkify es nuestra respuesta: un micro-SaaS multi-tenant que conecta el WhatsApp del negocio, responde con IA sobre la información real de ese negocio, consulta disponibilidad contra su Google Calendar y reserva la cita. Y que, cuando la conversación se tuerce, se calla y avisa a una persona.
Lo construimos nosotros, con nuestro dinero y nuestro criterio. Eso significa que las decisiones difíciles no se pudieron esquivar echándole la culpa a un requisito del cliente.
WhatsApp no tiene una API oficial asequible para un negocio de barrio. La API oficial de WhatsApp Business quedó fuera del MVP por presupuesto, así que la conectividad se apoya en Baileys, una librería no oficial que implementa el protocolo de WhatsApp Web multidispositivo.
Esto convierte la conectividad en el riesgo operativo número uno del producto, y así está registrado en el documento de riesgos desde antes de escribir la primera línea: librería no oficial, riesgo de baneo, y desconexiones como parte normal del ciclo de vida, no como incidencia.
Todo lo que viene después es consecuencia de haber aceptado esa restricción con los ojos abiertos.
Nuestro estándar interno de tecnología manda Go para los servicios de backend, precisamente para no mezclar el runtime de frontend con el de backend. Baileys sólo existe en Node.js y no hay equivalente en Go con cobertura comparable.
La decisión fue escribir el worker de WhatsApp en Node.js/TypeScript como proceso separado, y dejar absolutamente todo lo demás en Go. No comparten base de datos ni espacio de proceso: se hablan por una API interna.
El resultado se ve en el reparto del código:
srv-talkify-app. El worker que habla el protocolo no oficial de WhatsApp — el riesgo operativo número uno del producto — es el 4% del código y corre en su propio proceso.El componente de más riesgo del producto es el 4% del código. Una tormenta de reconexiones de Baileys no puede tumbar el API Core, porque ni siquiera vive en el mismo proceso. Es la única vez en todo el repositorio en que nos desviamos del stack por defecto, y llevó su propio ADR justificándolo.
El coste lo pagamos en otro sitio: dos ecosistemas que mantener, dos cadencias de actualización de dependencias y dos conjuntos de convenciones. Está escrito en el apartado de consecuencias negativas de esa decisión, porque un ADR que sólo lista ventajas no es un ADR.
Reservar citas es el objetivo comercial del producto, y es justo donde un modelo de lenguaje es menos de fiar. Los LLM son malos en aritmética de tiempo, en respetar los límites de un horario comercial y en detectar conflictos entre varios eventos.
Así que se lo prohibimos. El modelo tiene terminantemente vedado estimar o suponer disponibilidad.
Toda operación de calendario pasa por function calling nativo — check_availability, book_appointment, cancel_appointment, list_my_appointments — y la lógica vive en Go, no en el prompt. El paquete internal/calendarclient cruza de forma determinista tres fuentes:
| Fuente | Qué aporta |
|---|---|
tenant_configs.schedule | El horario de apertura real del negocio |
tenant_configs.services | La duración de cada servicio |
| Google Calendar del negocio | Los eventos ya existentes, en tiempo real, vía OAuth 2.0 |
La herramienta devuelve las horas válidas calculadas y una plantilla de texto que el modelo transmite literalmente. El modelo conversa; no decide.
El tercer punto es el que importa en el mundo real: el dueño de la peluquería sigue apuntando a los que entran por la puerta directamente en su Google Calendar de siempre. Sin sincronización bidireccional real, el sistema ofrecería huecos ya ocupados y generaría overbooking — que para un negocio pequeño es peor que no tener nada.
Los tokens de refresco de Google se guardan cifrados con AES-256-GCM.
Cada negocio necesita que la IA conozca su información: dónde aparcar, qué métodos de pago acepta, su política de cancelación, las especialidades de su equipo. Eso es recuperación aumentada, y la tentación estándar es montar una base de datos vectorial aparte.
No lo hicimos. Usamos pgvector dentro del mismo PostgreSQL, con vectores de 1536 dimensiones, índice HNSW y text-embedding-3-small.
El motivo principal no es el rendimiento, es el aislamiento. Cada trozo de conocimiento lleva tenant_id con clave foránea y borrado en cascada, y toda búsqueda por similitud está acotada por tenant_id en la propia consulta SQL. Que el conocimiento de la Clínica A llegue a un cliente de la Clínica B no es un bug aceptable: es el fin del producto.
Manteniéndolo en la base relacional, el aislamiento lo garantiza el mismo motor que ya garantiza el resto, las actualizaciones son atómicas y borrar un tenant limpia sus vectores sin código adicional. Una pieza menos de infraestructura que operar, monitorizar y pagar.
Las conversaciones de WhatsApp duran semanas. Si metes el histórico entero en el prompt, pasan tres cosas a la vez: el coste por mensaje crece linealmente, la latencia se degrada, y el modelo se confunde con citas viejas cuando el cliente pregunta por algo nuevo.
La solución son dos límites, ninguno sofisticado:
Es la clase de decisión que no sale en ninguna demo y que determina si el producto tiene margen unitario.
Un bot que discute con un cliente enfadado hace más daño que un bot que no existe.
El modelo dispone de la herramienta transfer_to_human(reason, summary) con cuatro motivos tipificados: cliente hostil, petición explícita de hablar con una persona, consulta fuera de alcance, y reclamación o devolución.
Cuando se dispara, la conversación pasa a needs_human y el orquestador suprime por completo las respuestas automáticas. Los mensajes siguientes del cliente se guardan en PostgreSQL para que el personal los lea, pero no se envían a OpenAI. El panel recibe una notificación en tiempo real por SSE. Sólo el dueño puede devolver la conversación a la IA desde el dashboard.
Silenciado significa silenciado. No “responde más flojito”.
Tan determinante como lo anterior. Talkify no tiene usuarios propios, ni contraseñas, ni facturación propia:
srv-accounts por OAuth2 + PKCE.srv-billing con Stripe Checkout y Portal.El panel web nunca llama a la API desde el navegador: todo pasa por un proxy BFF del mismo origen con cookie de sesión HttpOnly. El navegador no ve nunca un token.
Cada una de esas tres decisiones es un ADR con sus alternativas descartadas. Construir login y facturación propios habría añadido semanas y dos superficies de ataque para resolver problemas que ya estaban resueltos en casa.
Tres ciclos, con criterio de “hecho” escrito antes de empezar cada uno:
| Ciclo | Alcance | Estado |
|---|---|---|
| 1 — Foundation & Core Connect | Infraestructura multi-tenant y conectividad WhatsApp | Completado (jul 2026) |
| 2 — AI Engine & Human Panel | Motor de IA, RAG, citas deterministas, handoff | Completado en backend (ago 2026) |
| 3 — Monetization & GTM Launch | Facturación, planes, pipeline comercial | ago 2026 |
Primer commit el 9 de julio de 2026. El panel web arrancó el 22 de agosto sobre el sistema de diseño “Aurora” — papel cálido de día, casi negro de noche, un solo acento naranja — en Astro con islas de Preact, CSS plano en tres capas y una CSP que sólo admite script-src 'self'.
Un producto en producción con siete módulos funcionales, 125 rutas de API, 58 migraciones de base de datos y 74 ficheros de test en Go. La parte que asumía el riesgo protocolario quedó confinada en 1.505 líneas de TypeScript.
Y 27 decisiones de arquitectura documentadas, cada una con su contexto, sus alternativas descartadas y sus consecuencias negativas por escrito. Ese documento es el entregable del que más orgullosos estamos: dentro de un año, cuando alguien pregunte por qué el worker de WhatsApp está en Node, la respuesta estará escrita con fecha y con los argumentos que se descartaron.
Es exactamente la forma en que construimos para nuestros clientes. Talkify es la prueba de que también lo hacemos cuando el dinero es nuestro.
Todo proyecto empieza con una llamada gratuita de 30 minutos. Sin pitch — solo una conversación sobre tu negocio.
Cookies
Usamos cookies analíticas (Google Analytics) para entender cómo se usa la web. Solo se activan si las aceptas. Más información en nuestra Política de Privacidad.
Recurso gratuito
Las 12 preguntas que usamos en cada proyecto para detectar las mayores oportunidades de IA. Gratis — sin spam.
Revisa tu bandeja de entrada — está en camino.