Estado: borrador, abierto al debate
Discusión: este tema del foro
Hola a todos,
Os propongo una nueva funcionalidad que cambiará la forma en que se desarrollan las integraciones en Gladys.
Es un proyecto largamente madurado, y me encantaría tener vuestros comentarios, ideas y sugerencias para seguir mejorándolo ![]()
¿Por qué ahora?
Desde el inicio del proyecto, todas las integraciones de Gladys viven en el núcleo. Cualquiera puede desarrollar una o mejorarla mediante una solicitud de extracción, pero cada línea pasa por mi revisión antes de ser fusionada. Esta elección tiene una enorme ventaja: cuando instalas Gladys, todo está listo. No hay tienda, no hay dependencias que gestionar, no hay plugins rotos después de una actualización. Es una de las razones por las que Gladys es más fácil de usar que otras soluciones.
Pero este modelo tiene un límite, y estoy a punto de alcanzarlo. Existen miles de marcas, protocolos, servicios, y cualquier modificación de una integración, incluso un simple cambio de traducción, debe pasar por mí: revisión, fusión, lanzamiento. No es escalable, y me convierte en el cuello de botella del proyecto.
Podríamos pensar que Matter resolverá este problema. Matter llega, y a mi parecer se convertirá en el protocolo de referencia que controlará todos los dispositivos conectados en el futuro: un solo estándar, todos los dispositivos compatibles nativamente, sin necesidad de una integración por marca. Excepto que no sabemos cuándo este futuro será una realidad, y el proyecto no puede permitirse esperar indefinidamente a que el parque instalado cambie.
Y sobre todo, Matter solo cubre el control de los dispositivos conectados. Queda todo un aspecto de integraciones que no tiene nada que ver con dispositivos: la comunicación (Telegram, etc.), el clima (OpenWeather, Météo France), los calendarios (CalDAV, Google Calendar)… Todo esto nunca pasará por Matter. Si queremos que Gladys se convierta en un proyecto con la misma ambición que Home Assistant, debemos permitir la instalación de integraciones externas.
Esta RFC propone, por lo tanto, abrir Gladys a las integraciones externas: integraciones desarrolladas y publicadas por cualquiera, sin validación previa de mi parte, instalables con un clic desde la interfaz.
El desafío es hacerlo sin sacrificar lo que hace a Gladys. Concretamente, cuatro exigencias no negociables han guiado esta propuesta:
- Una integración que falle nunca debe hacer fallar a Gladys.
- No hay estados incomprensibles: si una integración deja de responder, el usuario debe verlo y poder actuar.
- Las interfaces deben seguir siendo limpias y coherentes entre sí.
- Cero manipulación técnica para el usuario. Sin terminal, sin YAML, sin reinicio manual.
Lo que esta RFC no propone
- No se reemplazan las integraciones nativas. Las integraciones de protocolos universales (Matter, Zigbee, Z-Wave…) seguirán siempre en el núcleo, preinstaladas, mantenidas como hasta ahora. El nuevo sistema se añade al lado, y se dirige a todas las integraciones de protocolos o servicios que no son universales: ahora, cualquiera podrá crear una integración separada.
- No se busca la compatibilidad con las integraciones de Home Assistant / HACS. Están profundamente acopladas a la arquitectura de HA; ejecutarlas en Gladys es irrealista. Sin embargo, me inspiro en su modelo de distribución (depósito Git + manifiesto + tienda).
- No se permite a las integraciones inyectar código en la interfaz. Es una elección asumida, detallada más abajo.
Arquitectura propuesta
Un contenedor Docker por integración
Gladys ya funciona exclusivamente en Docker, con el socket Docker montado. Nos apoyamos en esto: cada integración externa funciona en su propio contenedor, creado y supervisado por el núcleo de Gladys.
Este contenedor está bloqueado al máximo:
- sin modo privilegiado, sin acceso al socket Docker
- sin acceso a la base de datos ni a los archivos de Gladys
- sistema de archivos de solo lectura, excepto un pequeño directorio de datos que le es propio
- límites estrictos de memoria, CPU y número de procesos
- red restringida a los hosts que la integración ha declarado en su manifiesto.
Una integración que se bloquea, que pierde memoria o que entra en un bucle infinito queda confinada en su caja. Y una integración malintencionada o mal escrita no puede «ir a modificar la base de datos en directo»: el archivo SQLite simplemente no existe en su sistema de archivos.
Esta elección aporta un importante beneficio adicional: las integraciones ya no están limitadas a Node.js. Una imagen Docker puede contener Python, Go, Rust. Cada autor incluye sus dependencias en su imagen, y todo el proceso de construcción se realiza previamente, en el momento de la publicación, nunca en tiempo de ejecución en el usuario.
A largo plazo, esta elección también aporta algo interesante: ¡será posible ejecutar integraciones remotas!
Toda la comunicación pasa por la API-hoste
Una integración nunca toca los internos de Gladys. Su única puerta de entrada es una API-hoste: la integración dialoga con el núcleo a través de una API REST HTTP JSON muy simple, en el mismo espíritu de lo que ya existe en Gladys hoy.
Las primitivas previstas para la v1:
- declarar dispositivos y sus funcionalidades, en el modelo dispositivo/función existente de Gladys;
- publicar estados y recibir comandos
- almacenar su configuración y sus secretos (almacenados en la base de datos del núcleo)
- escribir registros estructurados
- solicitar una descubierta de red mediada: es el núcleo, que tiene acceso a la red del host, el que realiza los escaneos mDNS y el passthrough de los dispositivos USB, y luego transmite los resultados. La integración nunca necesita el modo
hostni acceso directo al hardware.
Este contrato a nivel de protocolo es el verdadero fundamento de la propuesta. El contenedor es «solo» el mecanismo que hace que este contrato sea imposible de eludir. También permite hacer evolucionar el esquema interno de Gladys sin romper el ecosistema: siempre que la API-hoste sea estable, las integraciones siguen funcionando.
Supervisión: sin estados zombis
El núcleo incluye un supervisor que gestiona el ciclo de vida completo de cada integración, con una máquina de estados siempre visible en la interfaz:
Instalada → Inicio → En funcionamiento → Degradada → En fallo → Detenida
El supervisor envía un latido regular a cada integración. ¿Sin respuesta? La integración pasa a «Degradada» y se reinicia automáticamente, con un retraso creciente entre los intentos. Si se bloquea en bucle, dejamos de insistir: pasa a «En fallo», y el usuario ve un mensaje claro con los registros de la integración y las acciones posibles (reiniciar, desactivar, informar al desarrollador).
Todas las llamadas entre el núcleo y la integración tienen un tiempo de espera. Una integración que se bloquea nunca bloquea a Gladys.
El objetivo: que no exista ningún estado no observable o no recuperable. Cuando algo no va bien, lo vemos, lo entendemos, actuamos, desde la interfaz.
Interfaz: declarativa, sin código arbitrario
Probablemente, esta es la elección más discutible de esta RFC, así que tanto mejor asumirla claramente.
Las integraciones no proporcionan componentes de interfaz. Describen sus necesidades, y es Gladys quien renderiza la interfaz con su propio sistema de diseño:
- la configuración se describe mediante un esquema (tipo JSON Schema): Gladys genera el formulario, la validación, los mensajes de error, de manera idéntica para todas las integraciones;
- los dispositivos se declaran en el modelo dispositivo/función existente: se muestran automáticamente con las mismas tarjetas y los mismos controles que las integraciones nativas;
- para necesidades más específicas, se definirá y enriquecerá progresivamente un vocabulario de widgets declarativos, en función de las necesidades reales que surjan de los desarrolladores.
Lo que cuesta: un desarrollador no podrá crear una pantalla totalmente personalizada. Lo que garantiza: una interfaz coherente en todas partes, ninguna vulnerabilidad XSS proveniente de un plugin, ningún conflicto de versiones front-end y una experiencia idéntica para el usuario, independientemente del origen de la integración. Dadas las prioridades del proyecto, creo que es el buen compromiso. Pero es exactamente el tipo de punto sobre el que espero sus comentarios.
Distribución: una tienda en Gladys
El usuario descubre e instala las integraciones desde una tienda integrada en la interfaz. Instalar = un clic. El núcleo descarga la imagen, la verifica, lanza el contenedor y muestra el formulario de configuración si la integración necesita credenciales. Sin terminal, sin archivos para editar.
Cada integración se publica con un manifiesto: nombre, versión, versiones de Gladys compatibles, permisos solicitados (hosts de red, dispositivos), esquema de configuración. Los permisos se muestran al usuario antes de la instalación, como en una tienda móvil.
Todas las integraciones externas son «basadas en la comunidad»: no pretendo revisarlas una por una, eso sería volver al cuello de botella que esta RFC busca eliminar. Se muestra una advertencia clara durante la instalación para recordar que se trata de código de terceros no auditado. Es el papel de los permisos declarados y del aislamiento por contenedor lo que hace que esta apertura sea aceptable.
Desarrollar una integración en la era de la IA
Un punto que lo cambia todo en comparación con hace unos años: desarrollar una integración se ha vuelto muy fácil gracias a la IA. Mi intención es proporcionar una plantilla de integración oficial, limpia y documentada. A partir de esta plantilla, con Claude Code/Cursor, crear una integración para un servicio o protocolo dado se convierte en un asunto de unas pocas horas en lugar de unos pocos días.
Es lo que hace que esta propuesta sea realmente poderosa: en lugar de esperar a que yo desarrolle o revise cada integración, la comunidad podrá producir muchas más, mucho más rápido.
El ritmo de aparición de nuevas integraciones ya no estará limitado por mi disponibilidad.
Hoja de ruta propuesta
- Definir la API-huésped y el SDK, y luego proponer a algunos desarrolladores que creen las primeras integraciones externas sobre ella.
- Especificar el manifiesto y el esquema de interfaz declarativa.
- Implementar el supervisor y el lanzamiento de contenedores bloqueados, como prueba de concepto en una sola integración.
- Construir la tienda y el proceso de instalación, con la plantilla de integración oficial.
- Abrir la publicación a todos.
Mi objetivo es sacar este nuevo sistema lo más rápido posible: con las IA, es posible ir muy rápido.
Planeo comenzar el trabajo esta misma semana con Fable 5, mientras esté disponible.
Preguntas abiertas a la comunidad
- ¿Les parece aceptable el compromiso de «solo interfaz declarativa»? ¿Qué casos de uso reales no entrarían en esto?
- ¿Qué primitivas faltan en la API-huésped para sus integraciones soñadas?
- ¿Debemos limitar la v1 a las integraciones en Node.js (con un SDK oficial) para simplificar, o abrir todos los lenguajes desde el principio?
Esta propuesta es un punto de partida, no una decisión grabada en piedra: sus críticas, objeciones e ideas son exactamente lo que espero para mejorarla ![]()
















