
Automatiser un parc de projets avec un agent DevOps autonome
Gérer plusieurs dépôts ne devient pas difficile parce qu’il y en a trop. Cela devient difficile parce que chaque demande oblige à répéter le même rituel : comprendre le ticket, retrouver le bon dépôt, vérifier les conventions, modifier, tester, ouvrir une merge request et prévenir les bonnes personnes. J’ai donc construit Betsaleel, un agent DevOps autonome qui prend en charge cette boucle, tout en gardant des limites explicites sur ce qu’il a le droit de faire.
L’objectif n’est pas de laisser une IA « coder toute seule ». L’objectif est de réduire le temps entre un signal fiable — un ticket assigné, un commentaire de revue, une erreur de production — et une proposition de correction testée, traçable et soumise à revue humaine.
Le vrai problème : plusieurs projets, mais une seule file d’attente humaine
Un portefeuille de projets mélange rapidement plusieurs stacks, habitudes de test et niveaux de risque. Passer d’une application .NET à un front JavaScript puis à un service Python coûte du temps de contexte. Le coût est encore plus visible lorsqu’une correction minuscule doit être interrompue par une alerte de production.
Betsaleel traite les événements à leur source :
- GitLab pour les issues assignées et les commentaires de merge request ;
- Sentry pour les nouvelles alertes d’erreur ;
- Discord pour suivre les travaux, les quotas et les interventions nécessaires.
Il ne réagit pas à tout. Une issue GitLab n’entre dans le pipeline que si l’agent est explicitement assigné. Cette règle simple évite que l’automatisation transforme chaque modification de ticket en tâche de développement imprévue.
Une architecture évènementielle qui protège chaque dépôt
Le point d’entrée est un service FastAPI. Il reçoit les webhooks, filtre les événements, puis transmet une mission à l’orchestrateur. L’orchestrateur consulte un registre de projets contenant notamment le chemin de travail, l’identifiant GitLab et la commande de test propre au dépôt.
GitLab (issues, revues) ─┐
├─> Service FastAPI ─> verrou par projet ─> orchestrateur
Sentry (alertes) ────────┘ │
├─> planification
├─> implémentation
├─> tests et correction
└─> branche / merge request / Discord
La pièce importante est le verrou asynchrone par projet. Deux dépôts indépendants peuvent avancer en parallèle. En revanche, deux demandes concernant le même dépôt passent l’une après l’autre. Sans cela, deux agents peuvent modifier la même branche ou travailler sur des hypothèses devenues fausses à quelques secondes d’intervalle.
Les opérations lentes — appels de CLI, tests, Git ou API GitLab — partent dans des threads de travail. La boucle asynchrone reste donc disponible pour recevoir les autres webhooks et mettre à jour Discord, même pendant un dotnet test un peu long.
Séparer la conception de l’exécution évite les décisions implicites
J’ai retenu une stratégie asymétrique : un moteur de planification analyse le ticket et le code, puis un moteur d’exécution réalise les changements. Le premier privilégie le raisonnement et la cartographie du contexte ; le second privilégie la mise en œuvre et les itérations de test.
Chaque rôle possède un moteur de secours. Si le moteur principal atteint une limite de débit, la mission peut être reprise par son équivalent, avec le même contexte et les mêmes restrictions. Cette redondance n’a pas pour but d’obtenir deux réponses « créatives » au même problème ; elle évite qu’un quota temporairement épuisé bloque tout le flux de travail.
Le choix du moteur, du modèle et du niveau de raisonnement est stocké dans une configuration persistante et peut être ajusté depuis Discord. Cela permet, par exemple, de réserver un profil plus approfondi pour l’analyse d’une régression et un profil plus économique pour une tâche de maintenance très bornée.
Le contexte de code doit être précis, pas énorme
Envoyer l’intégralité d’un dépôt à un modèle est coûteux et, surtout, peu utile. L’agent construit donc un graphe de code en mémoire pour les fichiers C#, TypeScript/JavaScript et Python. Il indexe les classes, fonctions, interfaces, imports, implémentations, appels et tests associés.
À partir d’un ticket, il extrait un sous-graphe : le symbole concerné, ses dépendances proches et les tests qui le couvrent. Ce contexte déterministe sert de base au prompt. Il limite les recherches répétitives et rend la correction plus facile à relire : on sait pourquoi ces fichiers, et pas tout le dépôt, ont été présentés à l’agent.
Cette approche a une limite nette : un graphe syntaxique ne comprend pas toutes les conventions métier, les dépendances dynamiques ou les comportements définis par configuration. Les instructions locales du dépôt restent prioritaires, et le plan doit signaler les zones où une lecture humaine demeure nécessaire.
Une boucle de validation courte, mais non négociable
Après l’implémentation, Betsaleel exécute la commande de test configurée pour le projet. En cas d’échec lié à ses modifications, il peut analyser le résultat et tenter au plus deux corrections. Au-delà, il s’arrête et remonte les éléments utiles : sortie de test, modifications réalisées et point de blocage.
Le seuil de deux itérations est volontaire. Sans plafond, une automatisation peut dépenser un budget important à contourner un échec qui révèle en réalité un problème d’environnement, une spécification ambiguë ou un test déjà instable. Sans tentative de correction, elle laisse aussi à l’humain les erreurs triviales qu’elle vient elle-même d’introduire.
La finalisation exige des tests verts. L’agent peut préparer une branche et une merge request, mais il ne doit pas présenter une mission comme terminée si la validation attendue n’a pas réussi.
Les garde-fous comptent autant que l’autonomie
Un agent connecté à GitLab, à un système d’erreurs et à Discord est un composant d’exploitation. Il doit donc être plus prévisible qu’impressionnant.
Les règles principales sont les suivantes :
- travailler systématiquement dans la racine du dépôt ciblé, sans
chdirglobal ; - respecter la stack et les instructions locales de chaque projet ;
- ne traiter que les issues qui lui sont assignées ;
- conserver les opérations Git, les tests et les appels réseau hors de la boucle principale ;
- dédupliquer les alertes Sentry et vérifier leur signature ;
- limiter les notifications de quota à une par période de 24 heures ;
- écrire la documentation, les guides et les notes d’architecture en anglais lorsque cette convention est celle du parc de projets.
Les secrets GitLab, Discord et Sentry restent dans les variables d’environnement. Ils ne sont ni codés en dur ni injectés dans le contexte envoyé à l’agent. Les permissions du processus doivent également rester minimales : le fait qu’un agent puisse lancer des commandes ne signifie pas qu’il doit avoir accès à tous les répertoires de la machine.
Observer le coût avant de vouloir optimiser le coût
L’agent enregistre ses consommations dans une base SQLite locale, en mode WAL : horodatage UTC, projet, type de tâche, moteur, modèle, niveau d’effort, volumes de tokens et estimation du coût. Les commandes Discord donnent une lecture par période, projet, modèle ou type de tâche.
Ce suivi répond à deux questions différentes : « quel projet consomme ? » et « quelle étape consomme ? ». Sans cette distinction, réduire le modèle de génération peut sembler être une économie alors que le coût réel provient d’une planification trop large ou d’échecs de tests récurrents.
Un tableau de quotas complète cette vue avec les fenêtres de consommation et les temps estimés avant réinitialisation. Quand une limite est atteinte, l’agent notifie l’équipe sans transformer Discord en journal de logs.
Ce que l’automatisation ne remplace pas
Betsaleel prépare et vérifie du travail ; il ne remplace pas la décision produit, la revue de sécurité ou la responsabilité d’une mise en production. Une merge request reste une proposition à relire. Les tests verts prouvent que les scénarios couverts passent, pas que l’intention métier est complète ni que tous les cas de production sont maîtrisés.
Le système est particulièrement utile pour les tickets bien définis, les corrections issues d’alertes reproductibles et la maintenance répétitive. Il est moins adapté aux changements de produit flous, aux migrations à fort impact ou aux opérations nécessitant un arbitrage humain. Dans ces cas, le bon résultat est parfois un plan clair et une question, pas un commit.
Reproduire le montage dans votre environnement
Pour construire un dispositif comparable, commencez petit :
- Déclarez un seul dépôt et une seule commande de test fiable dans un registre de projets.
- Configurez un webhook GitLab et limitez le déclenchement aux tickets assignés à l’agent.
- Ajoutez les alertes Sentry avec validation de signature et déduplication persistante.
- Isolez le travail par dépôt avec un verrou asynchrone avant d’autoriser le parallélisme.
- Rendez visibles les tests, les coûts et les quotas avant de donner à l’agent des droits d’écriture Git.
- Conservez une revue humaine obligatoire pour les merge requests et une autorisation distincte pour les déploiements.
L’intérêt d’un tel agent ne se mesure pas au nombre de tâches qu’il lance. Il se mesure au nombre de boucles répétitives qu’il ferme sans masquer le risque : bon dépôt, bon contexte, tests exécutés, résultat compréhensible et humain toujours responsable de la décision finale.