- Python 90.2%
- TypeScript 4.8%
- Vue 3.5%
- CSS 1%
- Shell 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .githooks | ||
| docs | ||
| requirements | ||
| resources | ||
| src/asami | ||
| tests | ||
| tools | ||
| web/wmi | ||
| .coveragerc | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| AGENTS.md | ||
| asami | ||
| CHANGELOG.md | ||
| Dockerfile | ||
| LICENSE | ||
| LICENSING.md | ||
| pyproject.toml | ||
| README.md | ||
Asami permet à des agents IA et à des opérateur⋅ices humain⋅e⋅s de travailler sur la même infrastructure réelle via MCP, avec un contexte partagé et des frontières techniques explicites.
Planka (l’appli web Kanban) sert de mémoire de travail durable à tous les acteur⋅ice⋅s : spécifications, décisions, tâches, commentaires et artefacts restent accessibles aux humains comme aux agents.
Les remotes (abstraction des machines en réseau) donnent ensuite à l’agent les moyens de vérifier une hypothèse sur un serveur ou une VM et d’exécuter uniquement les actions que le système et la politique courante permettent réellement.
La MCP est utilisée dans l’infrastructure LODLP et couvre des environnements hétérogènes : GNU/Linux, Docker, Windows/OpenSSH, réseau, téléphonie, multimédia, domotique et vidéosurveillance.
Pour découvrir le projet : présentation fonctionnelle · ensembles métier et profils d’agents · concepts clés · installation et premier déploiement · mise à jour d’une installation lifecycle.
Asami — WMI, TUI, sessions et coordination durable
Le produit courant consolide le contrat HUI introduit en 0.11.0 : la WMI fournit l’interface Web et asami sans argument ouvre la TUI. Ce sont deux incarnations humaines de la même grammaire métier : mêmes intentions, validations, plans, progression et résultats. La CLI non interactive reste disponible pour les scripts et l’automatisation.
Le produit courant expose notamment les sessions SSH structurées pour les épisodes multi-commandes, une coordination durable par claims structurés et reprise fenced, une Activity plus lisible avec historique borné, ainsi qu’une surface finale de 79 tools répartis en six ensembles métier. Les remotes conservent automatiquement leur identité stable lors d’une édition ; les batches Planka et transferts poursuivent les siblings indépendants après une erreur locale. Les conversations agentiques/Shadow ont été différées et ne font pas partie de la surface courante.
La WMI simplifie aussi son shell : thème clair/sombre directement dans la barre latérale, aucun écran Web « Préférences » séparé, coordinations visibles et libérables par l’opérateur, libellé d’instance asami.instance_label, et traitement explicite des redémarrages planifiés. Elle reste non privilégiée : ni socket Docker/libvirt, ni identifiants d’accès aux remotes. Après installation ou mise à jour, son bind est dérivé de la topologie du reverse proxy : loopback si le proxy est local, bind réseau joignable si le proxy est distant. Elle n’est pas publiée automatiquement : DNS, TLS et configuration du reverse proxy restent opérateur.
Voir la documentation WMI, le contrat HUI et l’accès WMI après déploiement.
Le parcours opérateur⋅ice : WMI + TUI
Le parcours humain principal passe désormais par la WMI ou la TUI. La WMI est adaptée à l’administration graphique quotidienne ; la TUI, ouverte avec asami sans argument, présente les mêmes domaines et intentions dans un terminal. L’opérateur⋅ice choisit donc le média, pas un second modèle d’administration.
La page d’accueil rassemble les entrées métier et l’état utile sans demander de connaître les primitives internes de la MCP.
Accueil de la WMI.
L’activité en cours reste visible comme une progression métier : l’interface suit les opérations et leurs résultats sans devenir un terminal distant.
Suivi des activités en cours.
La vue Machines présente les remotes par identité et état observé ; les détails techniques restent accessibles lorsque l’opérateur⋅ice en a besoin.
Vue Machines.
La configuration suit le même principe : une vue orientée intentions pour l’usage courant, avec accès explicite aux détails techniques plutôt que leur exposition systématique.
Configuration — vue principale.
Configuration — détails techniques.
La TUI porte le même contrat HUI dans le terminal. Elle n’est pas une seconde implémentation métier : les décisions, validations et opérations restent celles du backend MCP.
Pour les scripts, les agents ou la maintenance avancée, la surface CLI non interactive reste disponible (asami <domaine> <opération>, --json, --non-interactive, --input-json). L’édition directe de config/*.yaml reste également possible pour un opérateur⋅ice avancé, mais ce n’est pas le parcours humain nominal.
Après installation, ASAMI_ROOT désigne la racine canonique de l’instance (par exemple /home/docker/asami). Le runtime CLI persistant vit sous $ASAMI_ROOT/.asami/cli-runtime.
Voir documentation WMI pour la WMI, contrat HUI pour le contrat commun et documentation TUI et CLI pour la TUI et la CLI.
Ajouter et contrôler une machine
Un remote est une identité logique, pas une adresse saisie librement à chaque appel. La MCP conserve son transport, son identité de connexion, son ancrage de confiance SSH et son état enabled; les privilèges sont observés depuis la machine au lieu d’être persistés comme une politique d’autorité parallèle.
remotes add propose deux chemins :
- preprovisioned : la machine est déjà prête ; la MCP ne la modifie pas et vérifie l’accès final ;
- recipe : la MCP observe d’abord l’hôte, choisit une recipe compatible, applique uniquement son desired state typé, réinspecte puis valide avec la véritable identité MCP.
Les recipes officielles ne transportent pas de shell arbitraire et ne créent pas de privilège sudo. Les règles sudo éventuellement présentes sont découvertes ensuite comme capabilities du système distant.
Voir documentation des remotes.
Enrôler une machine avec l’Enroller
La branche remote-enrollment ajoute un parcours d’enrôlement SSH direct. Lancez l’Enroller sur la machine, ouvrez Machines dans une session WMI authentifiée et comparez les cinq symboles affichés de part et d’autre. La demande reste valable 15 minutes. Vous pouvez la refuser, ajouter une machine avec son nom lisible ou associer la demande à une identité Remote existante proposée par CORE.
Après approbation, l’Enroller prépare localement le compte Asami et son accès SSH. La liaison de la clé hôte dispose d’une fenêtre de 60 minutes. La machine devient prête lorsque CORE a réellement vérifié la connexion SSH, les droits administratifs et SFTP. Une coupure du CORE reprend la même demande avec son échéance initiale ; elle ne renouvelle pas cette fenêtre.
La restriction des réseaux source autorisés pour SSH est optionnelle. Liste absente, vide ou invalide : toute adresse source est acceptée, sous réserve de l’authentification SSH et du trust existants. Pour restreindre les origines, fournissez une liste de CIDR IPv4/IPv6 depuis lesquels CORE joint réellement les machines ; aucune adresse n’est déduite du reverse proxy ou du navigateur. Le champ TUI peut rester vide ; la CLI accepte --ssh-source-cidr répété pour chaque réseau. Installation, démarrage, upgrade et réinstallation acceptent l’absence du paramètre. Seule une liste entièrement valide active une restriction. Une liste invalide est signalée et ignorée, sans bloquer l’installation, le démarrage ou l’enrôlement ; aucun sous-ensemble partiellement valide n’est appliqué. Pour rester compatible avec les Enrollers V1 déjà intégrés, le bootstrap représente cette absence de restriction par les deux réseaux universels IPv4/IPv6 (0.0.0.0/0, ::/0). Ces réseaux ne sont pas persistés comme configuration par défaut. Aucune règle de refus global ni from="" n’est créée.
La WMI permet ensuite d’éditer cette liste dans la configuration technique. Saisissez les CIDR séparés par des virgules, puis appliquez la modification : CORE valide la liste entière avant l’écriture. Les valeurs soumises restent figées pendant l’enregistrement.
Pour réinstaller une archive de qualification de feature après désinstallation, conservez aussi l’ancienne archive source extraite. Le formulaire de récupération demande son chemin absolu : son identité et ses octets doivent correspondre à l’empreinte conservée avant désinstallation. Une feature ne reçoit pas de numéro de release artificiel ; la restauration exige la même identité et refuse une ancienne archive modifiée.
Configurer et utiliser Sentry
Dans Configuration → Sentry → Configurer, suivez le parcours Configurer → Tester → Valider → Utiliser :
- Saisissez l’origine HTTPS de votre instance et le User Auth Token dans le champ masqué. Si un token est déjà configuré, laissez ce champ vide pour le conserver.
- Confirmez l’instance destinataire et les permissions vérifiées côté Sentry :
org:read,project:readetevent:read. - Cliquez sur Tester. Asami effectue une lecture authentifiée ; le test n’enregistre pas la configuration et n’effectue aucune écriture Sentry.
- Cliquez sur Valider dans les cinq minutes suivant le test. Asami enregistre la configuration et le token dans son stockage canonique, puis démarre l’intégration. Les lectures deviennent disponibles après vérification de son état.
Le token enregistré n’est jamais renvoyé à la WMI. Toute modification du brouillon impose un nouveau test. Désactiver arrête l’intégration en conservant ses paramètres et son token.
La capacité inspect propose la liste des organisations et projets, la recherche native d’issues et la lecture d’une issue. Une URL de release donne uniquement une information partielle, sans chargement de détails. Les écritures, la recherche IA et les autres familles de ressources restent indisponibles.
Cette branche utilise FastMCP 4 et le scope OAuth asami:mcp : reconnectez les clients OAuth existants. L’admission du protocole MCP 2026-07-28 reste fermée par défaut ; les clients explicitement admis sont déclarés dans la configuration canonique mcp.sessionless_oauth_clients.
Coordonner plusieurs agents
La messagerie de coordination reste directe et sans registre de présence. Pour les ressources partagées, coordination_begin acquiert atomiquement des claims structurés sur une target, un chemin, un service, un port ou une ressource opaque. Les leases sont persistées hors des workspaces de release et survivent aux redémarrages tant que leur TTL reste valide. coordination_resume permet de récupérer une lease après perte du token privé uniquement avec sa préimage exacte et le même client OAuth.
Voir documentation de la coordination.
Travailler avec Planka
Les noms Planka sont des labels mutables ; les IDs sont les identités à réutiliser après découverte. Un renommage humain ne doit pas faire sélectionner silencieusement un autre objet.
La MCP découvre le scope réellement visible par son identité Planka. Un changement de membership peut donc prendre effet sans éditer une allowlist MCP ; un miss de lookup déclenche une découverte fraîche avant de conclure à l’absence.
Les mutations restent décidées par Planka lui-même. Les informations role, canComment et capabilities exposées par la MCP sont descriptives, pas une ACL concurrente.
Les labels d’un tableau Planka sont maintenant manipulables par identité stable : list_labels, create_label, update_label et set_card_labels couvrent la découverte, les champs nom/couleur, le placement sémantique et l’association aux cartes. Un ajout déjà présent ou un retrait déjà absent reste un no-op explicite ; les doublons, conflits add/remove et labels d’un autre tableau sont rejetés avant la première écriture. La suppression de label reste volontairement hors surface agent.
Les mises à jour de description conservent replace_exact avec expected_count et verrou SHA. Leur archive utilise désormais ARCHIVE_DESCRIPTION_V2 : delta inverse compact lorsque possible, checkpoint complet lorsque nécessaire, chaîne de provenance vérifiée et archives historiques toujours rollbackables. Le batch multi-cartes reste préflighté avant le premier write et expose explicitement completed/failed/remaining sans prétendre être une transaction ACID multi-cartes.
Le produit courant expose aussi read_card_custom_fields et l’unique writer batch set_card_custom_field_values, ainsi que create_tasks et delete_attachments pour traiter une intention multiple avec préflight global et reçus item par item. Après le préflight, les batches indépendants sont best-effort : une erreur locale n’annule plus les siblings, tandis qu’une perte du contexte partagé arrête seulement le suffixe non tenté.
Voir documentation des intégrations.
Tous les fichiers transitent via la MCP sans passer par le modèle / agent externe
Lorsqu’un artefact existe déjà sur une machine, dans Planka ou dans le staging, la MCP le déplace directement côté serveur.
deliver_files et export_attachments_to_target portent les intentions de haut niveau ; la publication de release passe par GitLab Release + Generic Package. Les anciennes primitives MCP spécialisées de publication de release ne sont plus exposées. Les primitives de staging restent disponibles pour les flux partiels ou personnalisés.
Les reçus indiquent les contrôles réellement effectués — taille, SHA-256, destination, réconciliation — afin qu’un agent n’ait pas à refaire une vérification annoncée comme finale.
Voir documentation des transports et transferts.
Configuration à chaud
La configuration métier active vit sous config/. Les secrets Planka/Frigate sont séparés du YAML principal ; les identités privées SSH/drop restent dans leurs répertoires dédiés.
Le MCP publie une nouvelle génération uniquement après validation complète. Lorsqu’une désactivation ou un changement d’identité/transport exige une reconnexion, les connexions concernées sont révoquées après le commit de la nouvelle génération. asami.instance_label ajoute un libellé opérateur facultatif de 16 caractères maximum pour distinguer visuellement les instances sans changer leur identité technique.
Voir documentation de configuration.
Installer, mettre à jour et revenir en arrière
Pour une nouvelle installation, le guide court couvre l’extraction de la release, asami install et le premier déploiement vérifié : installer Asami.
Pour mettre à jour une installation lifecycle existante depuis une archive officielle, suivez le guide général d’upgrade. Il couvre la vérification de l’archive, asami prepare-upgrade, la préparation de la candidate, le déploiement, la vérification et le nettoyage éventuel du rollback précédent.
Identités, permissions et vérification de l’installation
L’installeur ne tourne jamais en root : il exige un compte non-root avec sudo complet et confie chaque artefact système (fichiers sous /etc, unités systemd, wrapper CLI) à une élévation ponctuelle à argv fixe.
L’identité runtime est dérivée, jamais configurée : c’est l’uid/gid effectif du compte qui lance l’installation, pas une variable d’environnement. Les clefs ASAMI_RUNTIME_UID et ASAMI_RUNTIME_GID sont dépréciées et retirées du .env de déploiement.
Le compose.yaml généré impose cette identité aux trois services applicatifs (mcp, wmi, activity-journal) via la directive user: ":". L’uid est celui du compte installateur ; le gid est celui du groupe daemon de l’hôte, résolu dynamiquement à l’installation : c’est la plomberie du supervisor.sock (le superviseur, root, crée son socket et le donne au groupe daemon en 0660 ; le groupe users interne aux images serait trop large, et le gid du compte installateur n’est pas la plomberie). Conséquences :
- tous les fichiers des volumes (config, state, run, logs, pgbackup) appartiennent au compte installateur, quel que soit son uid ;
- l’uid interne des images Docker (plomberie interne, fixée au build) n’a aucun effet sur le déploiement : deux installations par deux comptes uid différents se comportent identiquement ;
- db gère ses propres permissions dans son volume Docker nommé, et seul le superviseur tourne en root (0:0, socket Docker).
Les services applicatifs portent des healthchecks compose : mcp et wmi répondent en TCP sur leurs ports (MCP_PORT et WMI_PORT, 8097/8098 par défaut), activity-journal ne présente pas d’enregistrement d’erreur de démarrage. L’installation elle-même vérifie la santé réelle des services (base prête, mcp et wmi joignables, activity-journal vivant et stable) avant de se déclarer terminée : un install_complete ne peut plus être émis avec des services en crash-loop, l’installeur s’arrête explicitement avec le diagnostic (docker logs asami-mcp etc.).
Lors d’un upgrade, le re-rendu du compose par le superviseur préserve l’identité de l’installation (extraite du compose existant, ou dérivée du propriétaire du compose.yaml et du groupe daemon pour les installations antérieures à ce mécanisme) : l’uid d’exploitation ne change jamais au fil des versions, le gid de plomberie non plus.
Voir aussi documentation du layout opérateur pour le layout lifecycle et documentation TUI et CLI pour le détail des commandes.
Déplacer une installation
Déplacer Asami une fois installé est possible, mais il faut utiliser l’outil ad-hoc fourni par le projet pour que l’opération soit sans friction pour l’opérateur : le compose.yaml généré par l’installeur contient des chemins absolus (montages, env_file) propres à l’emplacement d’installation, et une adresse telle que ASAMI_ROOT n’a de sens que sur l’hôte (/etc/asami/environment). Ne déplacez pas le répertoire à la main : le déplacement suppose la régénération du déploiement — aujourd’hui via l’installeur lifecycle, demain via l’outil dédié du projet.
Documentation technique
La documentation détaillée d’Asami est versionnée séparément du produit dans le dépôt lodlp/asami-docs. Le présent README reste donc utilisable depuis une archive Asami autonome, sans checkout du dépôt documentaire.
Roadmap du projet
Une feuille de route simplifiée est accessible dans le wiki GitLab du projet.
Elle décrit les fonctionnalités de manière succinte, et pointe vers les cartes Planka de spéficications détaillées.
Ces cartes seront publiquement accessibles dès que l’implémentation de lecture publique des tableaux de Planka sera terminée. En attendant, vous pouvez demander un accès privée en nous contactant sur le GitLab.
Licence
Copyright © 2026 Olivier Cortès.
asami est distribué sous GNU AGPL-3.0-or-later. Voir LICENSING.md pour la portée de la licence et LICENSE pour son texte intégral.




