Intégrations externes dans Gladys Assistant

Statut : brouillon, ouvert au débat
Discussion : ce sujet du forum


Salut à tous,

Je vous propose une nouvelle fonctionnalité qui va changer la manière dont les intégrations sont développées dans Gladys.

C’est un projet longuement mûri, et je serais ravi d’avoir vos retours, vos idées et vos remarques pour continuer à l’améliorer :slight_smile:

Pourquoi maintenant

Depuis le début du projet, toutes les intégrations de Gladys vivent dans le core. N’importe qui peut en développer une ou l’améliorer via une pull request, mais chaque ligne passe par ma review avant d’être mergée. Ce choix a un énorme avantage : quand vous installez Gladys, tout est déjà là. Pas de store, pas de dépendances à gérer, pas de plugin cassé après une mise à jour. C’est une des raisons pour lesquelles Gladys est plus simple à prendre en main que d’autres solutions.

Mais ce modèle a un plafond, et je suis en train de le toucher. Il existe des milliers de marques, de protocoles, de services, et la moindre modification d’une intégration, même un simple changement de traduction, doit passer par moi : review, merge, release. Ça ne passe pas à l’échelle, et ça fait de moi le goulot d’étranglement du projet.

On pourrait se dire que Matter va résoudre ce problème. Matter arrive, et va à mon avis devenir le protocole de référence qui contrôlera tous les appareils connectés à l’avenir : un seul standard, tous les appareils compatibles nativement, plus besoin d’une intégration par marque. Sauf qu’on ne sait pas quand cet avenir sera une réalité, et le projet ne peut pas se permettre d’attendre indéfiniment que le parc installé bascule.

Et surtout, Matter ne couvre que le contrôle des appareils connectés. Il reste tout un pan d’intégrations qui n’a rien à voir avec des appareils : la communication (Telegram, etc.), la météo (OpenWeather, Météo France), les calendriers (CalDAV, Google Calendar)… Tout ça ne passera jamais par Matter. Si on veut que Gladys devienne un projet avec la même ambition que Home Assistant, on doit pouvoir permettre l’installation d’intégrations externes.

Cette RFC propose donc d’ouvrir Gladys aux intégrations externes : des intégrations développées et publiées par n’importe qui, sans validation préalable de ma part, installables en un clic depuis l’interface.

Le défi, c’est de faire ça sans sacrifier ce qui fait Gladys. Concrètement, quatre exigences non négociables ont guidé cette proposition :

  1. Une intégration qui plante ne doit jamais faire planter Gladys.
  2. Pas d’états incompréhensibles : si une intégration ne répond plus, l’utilisateur doit le voir et pouvoir agir.
  3. Les interfaces doivent rester propres et cohérentes entre elles.
  4. Zéro manipulation technique pour l’utilisateur. Pas de terminal, pas de YAML, pas de redémarrage manuel.

Ce que cette RFC ne propose pas

  • On ne remplace pas les intégrations natives. Les intégrations des protocoles universels (Matter, Zigbee, Z-Wave…) resteront toujours dans le core, pré-installées, maintenues comme aujourd’hui. Le nouveau système s’ajoute à côté, et vise toutes les intégrations de protocoles ou de services qui ne sont pas universels : désormais, n’importe qui pourra créer une intégration séparée.
  • On ne vise pas la compatibilité avec les intégrations Home Assistant / HACS. Elles sont profondément couplées à l’architecture de HA ; les exécuter dans Gladys est irréaliste. En revanche, je m’inspire de leur modèle de distribution (dépôt Git + manifeste + store).
  • On ne permet pas aux intégrations d’injecter du code dans l’interface. C’est un choix assumé, détaillé plus bas.

Architecture proposée

Un conteneur Docker par intégration

Gladys tourne déjà exclusivement dans Docker, avec la socket Docker montée. On s’appuie dessus : chaque intégration externe tourne dans son propre conteneur, créé et supervisé par le core Gladys.

Ce conteneur est verrouillé au maximum :

  • pas de mode privilégié, pas d’accès à la socket Docker
  • pas d’accès à la base de données ni aux fichiers de Gladys
  • système de fichiers en lecture seule, sauf un petit répertoire de données qui lui est propre
  • limites strictes de mémoire, CPU et nombre de processus
  • réseau restreint aux hôtes que l’intégration a déclarés dans son manifeste.

Une intégration qui crashe, qui fuit de la mémoire ou qui part en boucle infinie reste confinée dans sa boîte. Et une intégration malveillante ou mal écrite ne peut pas « aller modifier la base en direct » : le fichier SQLite n’existe tout simplement pas dans son système de fichiers.

Ce choix apporte un bonus important : les intégrations ne sont plus limitées à Node.js. Une image Docker peut contenir du Python, du Go, du Rust. Chaque auteur embarque ses dépendances dans son image, et tout le build est fait en amont, au moment de la publication, jamais au runtime chez l’utilisateur.

À terme, ce choix apporte aussi quelque chose d’intéressant : il sera possible de faire tourner des intégrations déportées !

Toute communication passe par l’API-hôte

Une intégration ne touche jamais les internals de Gladys. Sa seule porte d’entrée est une API-hôte : l’intégration dialogue avec le core via une API REST HTTP JSON toute simple, dans le même esprit que ce qui existe déjà dans Gladys aujourd’hui.

Les primitives envisagées pour la v1 :

  • déclarer des appareils et leurs fonctionnalités, dans le modèle device/feature existant de Gladys ;
  • publier des états et recevoir des commandes
  • stocker sa configuration et ses secrets (stockés en DB côté core)
  • écrire des logs structurés
  • demander une découverte réseau médiée : c’est le core, qui a accès au réseau de l’hôte, qui effectue les scans mDNS et le passthrough des périphériques USB, puis transmet les résultats. L’intégration n’a ainsi jamais besoin du mode host ni d’accès matériel direct.

Ce contrat au niveau du protocole est le vrai fondement de la proposition. Le conteneur n’est « que » le mécanisme qui rend ce contrat impossible à contourner. Il permet aussi de faire évoluer le schéma interne de Gladys sans casser l’écosystème : tant que l’API-hôte est stable, les intégrations continuent de fonctionner.

Supervision : pas d’états zombie

Le core embarque un superviseur qui gère le cycle de vie complet de chaque intégration, avec une machine à états toujours visible dans l’interface :

Installée → Démarrage → En fonctionnement → Dégradée → En panne → Arrêtée

Le superviseur envoie un heartbeat régulier à chaque intégration. Pas de réponse ? L’intégration passe en « Dégradée » et est redémarrée automatiquement, avec un délai croissant entre les tentatives. Si elle crashe en boucle, on arrête d’insister : elle passe en « En panne », et l’utilisateur voit un message clair avec les logs de l’intégration et les actions possibles (redémarrer, désactiver, signaler au développeur).

Tous les appels entre le core et l’intégration ont un timeout. Une intégration qui pend ne bloque jamais Gladys.

L’objectif : qu’il n’existe plus aucun état non observable ou non récupérable. Quand quelque chose ne va pas, on le voit, on comprend, on agit, depuis l’interface.

Interface : déclarative, pas de code arbitraire

C’est probablement le choix le plus discutable de cette RFC, donc autant l’assumer clairement.

Les intégrations ne fournissent pas de composants d’interface. Elles décrivent leurs besoins, et c’est Gladys qui rend l’interface avec son propre design system :

  • la configuration est décrite par un schéma (type JSON Schema) : Gladys génère le formulaire, la validation, les messages d’erreur, de façon identique pour toutes les intégrations ;
  • les appareils sont déclarés dans le modèle device/feature existant : ils s’affichent automatiquement avec les mêmes cartes et les mêmes contrôles que les intégrations natives ;
  • pour les besoins plus spécifiques, un vocabulaire de widgets déclaratifs sera défini et enrichi progressivement, en fonction des besoins réels remontés par les développeurs.

Ce que ça coûte : un développeur ne pourra pas créer un écran totalement sur mesure. Ce que ça garantit : une interface cohérente partout, aucune faille XSS venue d’un plugin, aucun conflit de versions front, et une expérience identique pour l’utilisateur quelle que soit l’origine de l’intégration. Vu les priorités du projet, je pense que c’est le bon compromis. Mais c’est exactement le genre de point sur lequel j’attends vos retours.

Distribution : un store dans Gladys

L’utilisateur découvre et installe les intégrations depuis un store intégré à l’interface. Installer = un clic. Le core télécharge l’image, la vérifie, lance le conteneur, affiche le formulaire de configuration si l’intégration a besoin d’identifiants. Aucun terminal, aucun fichier à éditer.

Chaque intégration est publiée avec un manifeste : nom, version, versions de Gladys compatibles, permissions demandées (hôtes réseau, périphériques), schéma de configuration. Les permissions sont affichées à l’utilisateur avant l’installation, comme sur un store mobile.

Toutes les intégrations externes sont « community based » : je ne prévois pas de les relire une par une, ce serait retomber dans le goulot d’étranglement que cette RFC cherche justement à supprimer. Un avertissement clair est affiché à l’installation pour rappeler qu’il s’agit de code tiers non audité. C’est le rôle des permissions déclarées et de l’isolation par conteneur de rendre cette ouverture acceptable.

Développer une intégration à l’ère de l’IA

Un point qui change tout par rapport à il y a quelques années : développer une intégration est devenu très facile grâce à l’IA. Mon intention est de fournir un template d’intégration officiel, propre et documenté. À partir de ce template, avec Claude Code/Cursor, créer une intégration pour un service ou un protocole donné devient l’affaire de quelques heures plutôt que de quelques jours.

C’est ce qui rend cette proposition réellement puissante : au lieu d’attendre que je développe ou que je relise chaque intégration, la communauté pourra en produire beaucoup plus, beaucoup plus vite.

Le rythme d’apparition de nouvelles intégrations ne sera plus limité par ma disponibilité.

Feuille de route proposée

  1. Définir l’API-hôte et le SDK, puis proposer à quelques développeurs de créer les premières intégrations externes dessus.
  2. Spécifier le manifeste et le schéma d’interface déclarative.
  3. Implémenter le superviseur et le lancement de conteneurs verrouillés, en preuve de concept sur une seule intégration.
  4. Construire le store et le parcours d’installation, avec le template d’intégration officiel.
  5. Ouvrir la publication à tous.

Mon objectif est de sortir ce nouveau système le plus vite possible : avec les IA, il est possible d’aller très vite.

Je compte commencer le travail dès cette semaine avec Fable 5, tant qu’il est disponible.

Questions ouvertes à la communauté

  • Le compromis « UI déclarative uniquement » vous semble-t-il acceptable ? Quels cas d’usage réels ne rentreraient pas dedans ?
  • Quelles primitives manquent à l’API-hôte pour vos intégrations rêvées ?
  • Faut-il limiter la v1 aux intégrations en Node.js (avec un SDK officiel) pour simplifier, ou ouvrir tous les langages dès le départ ?

Cette proposition est un point de départ, pas une décision gravée dans le marbre : vos critiques, vos objections et vos idées sont exactement ce que j’attends pour la rendre meilleure :slight_smile:

Bonjour @pierre-gilles ,

Je ne suis pas expert en domotique, mais je suis bien sûr très heureux d’apprendre cette possibilité d’integration sur-mesure de besoin !

Je suppose que si une extension est super pertinente et fortement demandé, elle sera integrée à terme au core de Gladys ?

Il n’y aura aucun problème de performance à avoir une centaine de docker qui passe par la une seule voie l’API Host ?

Je suis Gladys depuis moins de 2 mois mais je suis choqué de la réactivité et de la vitesse de développement de cet outil !

Merci encore !

C’est en effet un gros changement mais je pense aussi que c’est nécessaire. Toi seul tu ne peux pas développer, relire et maintenir toutes les intégrations même avec de l’IA. Même avec de supers contributeurs, la relecture des contributions te prend sûrement beaucoup de temps.

Aussi, même si c’est à privilégier, il faut aussi reconnaître que l’intégration MatterBridge peut connaître ses limites quand le protocole Matter ne supporte pas certaines fonctionnalités.

Je suis d’accord avec ton approche de bien séparer le core et les intégrations. Ne pas permettre aux intégrations d’accéder au système est aussi un très bon point. Je préciserai aussi que les intégrations doivent être gratuites et open source pour être acceptées.

En ce qui concerne une version v1 je rajouterais le langage Python qui est très utilisé en domotique et facile à prendre en main. De plus les agents IA fonctionnent très bien pour produire du code Python.

Bonne question, mais rassure-toi : l’API n’est pas une file d’attente unique où les requêtes passent une par une. C’est un serveur HTTP, exactement comme celui que Gladys expose déjà aujourd’hui pour le frontend.

Node étant asynchrone, pendant qu’une requête attend la base de données, l’event loop en traite plein d’autres en parallèle. 100 conteneurs qui tapent dessus, c’est une charge ridicule.

Le vrai point d’attention, ce n’est pas l’API, c’est la RAM. Un conteneur en lui-même ne pèse presque rien (ce n’est pas une VM), mais chaque process Node embarque le runtime V8, donc il faut compter 50-80 Mo de RAM utilisée par intégration selon ce qu’elle fait. À la dizaine d’intégrations, aucun souci sur un mini-PC. À la centaine tournant en simultané, là cela dépend de ta RAM disponible :smiley:

En pratique, la plupart des installations auront entre 5 et 20 intégrations externes, ce qui est totalement confortable sur la plupart des mini-PC.

Merci !!

De toute façon, l’API sera totalement ouverte et documentée, donc chaque développeur pourra l’utiliser comme il le souhaite :wink:

Le vrai sujet est plutôt de voir quels exemples on fournit et dans quels langages. Personnellement, je n’ai pas d’expérience en Python, donc je pourrais éventuellement faire générer un exemple par IA, mais je ne serais pas vraiment en mesure de le relire, de le valider ou d’aider efficacement les utilisateurs dessus.

Mais c’est la force de ces intégrations externes : chacun sera libre et je ne serais pas le goulot d’étranglement :smiley:

Pour le futur store d’intégrations, je souhaite partir sur une architecture 100 % décentralisée, sans validation manuelle, sans review et sans avoir à demander une autorisation pour publier.

Concrètement, chaque développeur publiera simplement son intégration dans son propre dépôt GitHub en y ajoutant un topic spécifique. Ce dépôt restera la source de vérité : chacun garde le contrôle de son code et de ses mises à jour.

De son côté, un indexeur entièrement automatique (une GitHub Action publique) parcourra régulièrement tous les dépôts portant ce topic. Il vérifiera uniquement des critères objectifs : présence d’un manifeste valide, respect du schéma, accessibilité des images, cohérence des versions, etc. Si tout est conforme, l’intégration sera automatiquement ajoutée à un index.json statique, qui sera ensuite distribué via GitHub Pages et un CDN.

Les instances Gladys téléchargeront uniquement cet index statique, ce qui garantit des performances élevées, évite les limitations de l’API GitHub et permet de mettre facilement le contenu en cache. Et même si l’indexeur venait à être indisponible, le dernier index publié continuerait de fonctionner.

L’objectif est simple : personne n’a besoin de mon approbation pour publier une intégration. Les seules règles sont celles vérifiées automatiquement par le script, dont le code sera lui aussi public. Ainsi, chacun pourra comprendre immédiatement pourquoi son intégration est indexée… ou pourquoi elle ne l’est pas.

Bon je n’ai pas tout compris :face_with_head_bandage:, mais je trouve l’idée excellent car elle va permettre de faire un bond en avant concernant les possibilités de Gladys à rivaliser avec HA. Et cela va permettre à chacun de pouvoir contribuer « facilement » au perfectionnement de Gladys qui restera avec un core intact !

Il serait bien dans un second temps de laisser le choix d’utiliser une autre plateforme de dépôt Git comme GitLab et Codeberg.

Salut les @contributors :waving_hand:

J’ai bien avancé sur ce sujet aujourd’hui ! J’ai passé la journée à rédiger la spécification technique avec Fable 5.

La spécification de l’implémentation est disponible ici :

Mon objectif est de faire avancer ce développement rapidement, tout en maintenant un haut niveau de qualité.

Comme toujours, tous vos retours sont les bienvenus. :slightly_smiling_face:

3 nouveaux repository créé :

Implémentation en cours par 3 agents Fable 5 :

Je prends de l’avance car Fable 5 n’est pas garanti de rester après le 19 juillet.

Si vous avez des retours, bien-sûr tout reste modifiable, je suis vraiment preneur de retours !

Je pense que c’est une bonne chose que les intégrations puissent être gérées de cette manière.

Plus de barrière de langage et du temps libéré de ton côté, car valider chaque PR, tu dois y passer pas mal de temps, surtout en ce moment avec l’IA.

Par contre, concrètement, si on prend l’exemple de l’intégration Meteo France, il y a la partie API à gérer avec l’intégration, mais la partie widget et déclencheur de scène et action de scène.
Il faudrait découper en plusieurs parties pour séparer la partie intégration de la partie widgets et scène ? Il y aurait donc une PR pour le core avec les widgets/scène et la partie intégration Meteo France pour le store Gladys ?

Et les intégrations déjà existantes ? Elles devraient basculer dans le store ou tu vas les laisser ?