Signature : article de la rédaction

Placé sur une carte du génie logiciel, un relais IA (passerelle d’API / agrégateur) est un proxy de couche application (L7) doté d’un analyseur à machine à états et d’un ordonnanceur de contexte.

La donne a changé lorsque la complétion d’une seule ligne dans l’IDE a cédé la place aux agents en terminal, comme Claude Code CLI et OpenAI Codex CLI, et au développement piloté par les spécifications. Laissons de côté les métriques génériques de passerelle, comme la stabilité du réseau ou la tenue en charge à forte concurrence. Pour la génération de code, la question est de savoir si le proxy casse la syntaxe, interrompt la machine à états de l’agent, perd des dépendances du contexte long ou retire le protocole d’optimisation envoyé par le client de développement.

Quatre dimensions d’ingénierie couvrent cette question.

1. Intégrité de la syntaxe et des échappements

Le code généré est sensible aux caractères et à la mise en forme. Ce n’est pas de la prose ordinaire. Il comporte une indentation, des retours à la ligne, des échappements et du JSON ou du XML intégré.

1. Échappements sans perte

  • Pourquoi ça casse : un bloc de code SSE contient \n, \t, \", un \\d d’expression régulière ou une chaîne JSON. Si le relais déséchappe ou réencode le flux en réassemblant les blocs, un caractère UTF-8 multioctet peut être coupé, et le client reçoit du code qui ne s’analyse pas.
  • Comment tester : demandez du code aux échappements extrêmes : une expression régulière chargée, du Python qui embarque des chaînes JSON imbriquées, et du C++ avec pointeurs et macros.
  • Critère de réussite : écrivez le flux du relais dans un fichier et analysez-le avec un linter local (eslint, flake8) ou un analyseur AST (Babel ou Tree-sitter). Le taux d’analyse AST réussie doit être de 100 %.

2. Espaces et indentation

  • Pourquoi ça casse : Python et YAML délimitent la portée par l’indentation. Passer de \n à \r\n change un diff Git.
  • Comment tester : envoyez une refactorisation de logique profondément imbriquée, par exemple une fonction Python placée à l’intérieur de 8 niveaux de boucles.
  • Critère de réussite : les espaces et les tabulations de la sortie du relais doivent correspondre octet pour octet à la sortie amont, à 100 %. Le relais ne doit ni « embellir » ni compresser les espaces.

2. Appels d’outils et sortie structurée

Un agent de programmation ne se contente pas d’émettre du Markdown. Il appelle des outils comme read_file, edit_file et run_terminal_command.

1. Fidélité au schéma JSON

  • Pourquoi ça casse : une modification locale est un JSON structuré, avec des champs comme path, old_str et new_str. Si le relais casse cette sérialisation ou perd un champ imbriqué, l’agent échoue à l’analyse et plante.
  • Comment tester : lancez une tâche d’agent qui modifie plusieurs fichiers à la fois, par exemple une refactorisation d’interface sur 5 fichiers TypeScript, et capturez le corps de l’appel d’outil transmis.
  • Critère de réussite : l’objet d’appel d’outil transmis doit correspondre à celui de l’API officielle en amont. Aucun champ manquant, aucun changement de type (par exemple une string devenue number) et aucun JSON tronqué prématurément.

2. État multitour

  • Pourquoi ça casse : un bug difficile demande souvent 10 à 30 tours : lire un fichier, tenter une modification, lancer les tests, lire l’erreur, modifier à nouveau. Le relais doit transmettre tool_use sur role: "assistant" et tool_result sur role: "user" pour toute la chaîne.
  • Comment tester : menez un vrai débogage par agent de plus de 10 tours.
  • Critère de réussite : au tour N, le relais transmet encore chaque ID d’appel d’outil et chaque nœud d’état des N−1 tours précédents. L’historique et l’état ne doivent être ni perdus ni mélangés.

3. Contexte de code long et mise en cache des prompts

Le contexte d’une base de code moyenne ou grande atteint souvent 100 000 à 200 000 tokens.

1. Transmission du contrôle de cache

  • Pourquoi ça casse : une spécification d’architecture et le code de base partagé restent fixes. L’agent les marque avec cache_control pour que le service du modèle puisse réutiliser le cache KV. Si le relais retire ce marqueur, la moindre modification d’une ligne relance le préremplissage de centaines de milliers de tokens.
  • Comment tester : envoyez à plusieurs reprises un contexte d’ingénierie de 100 000 tokens avec cache_control.
  • Critère de réussite :
  • Côté requête, le corps envoyé en amont contient toujours cache_control.
  • Côté réponse, usage renvoie cache_read_input_tokens.

2. Une aiguille dans une base de code

  • Pourquoi ça casse : pour réduire ses coûts, un relais peut découper le prompt par RAG, le compresser ou substituer un modèle plus petit, et la vision qu’a le modèle du dépôt se rétrécit.
  • Comment tester : dans un dépôt de 150 000 tokens, cachez une définition d’interface au début du fichier A et le site d’appel à la fin du fichier B, remplissez le milieu de code sans rapport, puis demandez comment modifier l’interface.
  • Critère de réussite : comparez la modification obtenue via le relais avec celle d’un appel direct à l’API officielle. Si le contexte coupé par le relais fait manquer une variable ou un type partagé entre fichiers, le contexte a été endommagé.

4. Sortie complète et protection des instructions

Le mode d’échec typique : un module de 500 lignes qui s’arrête à la ligne 300.

1. Horizon de sortie maximal

  • Pourquoi ça casse : une refactorisation d’un seul fichier peut exiger 4 000, 8 000, voire 16 000 tokens de code en une seule réponse. Un tampon de proxy trop petit ou un délai d’expiration trop court coupe le fichier en deux.
  • Comment tester : demandez un long module sans remplissage, par exemple un parseur comportant des centaines d’énumérations et de conversions.
  • Critère de réussite : le relais doit pouvoir transporter le max_tokens maximal du modèle. Le finish_reason final doit être "stop" ou "length". Un EOF prématuré est un échec.

2. Intégrité du prompt système

  • Pourquoi ça casse : un agent de programmation place des règles strictes dans le prompt système, comme le mode strict de TypeScript ou une JSDoc sur chaque fonction. Certains relais injectent leur propre prompt global ou rognent le prompt système.
  • Comment tester : envoyez un prompt système contenant une contrainte de style de code reconnaissable, et demandez du code.
  • Critère de réussite : le code respecte cette contrainte, et une capture de paquets montre que le prompt système n’a pas été modifié d’un seul octet.

Grille de vérification

DimensionCe qu’il faut testerCritère de réussite
Caractères et syntaxeÉchappements, indentation, retours à la ligneL’analyse AST / linter locale réussit, correspondance à 100 %
Chaîne d’outils de l’agentForme des appels d’outils et état multitourZéro erreur d’analyse JSON, et une chaîne d’états d’outils de 10 tours ou plus
Contexte et cacheTransmission du cache de prompt et contexte réelcache_control n’est pas retiré, et une base de code de 150 000 tokens conserve les dépendances entre fichiers
Génération complèteLimite de sortie longue et protection du prompt systèmeAu moins 8 000 tokens de code continu, et un prompt système identique octet pour octet