Accueil / Articles

Remettre en question l’Agent Stack : les bases de données vectorielles, les hypergraphes et les tâches de codage

Trois cas où une pile d’agents plus importante a manqué le véritable goulot d’étranglement : la mémoire des agents basée sur des fichiers a surpassé un stockage vectoriel, un hypergraph RAG, ainsi que le travail de niveau senior.

Éditeur : REACTAPP.TOP12 min de lecture2733 mots

Sources: The Case Against Your Own Agent Stack: What Contrarians Get Right This Year

La tendance à en ajouter toujours plus

En parcourant les articles de cette année sur les agents IA, une chose ressort clairement par-dessus toutes les affirmations individuelles : les conseils conseillent presque toujours d’ajouter quelque chose. Une couche de mémoire. Un graphe. Un cadre d’orchestration. Un pipeline de récupération avec trois étapes de réclassification. Plus d’agents pour surveiller ceux que l’on possède déjà. Au fond, il y a la croyance tacite que la complexité signifie progrès, et que tout système qui ne fait pas mieux que celui de il y a six mois est en retard.

Une part considérable de cette pile technologique a probablement été développée et défendue par quiconque lit ceci. Il est donc utile de s’arrêter un instant sur un petit ensemble d’exemples qui avancent l’inverse : l’élément sophistiqué que vous avez ajouté n’a probablement pas mérité sa place. La plupart des écrits technologiques contraires à la tendance ne sont que du marketing inversé, tout aussi affirmés mais tout aussi dépourvus de preuves. Ces trois cas sont différents car chacun repose sur quelque chose de vérifiable, qu’il s’agisse d’un résultat de benchmark, d’une démonstration structurelle ou d’un récit simple de la journée de travail de quelqu’un. Ce standard s’applique ci-dessous, ainsi qu’à toute pile technologique, y compris la vôtre.

Chacun de ces cas représente un moment où le domaine a cherché plus de structure, bien que le véritable problème se trouvât ailleurs, de manière moins évidente.

Premier cas : mémoire d’agent et stockages vectoriels

La mise en mémoire des agents dans un stockage vectoriel prend généralement environ une demi-minute. Quelqu’un a souligné que les agents devraient conserver les données entre les sessions, ce qui a conduit à la méthode consistant à intégrer les données, à les stocker et à les récupérer par similarité. Tous les tutoriels fonctionnent de cette manière, ce qui en a fait la norme, sans que personne n’ait testé cette approche par rapport à des solutions plus simples.

Un article paru cette année a effectué ce test. Sur le benchmark LoCoMo, une solution de base composée d’un dossier de fichiers de texte brut et de grep a obtenu de meilleurs résultats que plusieurs produits spécialisés financés à cet effet. Cette comparaison n’a pas été organisée de manière contrôlée. Les systèmes utilisant des intégrations vectorielles, une recherche par similarité et parfois une mémoire graphique se sont retrouvés inférieurs à une configuration qui nécessite une après-midi entière pour être mise en place.

Après y avoir réfléchi, l’explication semble claire. La recherche par similarité trouve des résultats, mais elle ne raisonne pas. Elle excelle à récupérer du texte dont le sens est proche d’une requête. En revanche, elle est médiocre pour gérer les besoins en mémoire, comme reconnaître qu’un fait datant de trois semaines a été remplacé par un fait d’hier, ou que deux souvenirs enregistrés entrent en conflit et qu’un seul doit prévaloir. Un index ne possède ni notion de temps ni capacité de correction, il renvoie donc les vecteurs les plus proches et laisse au modèle le soin de constater que deux des cinq meilleurs résultats se contredisent.

Un deuxième problème concerne la familiarité et non la capacité. Les modèles ont été entraînés sur d’énormes quantités de matériel concernant le travail avec les fichiers : ouverture, recherche, modification, affichage des dossiers, suivi des importations. Les fichiers sont proches du matériel de base de leurs données d’entraînement, et une boucle combinant grep et lecture de fichiers en profite directement. En revanche, une API de requête vectorielle fournie par un fournisseur est quelque chose que le modèle doit apprendre à utiliser efficacement au sein de sa propre fenêtre de contexte, sans avoir été exposé à elle auparavant. Cela consiste à remplacer une compétence déjà acquise par une autre qu’il doit acquérir en cours de tâche, ce qui ajoute des retards liés aux embeddings et à la récupération des informations.

Un guide de décision comparant les deux options côte à côte se présente comme suit.

WHEN A FILESYSTEM + GREP BASELINE IS ENOUGH        WHEN YOU ACTUALLY NEED A VECTOR STORE
------------------------------------------------   ------------------------------------------------
Single-agent or small-team memory                  Retrieval across a corpus too large to
                                                    fit or scan in context at all
Facts that change over time and need               Cross-document semantic search where
correction, not just accumulation                  keyword overlap is genuinely weak
Memory the model itself writes,                    Centralized memory shared by many agents
manages, and re-reads in its own loop               that needs access control and auditing
Debuggable state, plain text you can                Multi-hop or relational reasoning across
open, diff, and edit by hand                        thousands of entities where similarity
                                                     search is doing real narrowing work

À quoi ressemble la boucle basée sur les fichiers

« Il suffit d’utiliser des fichiers » semble vague tant que ce n’est pas du code. Cette version ne nécessite aucun service hébergé.

import os
import subprocess
from datetime import datetime
MEMORY_DIR = "agent_memory"
def write_memory(topic: str, content: str) -> str:
    os.makedirs(MEMORY_DIR, exist_ok=True)
    path = os.path.join(MEMORY_DIR, f"{topic}.md")
    timestamp = datetime.utcnow().isoformat()
    with open(path, "a", encoding="utf-8") as f:
        f.write(f"\n## {timestamp}\n{content}\n")
    return path
def recall(query: str) -> str:
    # ripgrep if you have it, grep -r works fine too
    result = subprocess.run(
        ["rg", "-i", "-C", "2", query, MEMORY_DIR],
        capture_output=True, text=True
    )
    return result.stdout or "no matches"
def list_topics() -> list[str]:
    if not os.path.isdir(MEMORY_DIR):
        return []
    return [f[:-3] for f in os.listdir(MEMORY_DIR) if f.endswith(".md")]

Donnez au modèle ces trois fonctions en tant qu’outils et laissez-le décider quand enregistrer, quand rechercher et quand charger un fichier complet sur un sujet court. Le résultat est une mémoire sans coûts d’incorporation, sans base de données à héberger ou à payer, et avec un état que l’on peut ouvrir dans n’importe quel éditeur en cas de problème. Lorsque cette approche finit par échouer, la raison sera concrète, comme un corpus trop volumineux pour être parcouru rapidement ou une question à plusieurs étapes que la recherche par mots-clés ne peut pas résoudre. Cela justifie l’utilisation d’un stockage vectoriel bien mieux qu’une simple copie d’un tutoriel.

Rien dans tout cela ne dit que les bases de données vectorielles ne devraient pas exister. Cela signifie simplement de ne pas en recourir avant d’avoir évalué la solution de base. Essayez d’abord le contexte complet, le système de fichiers ainsi que grep, et n’adoptez un produit de mémoire payant que s’il surpasse cette solution de base suffisamment pour couvrir son coût et la perte de capacité de débogage. La plupart des mémoires d’agent n’ont jamais besoin d’atteindre ce niveau.

Cas deux : les hypergraphes dans RAG

L’an dernier, la solution par défaut était la base de données vectorielle. Cette année, c’est le RAG basé sur les graphes, et les hypergraphes entrent en jeu lorsque l’équipe estime qu’un graphique de connaissances ordinaire ne suffit pas pour exprimer l’ensemble des informations. Ce cas semble logique. Un bord ordinaire relie deux nœuds, mais de nombreux faits impliquent plusieurs acteurs. Prenons l’approbation d’une dépense : une personne approuve le rapport d’un collègue, au nom d’une équipe financière, et cela est imputé sur le budget marketing trimestriel. Il s’agit donc de cinq parties impliquées dans un seul fait. En les regroupant en paires, on perd l’idée d’un événement atomique unique ou bien on doit diviser ce fait en plusieurs bords binaires que les requêtes doivent ensuite reconstituer. Un hyperbord, quant à lui, peut relier n’importe quel nombre de nœuds en même temps, ce qui semble être le moyen le plus fiable pour stocker de tels faits ; les équipes développent donc des systèmes RAG à base d’hypergraphes dans l’espoir que cette fiabilité améliore les résultats de recherche.

Un autre article a vérifié cette hypothèse en se basant sur le code fonctionnel d’un papier sur HyperGraph RAG plutôt que sur son résumé, et a découvert quelque chose de presque comique. HyperGraphRAG, conçu pour favoriser les hyperarêtes natives, stocke tout dans une base de données de graphes ordinaire utilisant des arêtes binaires. Ses propres auteurs démontrent que transformer chaque hyperarête en quelques arêtes binaires autour d’un nœud représentant l’événement ne entraîne aucune perte d’information, de sorte que chaque forme peut être reconstituée avec précision à partir de l’autre.

Ce détail résume l’ensemble de l’argumentation. Supposons qu’un hyperarête natif et un cluster de bornes binaires possèdent exactement la même structure d’incidence, et que l’un puisse générer l’autre sans effort. Alors le choix entre eux n’a aucune conséquence sur le modélisation et revient simplement à choisir un format de stockage. Un commentateur a résumé brièvement les mathématiques : les deux formes correspondent à la même structure d’incidence, et la largeur de l’hyperarbre ne varie que d’une constante lorsque l’arity est bornée. C’est la largeur de l’hyperarbre qui détermine le coût d’une requête. Le nombre d’étapes de saut ne le fait pas, tout comme le nombre de participants regroupés dans une seule borne. En convertissant votre représentation, en décalant cette valeur d’une constante, et en limitant le nombre de participants pour chaque fait (cinq personnes approuvant une dépense, et non cinq cents), la difficulté des requêtes reste identique.

Pourquoi cela prend les gens au dépourvu

C’est une erreur facile à commettre. Le nombre d’étapes semble naturel, car plus il y a de nœuds entre la question et la réponse, plus la requête semble complexe. La largeur de l’hyperarbre est bien moins intuitive : elle relève de la théorie de la satisfaction de contraintes et de la complexité des requêtes, et diffère du nombre d’étapes de manières que l’on ne perçoit qu’en y regardant de plus près. On peut ajouter une structure qui réduit le nombre d’étapes pour une requête d’exemple sans affecter, ou au contraire nuire légèrement, à la classe de complexité à laquelle appartient cette requête. Les exemples illustrés dans un article peuvent paraître impressionnants sans pour autant révéler quoi que ce soit sur la mesure qui gouverne le cas général.

Avant de choisir entre un graphe simple, un graphe réifié ou un stockage d’hypergraphes natif, cette comparaison est utile.

REPRESENTATION          WHAT IT ADDS                     WHAT IT ACTUALLY CHANGES
---------------------   -------------------------------  --------------------------------
Plain binary graph       Simplest to build and query      Baseline; loses atomicity of
                         with standard graph tooling      multi-participant facts
Reified binary graph     Recovers atomicity via an        Same incidence structure as a
(event node + roles)     explicit "event" node             hyperedge; hypertree width
                                                            shifts by a constant only
Native hypergraph        Hyperedges as first-class         No reduction in query
store                    objects, arguably cleaner          complexity class over a
                         to write against                   reified graph; new storage
                                                             engine to run and maintain

Cela ne rend pas la structure de graphe inutile pour RAG. La récupération relationnelle à plusieurs étapes bénéficie effectivement des graphes par rapport à la recherche vectorielle plate, et personne ne contredit cela. L’argument porte plutôt sur le saut supplémentaire du graphe vers l’hypergraphe. Une fois la démonstration avancée, ce saut permet d’obtenir des modèles de données plus élégants, ajoute un nouveau type d’infrastructure à gérer, sans affecter le critère qui détermine si les requêtes sont rapides ou lentes. Si la récupération est insuffisante, le remède, étayé par des preuves, consiste généralement en une meilleure construction du graphe ou en une stratégie de récupération plus intelligente sur le graphe déjà créé, et non en un type d’arête plus exotique.

Cas trois : en quoi consiste réellement le travail d’un ingénieur senior

Les deux cas précédents portent sur l’architecture de récupération. Le dernier cas est différent, car il ne s’agit pas d’un choix d’outil, mais de la question de la composition du travail d’ingénierie senior.

Un chef technique dirigeant une équipe de cinq personnes au sein d’une entreprise comptant plus de mille employés a écrit que l’IA ne pouvait pas assumer 95 % de son travail. Il commence par ce qui ressemble à une concession : l’écriture de code occupe la part la plus petite de son temps, de loin. Son équipe fonctionne selon le principe « vous le créez, vous le gérez », ce qui signifie que ce sont ses propres ingénieurs qui doivent assurer la surveillance de ses systèmes, et non un groupe d’opérations distinct qui pourrait considérer la production comme une affaire qui ne le concerne pas. Sa journée commence à 8h30 par l’examen des demandes de fusion de code. Le code qui arrive, en grande partie tapé par des agents d’IA, est clairement de meilleure qualité que celui qu’il avait examiné deux ans auparavant. Il ne remet pas en question le fait que l’IA puisse écrire de bon code ; il l’accepte pleinement, avant de souligner à quel point cela modifie peu le travail qu’il effectue réellement.

Cela remet en question une prémisse courante dans la façon de concevoir les piles d’agents, à savoir que les capacités déterminent le rythme de l’automatisation. Selon cette logique, si un modèle génère du code correct, il n’est plus nécessaire d’intervenir humainement, et l’automatisation de la tâche correspond alors à la partie consacrée à la création du code. Le chef technique affirme que cette équation n’a jamais été vraie, et que l’IA se contente de rendre les défauts visibles. Son travail ne consistait pas principalement en écriture de code, mais plutôt en coordination : choisir ce qui doit être développé et dans quel ordre, négocier les objectifs avec des personnes aux priorités divergentes, examiner et soutenir les décisions prises par d’autres, gérer les communications urgentes, former les ingénieurs plus jeunes, et médier entre les demandes des parties prenantes et ce que le système peut soutenir en toute sécurité. Aucune de ces tâches n’est une mission d’écriture de code.

Ce pourrait être le point le plus négligé de l’année dans les débats sur les outils d’évaluation, plus que n’importe quel autre critère, car il explique pourquoi des scores de codage nettement améliorés et un travail considérablement plus facile n’ont pas évolué en même temps pour de nombreux ingénieurs seniors, même pour les utilisateurs quotidiens les plus enthousiastes. Une hausse des scores SWE-bench de quelques unités à plus de soixante-dix en quelques années représente bien une avancée significative. Cela ne se traduit cependant pas par 70 % de travail en moins, car la production de code n’a jamais représenté 70 % du travail, surtout lorsque le poste inclut des tours de garde, un plan stratégique ainsi que des demandes de fusion de code.

Une précision : le troisième point s’applique aux autres paramètres de manière moins claire que les deux premiers. Les affirmations concernant les bases de données vectorielles et les hypergraphes peuvent être vérifiées à l’aide d’un benchmark ou d’une démonstration. La répartition entre coordination et codage au cours de la semaine d’un ingénieur senior varie en fonction de la taille de l’entreprise, du niveau de maturité de l’équipe, du fait que les tâches supplémentaires soient dues à des dysfonctionnements ou à des activités essentielles, ainsi que du grade de l’individu lui-même. Une équipe de cinq personnes au sein d’une entreprise de mille employés suivant une politique de « construis et exécute » représente un type de poste qui ne correspond pas à tous les rôles d’ingénierie. La direction de la correction semble globalement correcte. Les capacités de l’agent limitent la part du codage qui peut être automatisée, et elles ne disent presque rien concernant la partie liée à la coordination, qui n’a jamais dépendu de la vitesse de frappe ou de la qualité du code.

Le schéma commun

En plaçant les trois cas côte à côte, on constate que la leçon ne porte pas spécifiquement sur les bases de données vectorielles, les hypergraphes ou les capacités d’intelligence artificielle. Elle concerne plutôt l’écart entre l’endroit où un domaine pensait que se trouvait le goulot d’étranglement et l’endroit où il se situait réellement.

CASE                WHERE COMPLEXITY WAS ADDED         WHERE THE REAL BOTTLENECK WAS
------------------  ----------------------------------  --------------------------------
Agent memory         Vector embeddings, similarity       Whether the model can use a
                     search, sometimes a graph layer      retrieval method it already
                     on top of that                        has deep fluency with
RAG structure         Native hyperedges, a new             The complexity class governing
                      storage engine, more                  query cost, which the fancier
                      elaborate graph modeling               structure barely touches
"How much of the      An assumption that model             Whether the job was ever
job gets automated"   capability alone predicts             mostly about the thing the
                       the automatable fraction              model is good at

Aucune de ces options sophistiquées n’est fausse pour avoir existé. Les bases de données vectorielles ont des utilisations réelles, les hypergraphes pourraient être utiles dans des domaines où personne n’y a encore pensé, et les agents d’IA permettent effectivement d’éliminer des tâches fastidieuses dans le travail d’ingénierie, ce que reconnaît le responsable technique. L’erreur a été de négliger la question de savoir si cette complexité supplémentaire vise le véritable goulot d’étranglement ou simplement celui pour lequel il est le plus facile de trouver une solution élaborée.

Cette habitude dépasse de loin le domaine de l’ingénierie des agents. Ajouter une couche est plus simple que de se demander si la solution de base a jamais été évaluée de manière équitable par rapport à elle. Une nouvelle abstraction est considérée comme un progrès visible auquel on peut se référer en parlant d’amélioration. Vérifier que grep fait déjà le travail, que la complexité des requêtes s’est réellement améliorée, ou que le problème qui occupe toute une semaine correspond bien à ce que l’on pensait, prend plus de temps, est plus difficile, et conduit parfois à décider d’arrêter de développer.

Une liste de contrôle avant l’ajout d’une nouvelle couche

Une courte liste à vérifier pour tout stack avant d’ajouter une nouvelle couche :

1. Have I benchmarked the boring baseline, not just assumed it loses?
   (full-context, grep, a plain graph, a human doing the coordination)
2. Does the new structure change the metric that actually governs cost
   or quality, or does it just look more sophisticated on a diagram?
3. Am I reaching for this because a benchmark or proof told me to,
   or because it's what the tutorials and the funded products default to?
4. If I strip this layer back out, what specifically breaks?
   If I can't name it precisely, I probably don't need the layer yet.
5. Am I solving the bottleneck I actually have, or the bottleneck
   that's most interesting to build a sophisticated solution for?

Rien de tout cela ne plaide en faveur d’une moindre ingénierie. Au contraire, il s’agit d’investir des efforts d’ingénierie pour identifier où se trouve le goulot d’étranglement avant de construire quelque chose de complexe en partant du principe que la réponse est déjà connue. Ces trois études n’ont pas été menées par esprit de contradiction. Elles ont effectué des vérifications peu spectaculaires, et ces vérifications étaient en désaccord avec les hypothèses initiales. Cela représente un standard bien plus élevé qu’une opinion tranchée accompagnée d’un titre accrocheur, et c’est le critère auquel tout système devrait se conformer.