¿Cómo funciona LIA?

Las grandes decisiones técnicas de LIA, y por qué las tomé.

1. Visión general

Diseñé LIA para que funcione en tu casa, con hardware modesto. La plataforma de referencia es una Raspberry Pi 5 (ARM64), y todo lo que sigue se deriva de ello: una sola máquina, una base de datos PostgreSQL y un Redis locales, ninguna base de datos alojada en otro sitio. Las credenciales y las claves de los proveedores se guardan cifradas.

Tres principios guían el resto. La transparencia, primero: la observabilidad forma parte de la arquitectura desde el principio, y cada token consumido se sigue con su coste. La defensa en profundidad, después: cuotas, confirmaciones y salvaguardas contra las alucinaciones son capas independientes. La independencia respecto a los proveedores, por último: cada rol del sistema puede confiarse a un modelo distinto, lo que me protege tanto de una subida de tarifas como de una caída.

El stack es deliberadamente clásico:

CapaElección
BackendPython 3.14, FastAPI, asíncrono de principio a fin
Orquestación de los agentesLangGraph 1.x
DatosPostgreSQL con pgvector: datos, checkpoints del grafo y búsqueda vectorial
Caché y coordinaciónRedis: caché, sesiones, límites de tasa, elección de un líder
FrontendNext.js 16 (App Router), React 19, TypeScript estricto
ModelosOpenAI, Anthropic, Google Gemini, DeepSeek, Perplexity, Qwen, y cualquier modelo local mediante Ollama
LogsJSON estructurado, datos personales filtrados

Un modelo local funciona sin coste de API, enteramente en tu casa. La API se ejecuta en varios workers; una elección de líder en Redis reserva las tareas programadas a uno solo de ellos. Cada subsistema opcional se activa con un flag, y la configuración sigue una sola cascada: lo que el administrador ajusta en la aplicación prevalece sobre el entorno, que prevalece sobre las constantes del código. Quise una sola cascada porque una constante que diverge en silencio de la configuración real produce los bugs más difíciles de ver.

Un instalador guiado hace unas pocas preguntas, crea la cuenta de administrador sin escribir ningún secreto en claro, comprueba que la instalación funciona de verdad y sabe reconfigurarla más adelante sin volver a pedir las claves (instalar LIA).

En órdenes de magnitud: más de 350 ADR, cientos de métricas Prometheus, decenas de miles de pruebas automatizadas, una interfaz en seis idiomas (francés, inglés, alemán, español, italiano, chino).

Para saber más: arquitectura general · autoalojamiento · proveedores de modelos · capacidades administrables

2. Un backend dividido por dominios

El backend sigue el Domain-Driven Design. Cada dominio de negocio (agentes, conectores, voz, memoria, recordatorios, conversaciones…) es un contexto aislado en src/domains/, dividido de la misma manera: router, servicio, repositorio, modelo, esquema. Al lado, un núcleo transversal (core) lleva la configuración y las reglas comunes, y una capa de infraestructura compartida reúne lo que todos necesitan: la fábrica de modelos, la caché, el cliente MCP, el navegador, los límites de tasa, el planificador de tareas, la observabilidad.

Elegí una arquitectura hexagonal para los servicios externos. Las herramientas solo conocen protocolos de Python (los puertos), y los clientes de Google, Microsoft, Apple o Philips Hue los implementan (los adaptadores). Añadir un proveedor no toca, por tanto, el código que lo llama.

El repositorio es un monorepo: apps/api para el backend, apps/web para la interfaz, infrastructure/ para Docker y la supervisión, docs/ para la documentación. Un administrador que cambia un modelo en la interfaz lo ve aplicado al instante, sin volver a desplegar, porque la configuración viva está en la base de datos.

Para saber más: crear un conector · crear un agente · crear una herramienta · añadir un canal · añadir un proveedor de modelos · añadir una tarea proactiva

3. El recorrido de un mensaje

Elegí LangGraph para orquestar los agentes porque aportaba tres cosas que necesitaba: un estado persistido en checkpoints en PostgreSQL, ciclos, e interrupt(), que permite suspender un turno para pedir una confirmación y luego retomarlo exactamente donde se había quedado. Sin ese mecanismo, no hay confirmación humana seria.

Cada mensaje pasa primero por un enrutador, que lo clasifica como conversación simple o como petición que requiere una acción. Una conversación va directa a la respuesta. Una acción sigue el modo elegido en la cabecera del chat.

En modo Pipeline, el modo por defecto, el planificador escribe antes de cualquier ejecución un ExecutionPlan: un plan en JSON cuyos pasos están enlazados por sus dependencias. Un segundo modelo, distinto del planificador, valida ese plan, para evitar que un modelo juzgue su propio trabajo. El orquestador ejecuta después los pasos en oleadas paralelas. El modo ReAct, en cambio, deja que el modelo llame a una herramienta, lea el resultado y decida qué sigue, paso a paso.

Mantuve los dos porque responden a dos necesidades. El Pipeline planifica, paraleliza, se controla y prevé su coste: una llamada al planificador y otra a la respuesta, frente a una llamada por iteración en ReAct, es decir, de 4 a 8 veces menos tokens. ReAct se adapta a cada resultado, lo que es mejor para una búsqueda exploratoria o una petición ambigua. Los dos modos comparten el registro de herramientas, las confirmaciones, el nodo de respuesta y la observabilidad.

La elección de los dominios y de las herramientas pasa por un enrutador semántico basado en embeddings en lugar de por palabras clave o por el modelo solo: cuesta menos y se equivoca menos. Cada herramienta declara un manifiesto (parámetros, salidas, coste, permisos, palabras clave en varios idiomas) que leen el planificador y el enrutador, y cada familia de herramientas se declara una sola vez en un registro central. Unos Smart Services reducen aún más el consumo almacenando en caché el análisis de las peticiones y aprendiendo los planes que se repiten. Tras un turno con acción, un nodo de iniciativa mira, en solo lectura, lo que el resultado implica en otros ámbitos: una lluvia anunciada remite a las actividades al aire libre de tu agenda. Cualquier otro turno se lo salta y no cuesta nada más.

Unas pocas reglas mantienen honesto el conjunto. Una petición sin intención de actuar no puede producir un plan que modifique nada, y es una regla determinista, comprobada antes de cualquier llamada al modelo. Un plan de modificación que agota sus intentos de corrección no se ejecuta: LIA hace una pregunta en lugar de escribir un dato falso. Un rechazo o un fallo nunca se presenta como una acción realizada, y una vez ejecutado el plan, nada se repite a tus espaldas: la respuesta dice cada fallo, qué herramienta, por qué, y el total exacto. Para un modo que se corrige sobre la marcha, está ReAct.

La respuesta llega token a token por SSE. La generación está desacoplada de la conexión: un productor independiente publica en un flujo de Redis propio del turno, y la página no es más que un suscriptor. Cerrar la pestaña no detiene nada, y la respuesta te espera.

Para saber más: los dos modos · la elección de LangGraph · el grafo en detalle · el enrutador · el plan y su ejecución paralela · el planificador y las operaciones masivas · el enrutador semántico · los manifiestos de herramientas · un fallo del pipeline se dice, nunca se repite · la restitución de los fallos de herramientas · los turnos que sobreviven a la pestaña · el modo ReAct

4. Actuar con prudencia

Para MCP, eliges confirmaciones por cuenta, servidor y herramienta. La vista de comportamiento explica la regla efectiva antes de cambiarla. Un agente dedicado pregunta antes de su tarea si alguna herramienta necesita aprobación; la respuesta cubre sus llamadas para esa tarea. «Nunca preguntar» se suspende si cambia la declaración. El chat puede reforzar estas protecciones; solo Configuración puede reducirlas. Una rutina puede usar los servidores que preaprobaste expresamente en su formulario.

LIA pregunta antes de lo que va a ocurrir de verdad: cada borrador (un correo, un evento, un borrado), cada operación masiva que modifica al menos un elemento, cada herramienta que declara requerir una confirmación. La confirmación se pide acción por acción, allí donde se prepara la acción, y no sobre el plan entero. A la inversa, una acción que nada puede desviar no pide nada: un correo que te envías a ti mismo sale directamente.

Lo que confirmas es exactamente el último contenido mostrado, y cada modificación solo se ejecuta una vez. Varios borradores de un mismo turno se revisan uno por uno. Puedes responder con tus propias palabras: un modelo clasifica tu respuesta como acuerdo, rechazo o petición de modificación. Fuera de la conversación, un ticket pide su confirmación en el propio ticket, y una rutina que se ejecuta sin nadie delante de la pantalla no hace preguntas: rechaza la acción y lo dice, porque si no tu siguiente mensaje pasaría por una respuesta. Una orden dada al chat («pon mis respuestas en tarjetas») sigue la misma regla, y cuando exige conectar una cuenta, introducir una clave o elegir un archivo, ese paso se hace en el navegador autenticado. LIA comprueba el resultado pedido en lo que puede observar, pero una delegación a una herramienta no prueba por sí sola todos sus efectos internos. Del mismo modo, un bloqueo impide una doble ejecución sin poder garantizar que un proveedor externo actúe una sola vez.

La respuesta misma está acotada: el modelo solo redacta a partir de los resultados reales de las herramientas. Y todo lo que LIA hace se inscribe en tres registros distintos: las acciones, las consultas y los turnos. Sus totales no se suman, ya que un turno puede consultar cinco fuentes sin cambiar nada. Una acción se inscribe antes de ocurrir y solo se cierra con un resultado explícito. Borrar una conversación retira los archivos que enviaste en ella, no los que LIA ha producido para ti.

Para saber más: las confirmaciones · la cadena de autoridad y los registros · los registros del lado del usuario · los tickets · los comandos de aplicación · lo que prueba una delegación · ejemplos de herramientas, correo a uno mismo y borradores · la síntesis de la respuesta

5. Memoria y contexto

Cuando designas un resultado por remitente, título o posición, LIA usa primero los elementos que realmente mostró. Si encajan varios, pregunta cuál. Una búsqueda planificada que actuaría sobre el primero de varios resultados también espera tu elección y después continúa con ese elemento.

El estado de una conversación es un MessagesState que LangGraph guarda en checkpoints en PostgreSQL después de cada nodo. Eso es lo que permite retomar un turno tras una confirmación, incluso horas después. Los resultados de las herramientas no viven en el historial de mensajes sino en un registro de datos aparte, de modo que sobreviven cuando el historial se trunca. Por encima de un umbral, los intercambios antiguos se resumen; un indicador muestra cuánto se ha llenado el contexto, y /resume lanza ese resumen a petición. En modo ReAct, lo que un bucle ya ha leído se guarda en un checkpoint y se reutiliza dentro del turno; una parada antes de ese checkpoint puede hacer que se vuelva a leer una fuente.

La memoria a largo plazo, los espacios de conocimiento y el contexto de las herramientas viven en la misma base de datos, con pgvector. Tras cada intercambio, una tarea en segundo plano extrae los recuerdos del último mensaje; los recuerdos cercanos a la pregunta vuelven al contexto siguiente, y la memoria también es una herramienta que consultan el planificador y ReAct. Una indicación duradera («responde más corto») queda fijada y visible. Cuando se toca un tema sensible, una directiva prohíbe bromear o quitarle importancia.

Alrededor de esta memoria, añadí varias capas. Los diarios son los cuadernos de LIA, en primera persona; de ellos surge un retrato de la persona, con las fuentes que lo han alimentado, y solo se corrige mediante palancas indirectas. El Psyche Engine da a LIA un estado psicológico que evoluciona con cada intercambio y se transparenta en su estilo sin anunciarse; también aprende, ámbito por ámbito, dónde es fiable, a partir de pruebas; es un piloto, sin ninguna ganancia reivindicada por ahora. Tiene un límite asumido: casi nunca informa de una emoción tranquila y poco intensa, y esa parte de su activación sigue bloqueada. Los intereses se detectan en tus peticiones y se alimentan de varias fuentes. Los hábitos, por último, se aprenden sin modelo entrenado, mediante tests estadísticos, y tenía tres razones, cada una suficiente por sí sola: una Raspberry Pi no tiene presupuesto de entrenamiento, una fórmula se le puede mostrar a la persona a la que concierne, y con volúmenes tan pequeños un modelo aprendería sobre todo el ruido.

Para saber más: los checkpoints · el registro de datos · la compactación · las lecturas de ReAct en checkpoints · la memoria en PostgreSQL · la memoria a largo plazo · la memoria como herramienta de búsqueda · las reglas duraderas · los diarios y el retrato · el Psyche Engine · su límite medido · la psique del lado del usuario · la eficacia aprendida a partir de pruebas · los intereses · los hábitos · la búsqueda en los diarios y los registros

6. Los modelos

Una fábrica única instancia el modelo de cualquier proveedor compatible y le aplica su adaptador. Cada rol tiene su slot de modelo (la conversación, la planificación, la imagen, la transcripción, la síntesis de voz…), ajustado en la administración sin volver a desplegar. El catálogo de modelos vive en la base de datos y declara, modelo por modelo, sus capacidades, los parámetros que acepta y la escala de reflexión que conoce; así, la pantalla de configuración solo ofrece lo que la API del modelo acepta de verdad.

Algunas tareas no son generaciones sino decisiones acotadas: elegir un formato, calificar un correo. Pueden confiarse a un motor de decisión nativo, cada una detrás de su propio interruptor y de un interruptor general. Una decisión incierta vuelve al tratamiento habitual, y ni los derechos ni las confirmaciones se le delegan. Un dictamen de calificación no autentica a ningún remitente, y una ganancia medida en un corpus de prueba no vale como promesa para cada petición.

Cada llamada a un modelo, tanto en el pipeline como en las tareas en segundo plano, se sigue y se valora a partir de las tarifas de la base de datos, y luego se agrupa por turno. En cuanto al coste, el principal ahorro viene de la caché de los proveedores. Cada prompt coloca su contenido estable antes de un marcador y el contenido propio de la petición después, y la infraestructura traduce ese marcador al mecanismo de caché de cada proveedor. Como cada slot puede cambiar de modelo, no ajusto esa caché para un modelo concreto: apunto a la mejor media, y un modelo sin caché no paga nada de más. Los estudios hechos sobre otros motores locales (oMLX, llama.cpp, LM Studio) son validaciones, no integraciones entregadas: solo cuentan los proveedores que ofrece la instancia.

Para saber más: la selección de los modelos · el catálogo en la base de datos · la pantalla de configuración · las decisiones nativas · su integración · la calificación de los correos · una disposición para todas las cachés · el filtrado del catálogo de herramientas · los motores locales estudiados

7. Conectores y herramientas

Cada categoría de conectores (correo, agenda, contactos, tareas, archivos, hogar) es un protocolo de Python. Solo hay un proveedor activo a la vez por categoría, y el consentimiento OAuth se da una vez por cuenta de Google o Microsoft. Los servicios que no piden nada a la persona (Wikipedia, la lectura de páginas, los lugares, el tiempo) pertenecen a la instancia y están activos para todos. En el correo, cada mensaje se resume una vez y luego se reutiliza, un adjunto se lee como texto o mediante un modelo de visión, y un envío nunca se reintenta tras un acuse de recibo perdido.

Las herramientas descansan sobre cinco capas componibles: una base común de conector (OAuth, caché, inyección), un decorador, formateadores por dominio, el manifiesto que lee el planificador y un cargador de catálogo. Las herramientas MCP se convierten en herramientas LangChain normales y entran en el mismo catálogo, que se conserva de un mensaje a otro para que un mensaje no suela esperar a ningún servidor; un servidor MCP debe usar HTTPS, sus credenciales están cifradas, y LIA cree una anotación que anuncia una modificación, nunca una que dice ser de solo lectura. Los plugins en formato Agent Plugins se instalan de una pieza, sin servidor local. Las skills del estándar agentskills.io pueden mostrar una pequeña aplicación en el chat o ejecutar sus propios comandos en una copia de su carpeta; una skill venida de fuera se ejecuta aislada y nunca recibe el token de un conector.

Cuando un paso requiere un cálculo de verdad, el modo ReAct puede escribir un breve script de Python y ejecutarlo en un contenedor desechable. Ese script solo llega a la web a través de un proxy único, no ve la clave de la persona (el proxy la sustituye en el único host autorizado), y un host desconocido da lugar a una pregunta con tres respuestas posibles. En los dos modos, los cálculos, las duraciones y las conversiones de divisas pasan por herramientas exactas en lugar de por el modelo. Un agente también sabe manejar un navegador (Playwright) o convertir una página en texto.

Los documentos de los espacios de conocimiento se dividen, se vectorizan y se guardan en PostgreSQL en lugar de en una base vectorial externa, y luego se recuperan mediante una búsqueda híbrida, semántica y léxica. Un espacio puede seguir una carpeta de Google Drive u OneDrive con sus subcarpetas, o una etiqueta de Gmail, sin indexar todo el buzón. No hay reconocimiento de caracteres: un PDF escaneado no se indexa tal cual. Los datos enviados desde fuera (SMS, número de pasos, frecuencia cardíaca, desde un iPhone, un Android o cualquier sistema capaz de enviar JSON) entran por puntos de acceso autenticados con un token de alcance limitado y revocable, distinto de la sesión.

Para una tarea compleja, LIA delega en subagentes efímeros, en solo lectura. También produce archivos: documentos, imágenes, capturas, ordenados en una galería, guardados, enviados por correo o, en el caso de una imagen, compartidos con una persona conectada a la instancia.

Para saber más: Herramientas · las páginas interactivas · los patrones de conectores · el consentimiento OAuth agrupado · los servicios de la instancia · los conectores del lado del usuario · los correos y sus resúmenes · los adjuntos · los tiempos de espera por slot · la base de las herramientas · MCP · el estándar Agent Plugins · los plugins · las skills · las skills del lado del usuario · las skills de terceros · modificar una skill · compartir una capacidad · el Python efímero · la salida de red del entorno aislado · las respuestas calculadas · el navegador · la lectura de páginas · los espacios de conocimiento · su guía · su uso · una carpeta de Drive es un árbol · una etiqueta de Gmail como fuente · la FAQ integrada · adjuntar un documento de un espacio · los subagentes · los datos de salud · su ingesta · la salud del lado del usuario · los SMS · la generación de documentos · los documentos del lado del usuario · las imágenes · los archivos generados · guardar un archivo · enviar por correo · los adjuntos del compositor · las respuestas guardadas

8. Voz, modo Live y teléfono

La voz clásica está hecha de piezas independientes. La palabra de activación «Dis LIA» se detecta en el navegador y no envía nada antes de oírse; por ahora solo se entrega el modelo francés, en beta. El dictado se transcribe en el idioma de la cuenta, en el servidor y sin conexión con Whisper, o mediante un motor remoto según el ajuste. La síntesis de voz tiene varios proveedores, Edge gratuito por defecto, y la respuesta empieza a leerse frase a frase mientras se escribe el resto. Puede añadirse un avatar parlante experimental, con la clave de Simli de la persona, que también factura los silencios mientras la conexión siga abierta.

El modo Live es una verdadera conversación de voz a voz. Le puse dos inteligencias y una sola costura: el modelo de voz lleva la conversación, y cada petición de datos o de acción pasa al motor del chat por una sola función, send_to_lia. La petición se convierte en un turno de chat normal, con sus confirmaciones, sus registros y sus cuotas. La voz no posee ni herramienta, ni credencial, ni memoria propia.

Una sesión Live se duerme en lugar de morir: durante el reposo, la conexión con el proveedor está cerrada y no se factura nada. El gasto del proveedor Live lo paga la clave de la persona y LIA nunca lo registra. En Live directo, la voz lee ella misma tus datos sin modificar nada.

El teléfono retoma los mismos dos modos. LIA puede llamar a un tercero por ti tras una confirmación, o llamarte a ti a un número verificado, y entonces tienes al teléfono tus datos y todas sus funciones, como en el chat. Cuando LIA llama a un tercero, el agente de llamada solo tiene una herramienta libre/ocupado en solo lectura: la protección de tu agenda es estructural, no depende de una instrucción en un prompt. Al teléfono, el modo Live solo existe si el proveedor puede acceder a tu instancia.

Una reunión se graba desde el navegador: el audio sale en pequeños segmentos, y luego se transcribe y se resume en un acta estructurada, guardada en un espacio de conocimiento. La radio personal, por último, solo produce durante una sesión de escucha y no guarda nada para una nueva escucha.

Para saber más: la voz del lado del usuario · el reposo Live y la palabra de activación · las voces y la síntesis · el avatar parlante · el modo Live · la telefonía del lado del usuario · el teléfono como canal · la radio · las reuniones · el acta estructurada · las plantillas de acta

9. La iniciativa

LIA toma la iniciativa de tres formas. Un heartbeat periódico mira tus fuentes y solo te escribe si una señal lo justifica, nombrando uno o dos hechos verificados. Estar conectado a una fuente y aceptar que te interrumpa son dos decisiones distintas. Una notificación push de Google puede despertar ese heartbeat para una sola persona, y un momento (el final de una reunión, la llegada de un correo esperado) se sirve al minuto en lugar de en la siguiente pasada. Las conversaciones proactivas, por último, piden una respuesta, con su propia política: horarios, máximo por día, temas sensibles mantenidos en privado, gasto reservado antes de producirse.

Las rutinas se activan según un calendario o según una condición, no ambas cosas, y una vista de la semana muestra lo que ha pasado de verdad. Un recordatorio puede repetirse. El tablero de tickets da a una tarea un ciclo de vida, un responsable y un resultado.

Dos reglas acotan todo esto. La iniciativa solo lee: una escritura se propone, nunca se ejecuta por sí sola. Y un nuevo intento de una misma ejecución se rechaza en cuanto el registro de efectos muestra que la acción ya se hizo. La página Actividad muestra en un mismo lugar todo lo que LIA ha emprendido sola, con totales exactos.

Para saber más: el heartbeat · el permiso para interrumpir · el despertar por push · los momentos y las vigilancias · las conversaciones proactivas · su entrega · su contexto · su presupuesto · las rutinas · la semana de las rutinas · los recordatorios · un recordatorio que siempre tiene texto · la iniciativa en solo lectura · el tablero de tickets · la página Actividad · valorar una notificación

10. Seguridad y privacidad

La seguridad está pensada en capas independientes, cada tipo de ataque con su propia protección. Las cuentas se conectan por OAuth 2.1 y los derechos siguen roles. Para las sesiones, elegí el patrón BFF: una cookie HTTP-only y una sesión en Redis en lugar de un token JWT, que estaría expuesto al XSS si viviera en el navegador, sería pesado de transportar e imposible de revocar. Una cuenta puede protegerse con passkeys y un segundo factor, cada dispositivo conectado se puede revocar, y vincular una identidad de Google nunca cambia el estado de una cuenta. Los límites de uso se aplican a todas las puertas, rutinas incluidas.

Todo lo que se ejecuta para la persona se trata como hostil: el código de las skills se ejecuta en un contenedor desechable, una página escrita por el modelo se ejecuta en un marco sin origen ni host propio, y una tarea en un servidor remoto se prepara y luego se confirma. Del mismo modo, lo que LIA lee sigue siendo un dato y no se convierte en una instrucción. La procedencia es una propiedad del dato: cada tipo de contenido se clasifica una vez, un tipo desconocido se trata como externo, y un tipo que nadie ha clasificado impide que la aplicación arranque.

Por encima del nivel debug, una línea de log lleva hechos (números, identificadores, códigos, el host de una dirección), no lo que escribiste ni lo que un modelo escribió sobre ti. Dos salvedades: el mensaje de error de un servicio externo en un formato desconocido aún puede citar un fragmento de ello, y el nivel debug, desactivado en producción, guarda más. La base de datos se respalda automáticamente: como mucho se puede perder un día de datos con los ajustes por defecto. La copia externa y los adjuntos quedan fuera de estas copias de seguridad.

Hay dos límites que conviene conocer. Estas medidas no demuestran por sí solas la conformidad con el RGPD de un despliegue. Y eliminar mediciones brutas, como tus datos de salud, no elimina los recuerdos que se derivan de ellas, que tienen sus propios controles.

Para saber más: la seguridad · la autenticación BFF · las passkeys · los dispositivos · los límites de uso · el entorno aislado · la procedencia de los contenidos · la privacidad del lado del usuario · logs sin datos personales · una línea de log lleva hechos · las copias de seguridad · la procedencia de un recuerdo

11. Observar y medir

La supervisión viene integrada en el despliegue: Prometheus y Grafana para las métricas, Loki para los logs, Tempo para las trazas, Langfuse para las llamadas a los modelos, Alertmanager para las alertas. El código define cientos de métricas, una treintena de dashboards se entregan listos para usar, y la emisión de métricas es defensiva: una métrica que falla no tumba una petición.

También puse la depuración en la interfaz, porque un agente es difícil de depurar: el panel de debug muestra para cada intercambio la intención, el plan, cada herramienta y cada llamada al modelo, y se ve por qué una petición ha costado cara o por qué se eligió tal dominio sin abrir Grafana.

En cuanto a los costes, cada euro que la plataforma paga por una persona se rastrea, se muestra, se atribuye y se contabiliza para ella, sea cual sea la forma en que se gastó. Existe un techo de gasto de la instancia junto a las cuotas por cuenta, porque varias cuentas multiplicadas por su cuota siguen siendo un gasto sin límite. Un operador apaga una capacidad sin volver a desplegar: lo que el despliegue autoriza y lo que el operador elige se combinan, y prevalece el menor de los dos límites.

LIA también lee su propia telemetría para autodiagnosticarse: cada alerta vital se envía por correo con su procedimiento y se convierte en un incidente, y sus recomendaciones siguen siendo propuestas. Un administrador puede incluso manejar Claude Code CLI desde el chat para examinar su servidor.

Una precisión sobre el rendimiento: las latencias medidas son las de la infraestructura. El tiempo de respuesta que percibes depende sobre todo de la secuencia de llamadas a los modelos, de unos pocos segundos a varias decenas según la petición y el hardware. Y el escalado más allá de una sola máquina (varios nodos, réplicas, Redis en clúster) sigue siendo una evolución posible, no una realidad. Quedan dos cuestiones abiertas: el crecimiento de la memoria de un worker a lo largo de varios días y la conservación de los checkpoints de LangGraph.

Para saber más: el stack de observabilidad · el panel de debug · su arquitectura · el techo de la instancia · cada gasto responde a dos techos · la administración por hoja de cálculo · los anuncios dirigidos · la instancia de demostración · el autodiagnóstico · las alertas y su resiliencia · Claude CLI desde el chat · la anatomía de un worker · las extracciones completas de los registros · la organización de las tareas en segundo plano

12. Las interfaces

El botón del centro de la cabecera del chat abre Principal y las conversaciones con título. Al crear una conversación, escribe un título. Puedes abrirla, cambiarle el nombre o eliminarla desde la lista. Principal recibe los mensajes automáticos y ofrece Restablecer. El indicador de sesión muestra los tokens, el coste y el contexto de la conversación abierta. Las preferencias, la memoria y el diario se comparten en la cuenta.

El espacio Herramientas tiene sus propias rutas REST, fuera del grafo de conversación. Reutiliza los clientes de los conectores y publica sus controles y límites en la interfaz. Las sesiones de base de datos se cierran antes de llamar al proveedor; los envíos se protegen contra repeticiones y una respuesta perdida se declara como resultado desconocido. El HTML del correo queda en un marco aislado que bloquea contenido remoto. Así se distingue un gesto manual de una acción delegada a LIA; lo que un clic le pide desde estas pantallas pasa por una puerta aparte, una llamada y una propuesta, nunca una escritura en el proveedor.

La interfaz web es una aplicación Next.js que se instala como una aplicación (PWA). El chat actualiza la conversación sin recargar, muestra las fórmulas matemáticas y el código con colores, guarda un borrador por cuenta, y se puede buscar en él; los ajustes tienen su propia búsqueda, un tema negro absoluto para las pantallas OLED que puede seguir tus horarios, tres estilos de iconos y un tamaño de texto ajustable. Una sola capa de selección sirve a todas las pantallas: un texto seleccionado se explica, se traduce o pasa al formulario habitual, nunca a otro, y un reemplazo conserva el deshacer del navegador.

En la visualización en tarjetas, uno de los tres modos a elegir junto con el HTML simple y el Markdown, una respuesta que trae datos no la formatea el modelo: el servidor la muestra en tarjetas HTML deterministas, independientes del modelo y del modo, archivadas con el mensaje. Una tarjeta muestra un hecho recibido entero y no inventa nada, y una acción desde una tarjeta prepara una petición en lugar de actuar. Para mantener la interfaz coherente, escribí reglas que unas pruebas verifican: un estado toma su tono de una tabla única, una acción tiene un nivel de importancia, y una fila de lista expone sus acciones de una sola forma. Las pruebas de navegador y de accesibilidad apuntan al nivel WCAG AA, sin certificar la visualización en un dispositivo físico ni la fidelidad de las traducciones.

Las aplicaciones móviles son carcasas nativas publicadas una vez por tienda. Cargan la dirección del servidor introducida en el primer arranque y no duplican la interfaz, porque una sola aplicación debe servir a todos los que alojan LIA. En Android, las notificaciones pasan por el proyecto Firebase de tu propio servidor; en iOS, donde solo el editor de una app puede notificar, un relé mínimo despierta el teléfono. Compartir un texto o un enlace con LIA desde el teléfono prepara un borrador de chat, que no se envía solo.

Alrededor del chat, un compañero de ojos expresivos reacciona a todo el ciclo de una respuesta, y cada respuesta lleva un pequeño avatar de estado de ánimo. El mundo de LIA es otra interfaz: una casa y un jardín compartidos por los que uno se pasea, sin que ninguna sala conceda derechos adicionales. La voz entre personas y la federación entre instancias no están implementadas en él. El vídeo de presentación, por su parte, muestra réplicas de la interfaz y datos de demostración.

Dos personas de una misma instancia pueden vincular sus asistentes para que se transmitan mensajes, y la página Relaciones reúne lo que concierne a cada persona, con un resumen redactado por el modelo.

Para saber más: el chat del lado del usuario · los ajustes · la búsqueda en los ajustes · los primeros pasos · el chat que sigue al servidor · las tarjetas · su renderizado · los lugares y los trayectos · la ubicación conocida · las primitivas y su contrato · la aplicación Android · las notificaciones nativas · las aplicaciones del lado del usuario · los ojos expresivos · los compañeros nativos · el vídeo de presentación · el mapa de capacidades · el mundo · su prototipo · las conexiones entre asistentes · las relaciones · el resumen de una relación · Telegram

13. Cómo se mantiene este código

Cada cambio pasa unas puertas locales (antes del commit, antes del envío) y luego la integración continua en GitHub Actions, que llama exactamente a los mismos comandos que un desarrollador. Las dependencias de Python son manifiestos de intención compilados en archivos de bloqueo universales que llevan la huella de cada paquete: un mismo commit instala siempre las mismas versiones, verificadas, en cada arquitectura.

Las reglas del proyecto no dependen de la memoria de quien revisa: las sostienen guardas automáticas. Varias de ellas recalculan la protección desde la fuente de verdad (el propio código, las rutas realmente montadas, el registro de conectores) en lugar de fijar una lista escrita a mano, y se han forzado a fallar a propósito para comprobar que fallan de verdad. En otros lugares, unas listas de referencia solo pueden encogerse, para que ninguna deuda crezca en silencio. Los prompts son archivos de texto versionados, uno por prompt, leídos por un único cargador. Más de 350 ADR recogen las decisiones, las alternativas descartadas y los compromisos aceptados, y decenas de miles de pruebas, la integración continua y el tipado estricto permiten hacer evolucionar el sistema sin regresiones.

Una auditoría técnica completa, de 360 grados, está publicada en el repositorio con su protocolo, para que cualquiera pueda repetirla. Cómo se escribió este código, casi por completo por una IA dirigida y controlada, se cuenta en el informe de experiencia.

Para saber más: la integración continua · el bloqueo de dependencias · los prompts versionados · la auditoría pública

14. Para saber más

Esta guía se apoya en el código, en más de 800 documentos técnicos y en los ADR. Para saber más:

El código está bajo AGPL-3.0, en GitHub.