Accueil / Articles

Pourquoi le monorepo modulaire convient aux agents de codage : voir tout, toucher peu

Les agents aveugles de type Polyrepos et les monorepos non structurés les submergent. Un contexte ouvert, une encapsulation et un véritable graphe de dépendances permettent au monorepo modulaire de fonctionner avec des agents.

Éditeur : REACTAPP.TOP7 min de lecture1695 mots

Sources: The Shine of the Modular Monorepo in the Agentic Era

Un vieux débat avec de nouveaux enjeux

Pendant des années, les ingénieurs se sont divisés en deux groupes. L’un conserve tout le code dans un seul répertoire, tandis que l’autre attribue à chaque composant son propre espace de stockage, avec de nombreux compromis en entreprenant. Personne n’a raison à 100 %, et ceux qui prétendent le contraire extrapolent généralement à partir d’un seul projet. Si l’on demande si un monorepo ou un polyrepo est préférable, la réponse honnête est « cela dépend » : de la taille du système, du degré de couplage de ses composants, des membres de l’équipe et de la fréquence de publication des mises à jour. Quelques services peu liés entre eux méritent d’être placés dans des répertoires séparés. En revanche, un produit fortement intégré autour de contrats partagés indique plutôt la direction opposée.

Les agents de codage ont exacerbé ce problème. Lorsqu’on leur confie une tâche impliquant un frontend, une bibliothèque partagée et un contrat backend, la structure du répertoire cesse d’être une question de goût. Ses conséquences se manifestent dans la qualité du code, dans la fréquence à laquelle l’agent doit deviner, ainsi que dans son niveau de désorientation. Ce cas est présenté à partir d’une configuration TypeScript NX couvrant six plateformes. Il s’agit d’un point de vue déclaré, qui ne correspondra pas à celui de tout le monde ; il faut donc le considérer comme une opinion ferme visant à lancer un débat. Quatre mots résument cette idée : voir tout, toucher peu.

Le premier obstacle : les barrières que l’agent ne peut pas franchir

Imaginez le monde divisé dans lequel évoluent la plupart des équipes : un répertoire frontend, deux répertoires de services backend, un paquet shared-types dans un registre privé, et un répertoire d’infrastructure. Ces limites ont du sens et chaque composant a un responsable.

Supposons qu’un agent du dépôt frontend soit chargé de modifier la manière dont il appelle une extrémité de service appartenant à un dépôt qu’il ne peut pas ouvrir. Sans un gestionnaire de lecture, il devine à quoi ressemble la réponse. Un modèle de type obsolète ou un exemple de test isolé deviennent ses seules preuves. Le résultat compile sur la machine locale, mais est probablement incorrect une fois intégré. Chaque limite entre dépôts constitue un mur que l’agent ne peut pas franchir, et il comble chacune d’elles par une supposition crédible. Ce qui protège les humains laisse les agents assoiffés d’informations.

Les équipes comblent cette lacune de trois manières principales, et certaines des solutions sont efficaces :

  • Git submodules placent les dépôts dépendants à l’intérieur du dépôt principal, ce qui donne l’impression d’un arborescence unifiée. L’agent peut ainsi lire tout le contenu, mais au prix habituel : les commits verrouillés évoluent, maintenir les choses à jour devient une tâche fastidieuse, et le flux de travail ne satisfait personne.
  • Les espaces de travail IDE à plusieurs racines permettent à Cursor ou VS Code d’indexer plusieurs dépôts ensemble, ce qui est utile lorsque l’objectif est simplement de lire du contenu dans ces dépôts. Cependant, cette organisation relève de la machine et non du projet, et l’agent se retrouve avec une multitude de fichiers sans graphe de dépendances. Il sait que du code existe, mais il ne sait pas ce qui dépend de quoi.
  • Les monorepos synthétiques constituent le choix sérieux. Polygraph de NX, par exemple, regroupe des dépôts séparés en un seul graphe de dépendances tout en laissant le code à son emplacement initial. Un agent de coordination consulte ce graphe pour déterminer quels dépôts sont affectés par une modification, lance un agent dans chacun d’eux et ouvre les demandes de fusion correspondantes tout en suivant les processus CI partout. Cela offre le comportement le plus proche d’un monorepo au sein d’une structure polyrepo.

On doit du respect à l’approche synthétique, mais regardez ce qu’elle fait réellement : elle crée des tunnels à travers des murs qui restent debout. Les ingénieurs déploient beaucoup d’efforts au niveau des outils pour recréer la visibilité que fournit naturellement un monorepo sans aucun coût. Et lorsque aucun de ces outils n’existe, c’est l’humain qui agit comme tunnel, lisant le service B, transmettant les informations à l’agent du service A, collant des définitions de types dans le chat, et servant de messager entre des sessions scellées.

Le deuxième obstacle : la pile sans structure

Donc tout est regroupé dans un seul repo, et le problème est résolu ? Pas tout à fait. Un monorepo sans structure interne échoue encore plus gravement, car il est tentant. Tout est visible, ce qui semble suffisant. En réalité, il s’agit d’un seul et énorme répertoire d’applications, avec des bibliothèques qui s’importent mutuellement de toutes les manières possibles, sans limites imposées, et sans notion claire de savoir à qui appartient chaque partie.

Ici, un contexte trop large est préjudiciable. Un agent qui voit tout ne reçoit aucun indice sur ce qu’il convient d’ignorer. La fenêtre se remplit de code situé à proximité sur le disque mais sans rapport avec la tâche ; une seule modification a des répercussions sur des importations que personne n’a suivies, et la question essentielle — en quoi ce changement a-t-il un impact ? — reçoit pour réponse « possiblement tout ». La visibilité sans structure n’est que du bruit et non un contexte véritable, d’où le fait que stocker tout le code dans un seul répertoire ne soit pas la solution idéale.

Les trois piliers d’un monorepo modulaire

Un monorepo modulaire réussit en accomplissant trois choses en même temps. En négliger ne serait-ce qu’une seule entraîne des conséquences désastreuses.

Contexte ouvert. Un seul arbre contient tout, et l’agent peut le parcourir : interface utilisateur, partie serveur, bibliothèques partagées, tests ainsi que les contrats de type qui les relient, en une seule session. Pas de barrières, pas de devinette, pas de messager. Le plan stratégique de NX met l’accent sur ce pilier, et à juste titre, car un agent qui lit en une seule passe le producteur d’un contrat ainsi que tous ses consommateurs pourra effectuer de meilleures modifications.

Encapsulation. Les bibliothèques sont délimitées et exposent des interfaces publiques explicites, de sorte que l’agent n’a pas besoin de garder l’ensemble du système en tête. Il travaille sur une partie seulement. C’est précisément cet équilibre qui permet à la vision globale et à l’intervention limitée de coexister, sans lequel le contexte ouvert se transforme en un problème majeur.

Un véritable graphe de dépendances, avec des outils pour l’explorer. C’est le pilier que les gens sous-estiment. NX traite ce graphe comme un artefact de première classe qui peut être interrogé. Au lieu de chercher manuellement dans l’espoir d’en déduire la structure, l’agent peut exécuter nx show projects, ouvrir nx graph, demander quels éléments sont affectés par une modification, et recevoir une réponse précise que la machine peut interpréter. La carte se trouve dans le dépôt, et non dans une wiki ou dans la mémoire d’un ingénieur senior, et elle est exécutable.

Tout cela permet de concrétiser la thèse en quatre mots : voir tout est le premier pilier, toucher peu en est le deuxième, et savoir quels éléments toucher en est le troisième, le lien qui permet de combiner les deux premiers en toute sécurité.

Acquérir et vérifier

Les agents fonctionnent en boucle : ils récupèrent du contexte, modifient le code, vérifient les changements, puis recommencent. Toute mesure d’entretien du monorepo sert à l’un de deux objectifs : obtenir du contexte à moindre coût ou vérifier une action à moindre coût.

  • Types forts (acquisition). Une bibliothèque de types partagée fournit à l’agent un contrat qu’il peut lire et que le compilateur peut faire respecter. Cela résout le problème des agents aveugles évoqué dans le premier chapitre, car aucune forme de réponse n’a besoin d’être devinée lorsqu’elle est écrite et vérifiée. Les types servent également de documentation qui ne devient jamais obsolète.
  • Règles relatives aux erreurs de lint et aux limites des modules (vérifier). Grâce à @nx/enforce-module-boundaries de NX, une importation interdite provoque une erreur au lieu d’être ignorée, et cette erreur est renvoyée dans la boucle propre de l’agent en tant que feedback. Si l’agent intègre une bibliothèque UI dans la couche de données, la règle le bloque, et l’architecture est déduite de cet échec sans qu’aucun utilisateur ait besoin de la définir manuellement.
  • TDD et tests concernés (vérifier). nx affected permet de réaliser des vérifications rapides et fiables. Après avoir modifié un élément, l’agent exécute uniquement les tests qui suivent et obtient immédiatement un résultat positif ou négatif, sans avoir à attendre l’exécution de l’ensemble des tests ni à se demander si la modification a fonctionné. Ces boucles courtes font que le travail avec l’agent ressemble à de la construction plutôt qu’à de la surveillance constante.
  • Compétences et AGENTS.md ou CLAUDE.md (à acquérir). L’exécution de npx nx configure-ai-agents dans un espace de travail installe un serveur MCP, les compétences des agents ainsi que les fichiers de convention. Les compétences sont chargées sur demande et non toutes en même temps dans la requête, de sorte que la manière de structurer une bibliothèque est apprise précisément au moment où on la structure. Elles orientent également l’agent vers la consultation du graphe plutôt que vers une recherche brute, ce qui renvoie au troisième pilier.
  • Guides atomiques par module (à acquérir). Chaque bibliothèque peut contenir un bref README ou AGENTS.md, fournissant un contexte local juste là où l’agent vient d’arriver. L’accès à cette bibliothèque fait apparaître son contrat et ses conventions sans entraîner le reste de l’arborescence.

En énumérant les étapes, on obtient : acquérir, vérifier, vérifier, acquérir, acquérir, bien que l’ordre soit secondaire. Chaque fonctionnalité correspond à l’une de ces deux tâches. Un monorepo modulaire n’est pas une fonction unique destinée aux agents, mais plutôt de nombreuses petites fonctionnalités qui permettent de maintenir un cycle rapide et efficace.

Les arguments contre

Personne n’est bénéficiaire d’une présentation commerciale, il convient donc d’examiner les contre-arguments. Les fenêtres de contexte continuent de s’élargir, et les espaces de travail à plusieurs racines ainsi que les outils de type synthetic-monorepo réduisent progressivement l’écart. Un sceptique pourrait qualifier l’avantage du monorepo d’artéfact temporaire dû aux limites actuelles, qui disparaîtrait avec une fenêtre suffisamment grande et des outils de gestion inter-repo adéquats. La version plus précise ne concerne pas les fenêtres de contexte. Le polygraphie montre qu’un graphe de dépendances peut être reconstruit au sein d’un polyrepo, ce qui signifie que la structure souvent attribuée aux monorepos ne leur appartient pas exclusivement.

Chaque version se trompe quant à l’origine du bénéfice. Il ne s’agit jamais de lire plus de texte brut ; il s’agit de la structure. Une fenêtre plus grande permet à un agent perdu de se retrouver dans des détails plus fins sans qu’il ne soit possible d’identifier la bonne porte. Un graphe synthétique est également une structure, ce qui explique pourquoi il fonctionne, mais cette structure est reconstruite et maintenue en fonction de la segmentation, et non déterminée par la disposition. Le contexte brut évolue avec le modèle, tandis que la structure progresse grâce à la discipline, et c’est la structure qui transforme la vision de tout comme d’un danger en un atout. À mesure que les fenêtres s’agrandissent, un monorepo dépourvu de modules devient plus risqué, car les possibilités s’élargissent. C’est l’adjectif qui porte le fardeau.

Ce que l’ère des agents a révélé

Les graphes de projet, les limites des modules et les types partagés semblaient autrefois être des facilités destinées à une équipe humaine. L’ère des agents a révélé ce qu’ils avaient toujours été : une interface pour des collaborateurs non humains. L’architecture conçue pour la pensée humaine s’est avérée être un ingénierie de contexte au niveau du répertoire, des années avant même que le terme n’existe. Cela explique pourquoi d’autres approches que les monorepos reviennent en vogue. Le monorepo modulaire a silencieusement répondu à une question que personne n’avait encore posée : voir tout, toucher peu, et les agents se sont contentés de le rendre évident.