BLOG · RETOUR D’EXPÉRIENCE

Un agent IA qui travaille la nuit, sans contourner GitLab

Le montage que j'utilise pour confier les tâches répétitives à un agent, garder la traçabilité et rester le dernier validateur.

Un agent IA qui travaille la nuit, sans contourner GitLab

Ces derniers mois, l’IA a révolutionné nos usages en développement et en gestion de projet. J’ai voulu appliquer les méthodes de l’industrie logicielle à une solution agentique simple : une file de travail, des tickets, des validations et une traçabilité qui ne repose pas sur ma mémoire.

J’ai donc monté un agent que j’ai appelé Betsaleel. Son rôle n’est pas de prendre les décisions à ma place ou de publier du code sans contrôle. Il m’aide à transformer une demande claire en travail cadré : il récupère le contexte du bon projet, prépare les modifications, lance les validations et me laisse une trace lisible de ce qui se passe.

Le point important : je garde GitLab comme point de départ et la merge request comme point de contrôle. L’agent accélère le parcours, il ne le court-circuite pas. Là où je dois m’arrêter le soir — ou changer de sujet parce qu’un client appelle — il peut continuer 24 h/24 sur les tâches répétitives qui n’ont plus beaucoup d’intérêt humain en 2026.

Je ne cherchais pas un pilote automatique, mais un collègue de nuit

Le besoin de départ était très concret :

  • avoir un agent qui code la nuit ;
  • ne plus dépendre de ma machine de développement ;
  • garder une traçabilité complète sur mes projets ;
  • rester le dernier validateur ;
  • me faire aider par des agents pour les reviews de code ;
  • rester complètement agnostique vis-à-vis des IA utilisées.

La dernière ligne est importante. Je ne voulais pas construire un système verrouillé à un seul fournisseur ou à un seul modèle. Les modèles évoluent vite, leurs coûts et leurs limites aussi. Le bon modèle pour comprendre un ticket, écrire une modification ou relire un diff n’est pas forcément le même. Je veux pouvoir changer cette configuration sans refaire toute l’infrastructure.

Au début, j’ai pensé partir sur Hermès. En dessinant le besoin réel, je me suis rendu compte que je n’avais pas besoin d’une couche de plus. Le montage le plus utile restait assez direct : GitLab déclenche le travail, un VPS l’exécute, Discord le rend visible et GitLab CI publie vers Cloudflare une fois le code validé.

Le VPS orchestre, GitLab décide et Cloudflare publie

Le VPS héberge l’agent et sa file de travail. Il reçoit les événements GitLab, peut prendre en compte les alertes Sentry, prépare le travail et remonte son état dans Discord. En revanche, il ne contourne pas le processus de publication : le code revient dans GitLab, puis le pipeline déploie le site vers Cloudflare Pages ou les stores d’application (google play) une fois les validations terminées.

Schéma global : GitLab, Sentry, le VPS qui héberge l’agent, Discord et Cloudflare Pages

Cette séparation répond directement à mon besoin de ne plus dépendre de ma machine. Le VPS ne dort pas quand mon ordinateur est fermé, mais il n’a pas pour autant carte blanche. Il dispose uniquement des accès et des commandes nécessaires aux dépôts qu’il traite. La mise en production conserve son circuit normal : une branche, une merge request, la revue puis le pipeline.

Quand je veux ajouter un nouveau projet je demande via discorde à l’agent de le faire à partir de mon repository gitlab, il va cloner le projet, créer un channel discord dédié pour la communication et attendre les tickets à traiter.

Le ticket assigné est le contrat de départ

Mon Issueboard GitLab reste la vue la plus simple pour savoir où en sont les sujets. Un ticket arrive dans la colonne ouverte, je le précise si nécessaire, puis je l’attribue à l’agent lorsqu’il est assez clair pour être traité. Les tickets sont formalisés en amont avec gemini.

Tableau GitLab utilisé pour suivre et attribuer les tickets aux projets

Cette attribution est volontairement le déclencheur. L’agent ne doit pas se jeter sur tous les tickets modifiés, ni interpréter chaque discussion comme une demande de développement. S’il n’est pas assigné, il ne fait rien. Cela paraît simple, mais c’est ce qui évite les changements surprises et les fils Discord illisibles.

Le webhook GitLab transmet ensuite la demande au VPS. Le service sait à quel projet le ticket appartient, où se trouve le dépôt, quelles conventions lire et quelle commande de validation lancer. Le ticket devient donc un contrat : voilà le sujet, voilà le projet, voilà ce qui doit être vérifié avant de me proposer quoi que ce soit.

Une file par projet évite que les agents se marchent dessus

Dans mes répositories j’ai des projets très différents, il y a des applications .NET, des sites Astro, des services Python ; chacun a ses commandes, ses tests et ses conventions. L’agent garde cette configuration par projet plutôt que de traiter tous les dépôts comme s’ils étaient interchangeables.

Il y a aussi un verrou par projet. Deux projets indépendants peuvent avancer en parallèle. En revanche, deux tâches sur le même dépôt passent l’une après l’autre. Sans cela, deux traitements peuvent modifier la même branche ou travailler sur un état déjà dépassé. Je préfère qu’un ticket attende son tour plutôt que de passer une heure à comprendre un conflit créé par l’automatisation.

Avant de toucher au code, l’agent lit les instructions du dépôt, repère les fichiers concernés et regarde les tests existants. Cela semble évident, mais c’est le point qui évite de traiter un ticket comme une consigne isolée de son code.

Je sépare le code, la review et la décision finale

Un agent qui écrit un changement n’est pas forcément le meilleur pour le relire. Je peux donc utiliser des rôles séparés : une première IA analyse le ticket et prépare un plan ; une autre exécute les modifications ; un agent de review vérifie le diff, les tests et les oublis éventuels. Actuellement : le plan est réalisé par Codex Sol, le code par Codex Terra et la revue de code par Antigravity Flash 3.8. Mais je change assez régulièrement ces paramètres au fil d’avancement des évolutions des models.

Cette séparation ne transforme pas une review en tampon automatique. Elle fait remonter des questions utiles avant que je relise moi-même : une zone non couverte par les tests, une convention locale oubliée, un effet de bord possible ou un changement de périmètre. La première passe de review me lève 90% des grosses erreurs. La dernière validation reste la mienne, dans la merge request, je demande à l’agent directement dans les commentaires de la MR de traiter mes retours où ceux de la review automatique.

Et comme ces rôles ne sont pas attachés à un fournisseur, je peux tester un modèle plus pertinent pour la planification, un autre pour l’implémentation et un troisième pour la review. Si un fournisseur atteint une limite ou ne convient pas à un projet, le workflow continue sans devenir prisonnier d’un seul outil.

Les tests sont la porte de sortie, pas une formalité

Les pipelines Gitlab et les tests dans la CI s’execute, l’agent détecte si il a cassé quelque hcose et le corrige automatiquement afin d’avoir une build qui passe. S’il bloque, il s’arrête et remonte ce qu’il a fait ainsi que le résultat de la validation.

Je préfère cette limite à un agent qui essaie sans fin de faire disparaître un test rouge. Un échec peut révéler un environnement cassé, un test instable ou un besoin mal défini. Dans ces cas, le bon résultat est un diagnostic clair, pas vingt itérations invisibles.

Quand les validations passent, l’agent prépare une branche et une merge request. Il peut faire beaucoup de travail pendant que je dors ; il ne peut pas faire semblant d’être la personne responsable de la décision produit ou du déploiement.

Discord est le tableau de bord, pas le système de vérité

GitLab porte les tickets, le code et les revues. Discord me sert à savoir rapidement ce qui se passe : tâche en cours, projet concerné, ticket traité, tests lancés et blocage éventuel.

Suivi Discord anonymisé d’une tâche de développement et de ses validations

Je garde volontairement ces messages sobres. Discord n’a pas besoin de devenir un terminal qui publie chaque commande exécutée. Il doit me prévenir lorsqu’une tâche commence, lorsque les tests sont terminés ou lorsqu’il faut que je tranche. Si je veux l’historique complet, je reviens au ticket et à la merge request GitLab.

Cette traçabilité est l’un des bénéfices les plus concrets du montage. Je peux retrouver pourquoi une tâche a été lancée, sur quel dépôt elle a travaillé, quelle branche a été créée, quels tests ont été exécutés et ce qui reste à valider. Même après plusieurs jours ou plusieurs projets, rien ne dépend d’un message perdu ou d’un terminal fermé.

Ce que l’agent ne fait pas

Il n’arbitre pas une décision produit. Il ne valide pas seul une mise en production. Il ne remplace pas une revue de sécurité et il ne doit pas interpréter une phrase ambiguë comme une autorisation de modifier tout un projet.

En pratique, il est particulièrement utile sur les tickets bien définis, les anomalies reproductibles, les tâches de maintenance et les reviews préparatoires. Pour une migration sensible, une évolution produit encore floue ou un choix d’architecture, je préfère lui demander d’analyser, de proposer un plan et de lister les risques. La décision reste la mienne.

Le résultat n’est pas une usine à agents. C’est une chaîne de développement plus disciplinée : un ticket clair, le bon dépôt, des validations visibles, une review assistée et, à la fin, une décision humaine. C’est exactement ce que je cherchais en voulant faire travailler l’IA la nuit sans lui donner les clés de la maison.