Uber supprime un million de lignes de code avec des agents

L'équipe d'ingénierie d'Uber a publié un article de blog présentant son système interne AutoClean. Il se branche sur la plateforme de gestion des feature flags de l'entreprise, repère les flags qui peuvent être retirés sans risque, génère automatiquement le diff qui supprime le code et, une fois les tests passés, le transmet à un ingénieur pour approbation. Ces dernières années, le système a nettoyé plus de 16 000 feature flags et plus d'un million de lignes de code, et il tourne en continu sur plusieurs monorepos d'Uber.

L'article est signé des ingénieurs logiciel seniors d'Uber Daniel Ramos et Diego Marcilio, ainsi que de l'ingénieur logiciel Nikhil Parasaram.

Pourquoi supprimer du code est difficile

Chez Uber, les nouvelles fonctionnalités sont déployées progressivement grâce aux feature flags, et des milliers de flags coexistent sur la plateforme. Une fois le déploiement achevé, les branches conditionnelles, fonctions utilitaires, points d'appel, configurations et tests restent souvent en place. Retirer un flag oblige à intervenir à tous ces endroits en même temps, tout en garantissant que le comportement en production ne change en rien.

Le blog évoque un coût nouveau : le code mort ne fatigue pas seulement les lecteurs humains, les assistants de programmation IA passent eux aussi plus de temps et de tokens sur ces branches lorsqu'ils analysent la base de code.

Un pipeline en trois étapes

Première étape : la réécriture. L'agent reçoit un accès à la base de code et appelle, via MCP, PolyglotPiranha, le moteur de transformation de code développé par Uber et publié en open source, qui gère la simplification booléenne et l'élimination de conditions. L'argument des auteurs est direct : une erreur de simplification booléenne peut "can silently change program behavior", c'est-à-dire modifier le comportement du programme sans bruit, c'est pourquoi ils confient autant que possible ce travail à des outils déterministes.

Deuxième étape : la réparation de la CI. Les échecs simples sont traités par des correcteurs déterministes, par exemple en supprimant des valeurs par défaut inutilisées ou en réglant des erreurs de lint ; les cas complexes reviennent à l'agent, comme décider si un test doit être supprimé ou modifié. Les droits de chaque correcteur sont strictement bornés : celui des tests ne peut toucher qu'aux fichiers de test. La boucle se poursuit jusqu'à ce que la CI passe ou que le nombre d'essais soit épuisé.

Troisième étape : la vérification. Une fois la CI au vert, l'analyse statique s'exécute d'abord, puis la couche de vérification baptisée CodeCourt prend le relais : plusieurs agents relecteurs spécialisés contrôlent le diff en parallèle. Parmi les règles citées par le blog :

  • supprimer uniquement, sans ajouter ni introduire de nouveau code ;
  • le comportement observable reste inchangé ;
  • ne traiter que le flag désigné, sans supprimer au passage d'autres flags apparentés ;
  • ne laisser ni commentaire ni trace du raisonnement de l'agent.

Si une seule de ces règles n'est pas respectée, le diff est aussitôt invalidé et n'atteint jamais un humain. Selon les auteurs, plusieurs sous-agents spécialisés donnent de meilleurs résultats qu'un seul agent chargé de relire un diff entier du début à la fin.

De Piranha aux agents

AutoClean repose sur Piranha, qu'Uber a publié en open source il y a quelques années. Cet outil avait été conçu dès le départ pour supprimer les flags périmés, par réécriture statique fondée sur la correspondance de règles. PolyglotPiranha a ensuite étendu le moteur de règles à plusieurs langages. Le changement, cette fois, se situe en périphérie : le moteur de règles continue de gérer la logique booléenne, la plus sujette aux erreurs, les agents prennent en charge ce que les règles ne couvrent pas, comme réparer des tests ou compléter des points d'appel, et un autre groupe d'agents fait office de contrôle croisé.

Le blog reconnaît sans détour plusieurs modes d'échec : l'agent peut modifier du code de production uniquement pour faire passer les tests, supprimer des tests dont le comportement devait être conservé, ou s'arrêter trop tôt en laissant un nettoyage à moitié fait ; face à de nombreuses instructions, il peut aussi oublier l'une des contraintes. La CI ne détecte pas ces problèmes sémantiques, et la limitation des droits des correcteurs comme l'ajout de CodeCourt visent précisément ces cas.

L'article ne donne ni taux de réussite, ni durée moyenne, ni proportion de diffs invalidés ; l'exemple de code est en Go, et la couverture des autres langages n'est pas détaillée. D'après les auteurs, le relecteur humain n'a plus qu'une question à trancher : ce flag doit-il être supprimé ? La justesse mécanique a déjà été filtrée une première fois par les trois étapes précédentes.

Sources : blog officiel d'Uber Engineering, CocoLoop, page GitHub du projet PolyglotPiranha ; les chiffres de nettoyage suivent le cumul publié sur le blog d'Uber.