Guillaume Duvernay

La plupart des agents IA ne devraient pas être des agents

agentsn8nAI efficiencyrouting

Lorsque les agents sont arrivés dans n8n, j’en ai créé beaucoup. On glisse un nœud d’agent, on y rattache trois outils, et il détermine lequel appeler. On avait l’impression que tout était devenu simple.

Au cours des mois suivants, je les ai retirés pour la plupart. Dans les workflows qui devaient passer à l’échelle et tourner réellement en production, je n’ai plus qu’environ un cinquième des agents que j’avais.

Non pas parce que les agents sont mauvais. Mais parce que pour la majorité de mes tâches, l’agent décidait à l’exécution de choses que je connaissais déjà à la conception, et me facturait ce privilège à chaque interaction.

Le schéma que je prends pour exemple

Un chatbot de support. Un déclencheur de chat, un agent basé sur un grand modèle, et un outil: une requête HTTP vers un point de terminaison de récupération qui répond aux questions à partir de mes documents. Quelqu’un pose une question sur le produit, l’agent appelle l’outil, lit le résultat et rédige la réponse.

Quatre nœuds. C’est vraiment rapide à construire, c’est d’ailleurs pour cela que cette structure est omniprésente.

Un simple bonjour et cela vous coûte un modèle de pointe

Envoyez “bonjour” à cet agent. Vous obtenez une réponse amicale en environ 1,3 seconde, rédigée par l’un des plus grands modèles disponibles.

Aucun outil n’a été appelé. Rien n’a été récupéré. L’intégralité du prompt système a été envoyée en tokens d’entrée, y compris chaque ligne décrivant des outils qui n’ont jamais été utilisés.

Mon prompt était ici léger. Avec cinq outils attachés et l’ordre d’appel détaillé, c’est la ligne du milieu qui représente la majeure partie de la facture.

La salutation est le cas le plus simple à observer, mais elle n’est pas rare. Sur un chatbot, une part importante des messages ne nécessite ni récupération ni recherche d’informations.

La même chose, mais explicitée

Voici le remplacement. Il y a plus de nœuds, et chacun d’eux représente une décision que j’ai prise une seule fois, plutôt qu’une décision qu’un modèle prend à chaque message.

Trois modèles sur le canevas, chacun dimensionné pour son étape. Le grand ne s’exécute que sur un seul nœud, et uniquement pour les messages qui l’atteignent.

Router d’abord, avec un modèle qui ne coûte rien

Le seul travail du classificateur de texte est de décider quel chemin le message doit prendre. Deux catégories, chacune avec une description:

  • Aucune récupération de connaissances nécessaire. Salutations, confirmations, discussions informelles. Tout ce qui peut être répondu sans consultation externe.
  • Récupération de connaissances nécessaire. Le message nécessite des informations issues des documents avant de pouvoir être traité.

La classification est une tâche légère et un petit modèle s’en sort très bien. C’est assez rapide pour que l’étape soit presque invisible dans la latence totale, et assez peu coûteux pour que je n’y pense plus.

Le chemin économique consiste en une chaîne LLM basique sur ce même modèle minuscule avec un prompt système court. Un « Salut » revient maintenant en environ deux secondes, avec un résultat identique, sur un modèle dont le coût par token est une fraction de celui qu’il remplace.

Un seul nœud de modèle alimente à la fois le routeur et la réponse simple. Ce sont des tâches différentes, mais d’une complexité similaire. Avoir un seul endroit pour changer le modèle signifie que j’essaie occasionnellement d’en tester un autre, au lieu de modifier deux nœuds et d’en oublier le second.

Configurer le déclencheur pour répondre depuis un nœud

Un petit détail qui bloque tout le design si on l’oublie. Par défaut, un déclencheur de chat répond à partir du dernier nœud, or ce workflow possède deux chemins qui doivent tous deux pouvoir répondre.

Réglez le mode de réponse du déclencheur sur « répondre depuis un nœud », puis placez un nœud Respond to Chat là où les branches se rejoignent. Sans cela, il est impossible d’avoir un chemin économique et un chemin coûteux qui répondent tous les deux, ce qui est tout l’intérêt du routage.

Le chemin de récupération, en trois nœuds

Regardez ce que l’agent a fait pour une question réelle. Le grand modèle a été sollicité, a pris 600 ms et a décidé d’appeler l’outil. Bonne décision. Mais ce qu’il a produit avec toute cette intelligence est une courte chaîne de requête, grossièrement une version nettoyée de ce que l’utilisateur vient de taper. Et pour l’écrire, l’intégralité du prompt système a été renvoyée.

Seul le dernier bénéficie du modèle coûteux, alors que dans une structure d’agent, les trois s’exécutent dessus.

Le chemin se compose donc de trois nœuds plutôt que d’un seul agent.

Prepare retrieval query est une chaîne LLM basique sur un mini modèle. Son prompt système : à partir du message de l’utilisateur, formuler la requête courte et concise à envoyer à l’outil de récupération de connaissances, et l’afficher directement sous forme de question. Dans mes tests, le petit modèle a écrit la même requête que le grand.

RAG via Lookio est une simple requête HTTP. La requête va dans le corps, l’ID de l’assistant et le mode sont des valeurs fixes que j’ai choisies plutôt que des paramètres sur lesquels un modèle pourrait dériver. La plupart des outils que vous attachez à un agent sont des API, et la plateforme vous fournit généralement le nœud prêt à être collé.

Write the final response reçoit le message original et le contenu récupéré, étiquetés, puis rédige la réponse. Celui-ci reste sur le grand modèle, car c’est dans la formulation de la réponse finale que la qualité s’exprime.

La mémoire est désormais à votre charge

C’est la partie que l’agent gérait pour vous, et celle que vous devez rétablir.

Un nœud d’agent prend un sous-nœud de mémoire et le gère. Si on divise l’agent en étapes, plus rien ne le fait : la conversation est donc chargée une fois en haut et stockée une fois en bas.

Plus de câblage qu’un sous-nœud de mémoire, pour le même tampon sous-jacent. En échange, vous voyez, étape par étape, exactement quelle quantité d\'historique a été fournie.

C’est plus de travail. C’est aussi le moment où l’on s’aperçoit qu’un agent injectait toute la conversation dans chaque tour, alors qu’une étape de réécriture de requête n’a besoin que des deux derniers messages plutôt que des vingt derniers.

Ce que vous y gagnez

La prédictibilité est le critère que j’aurais classé dernier il y a un an, et que je classe premier aujourd’hui.

La troisième ligne est la plus importante pour moi. Un agent qui ignore un outil pour répondre avec ses propres connaissances est une erreur impossible à reproduire ou à tester. Un workflow ne peut pas faire ça. Le nœud est là, il s’exécute.

Quand j’utilise encore un agent

Quand je ne connais réellement pas l’ordre des étapes. Pour de la recherche ouverte, où la seconde requête dépend des résultats de la première. Bref, dès que le nombre d’étapes n’est pas connu à l’avance.

C’est le test que j’utilise désormais : puis-je dessiner ce processus sur papier avant qu’il ne s’exécute ? Si oui, utiliser un agent revient à payer un modèle pour qu’il redécouvre mon dessin à chaque requête.

La même question, un niveau au-dessus

C’est cette habitude qui se transfère. Quand j’utilise Claude Code ou Codex, beaucoup de mes actions ressemblent à ce bot de support, et les parties coûteuses sont les mêmes : tout le contexte est renvoyé pour une étape qui n’en aurait besoin que d’une fraction, ou un modèle redécouvre quelque chose que je savais déjà.

Savoir combien coûte l’appel d’un outil, parce qu’on l’a un jour configuré à la main en surveillant le nombre de tokens, permet de voir ce qui se passe à l’intérieur d’une interface qui ne montre presque rien.

Ouvrez vos propres agents et analysez les exécutions. Pour chacune, demandez-vous si vous auriez pu dessiner les étapes vous-même avant l’exécution. Pour la plupart des miens, c’était possible.

Sources