La première fois que j’ai utilisé Claude Code pour refactoriser un module entier, j’ai vécu une expérience presque mystique. Je lui ai décrit ce que je voulais, je suis parti prendre un café, et quand je suis revenu j’avais une pull request avec 14 fichiers modifiés, des tests mis à jour et un message de commit correct. “C’est de la magie”, me suis-je dit.
Ce n’est pas de la magie. C’est une boucle while.
Michael Bolin, d’OpenAI, a publié récemment un article où il décortique le fonctionnement interne de Codex CLI. Et il s’avère que le secret derrière les agents de codage IA n’est pas un algorithme révolutionnaire ni un réseau de neurones mystérieux. C’est une boucle qui appelle un LLM, exécute des outils, et répète jusqu’à ce qu’il n’y ait plus rien à faire.
Ouvrons le capot.
La machine à états : 5 phases et une boucle
Tout agent de codage — Codex, Claude Code, Cursor, peu importe — exécute le même pattern fondamental. Michael Bolin le décrit comme une boucle à 5 phases :
flowchart TD
A["1. Prompt Assembly\n(assemblage du prompt)"] --> B["2. Inference\n(envoi au LLM)"]
B --> C{Tool call ?}
C -->|Oui| D["3. Tool Invocation\n(exécution de l'outil)"]
D --> E["4. Tool Response\n(retour du résultat au LLM)"]
E --> B
C -->|Non| F["5. Assistant Message\n(réponse finale)"]
F -->|Nouvel input| A
style A fill:#2d3748,stroke:#4a9eed,color:#fff
style B fill:#2d3748,stroke:#4a9eed,color:#fff
style C fill:#4a3728,stroke:#ed9a4a,color:#fff
style D fill:#2d3748,stroke:#4a9eed,color:#fff
style E fill:#2d3748,stroke:#4a9eed,color:#fff
style F fill:#283d28,stroke:#4aed5c,color:#fff
En clair :
- Prompt Assembly : on assemble un prompt gigantesque avec tout ce que l’agent doit savoir — ton message, les instructions système, les outils disponibles, les fichiers qu’il a lus, et l’historique complet de la conversation.
- Inference : ce prompt est tokenisé et envoyé au modèle. Le modèle retourne un stream d’événements : raisonnement interne, tool calls, ou texte de réponse.
- Tool Invocation : si le modèle demande à exécuter un outil (lire un fichier, lancer une commande, écrire du code), on l’exécute. Si ça échoue, l’erreur retourne au modèle.
- Tool Response Loop : le résultat de l’outil retourne au modèle comme contexte supplémentaire. Et on répète les étapes 2-4 jusqu’à ce que le modèle ne demande plus d’outils.
- Assistant Message : quand le modèle décide qu’il a terminé, il émet un message final et le cycle se ferme.
C’est tout. Pas de graphes de connaissances, ni de planificateurs symboliques, ni d’architectures sophistiquées. C’est une boucle while avec un LLM à l’intérieur.
La différence entre un bon agent et un mauvais n’est pas dans l’architecture de la boucle — qui est identique — mais dans les détails de chaque phase.
Phase 1 : L’art d’assembler un prompt
La première phase est là où tout se joue. Avant que le LLM ne voie une seule ligne de ton code, l’agent doit construire un prompt qui inclut :
flowchart LR
subgraph Prompt["Prompt Assembly"]
direction TB
SP["System Prompt\n(personnalité, règles)"]
Tools["Outils disponibles\n(Read, Write, Bash, MCP...)"]
Ctx["Fichiers / images\nlus précédemment"]
Inst["CLAUDE.md / AGENTS.md\n(instructions du repo)"]
Env["Info de l'environnement\n(OS, shell, git status)"]
Hist["Historique de la\nconversation"]
User["Message de l'utilisateur"]
end
SP --> Final["Prompt\ncomplet"]
Tools --> Final
Ctx --> Final
Inst --> Final
Env --> Final
Hist --> Final
User --> Final
style Final fill:#283d28,stroke:#4aed5c,color:#fff
Tu vois déjà une décision de conception cruciale : l’ordre compte. Le prompt se construit du plus stable au moins stable. Le system prompt va en premier (ne change jamais), puis les outils (changent rarement), puis fichiers et historique (grandissent à chaque interaction), et enfin ton dernier message.
Pourquoi cet ordre ? À cause du prompt caching. Comme le cache fonctionne par correspondance exacte de préfixe, si tu mets le contenu stable au début, tu maximises la quantité de tokens lus depuis le cache à chaque itération. Changer quelque chose au début invalide tout ce qui suit. J’ai détaillé cela dans mon article sur le prompt caching, mais l’idée clé est : l’ordre de ton prompt n’est pas cosmétique, il est économique.
Et puis il y a les fichiers CLAUDE.md et AGENTS.md. Les deux sont l’équivalent de laisser un mot au plombier avant de partir de chez toi : “la vanne d’arrêt est sous l’évier, ne touche pas au tuyau bleu”. L’agent les lit au démarrage et les injecte dans chaque prompt. C’est ton mécanisme pour lui donner du contexte sans avoir à te répéter à chaque fois.
Le problème du carré : pourquoi le contexte grandit comme une boule de neige
Voilà la claque de réalité. Chaque itération de la boucle envoie toute la conversation complète au modèle. Il n’y a pas d’état sur le serveur. Chaque requête est indépendante, stateless.
Pourquoi ? Parce qu’ainsi le fournisseur peut garantir Zero Data Retention — tes données ne persistent pas sur leurs serveurs entre les requêtes. C’est une décision de confidentialité, pas d’efficacité.
Mais ça a un coût brutal :
flowchart LR
subgraph Msg1["Itération 1"]
S1["System\n10K tok"] --> U1["User\n500 tok"]
end
subgraph Msg5["Itération 5"]
S5["System\n10K tok"] --> H5["Historique\n40K tok"] --> U5["User\n500 tok"]
end
subgraph Msg20["Itération 20"]
S20["System\n10K tok"] --> H20["Historique\n180K tok"] --> U20["User\n500 tok"]
end
style Msg1 fill:#1a2332,stroke:#4a9eed,color:#fff
style Msg5 fill:#2a2332,stroke:#9a4eed,color:#fff
style Msg20 fill:#3a1a1a,stroke:#ed4a4a,color:#fff
À l’itération 1 tu envoies 10K tokens. À la 5, tu envoies 50K. À la 20, tu envoies 190K. Chaque message renvoie tout l’historique précédent. Et comme le mécanisme de self-attention du transformer a un coût quadratique par rapport au nombre de tokens, non seulement la quantité de données envoyées croît — le coût computationnel pour les traiter croît aussi.
Autrement dit : l’itération 20 ne coûte pas 20 fois plus que la première. Elle coûte beaucoup plus.
Compaction : compresser sans perdre l’essentiel
Codex et Claude Code ont tous deux une solution au problème de la croissance incontrôlée du contexte : compaction (ou compression automatique).
Quand l’historique s’approche de la limite de la fenêtre de contexte, l’agent fait quelque chose d’astucieux : il envoie tout l’historique à un endpoint spécialisé qui génère une représentation compressée. Au lieu de 180K tokens de conversation, tu obtiens peut-être 20K qui capturent les décisions prises, les fichiers modifiés et l’état actuel de la tâche.
flowchart TD
Full["Historique complet\n180K tokens"] --> Check{Proche de la limite ?}
Check -->|Non| Continue["Continuer normalement"]
Check -->|Oui| Compact["Endpoint de compaction"]
Compact --> Summary["Résumé compressé\n~20K tokens"]
Summary --> NewCtx["Nouveau contexte\n= System + Résumé + Dernier message"]
NewCtx --> Continue2["Continuer avec contexte frais"]
style Full fill:#3a1a1a,stroke:#ed4a4a,color:#fff
style Summary fill:#283d28,stroke:#4aed5c,color:#fff
style Compact fill:#2d3748,stroke:#4a9eed,color:#fff
Point important : la compression n’est pas gratuite. Tu perds en détail. Le modèle n’a plus accès au diff exact que tu as fait à l’étape 7, mais à un résumé qui dit “le module d’authentification a été refactorisé”. Pour la plupart des tâches c’est suffisant. Pour du débogage chirurgical, ça peut poser problème.
Codex appelle ça compaction. Claude Code fait quelque chose d’équivalent avec la compression automatique de contexte. L’idée est identique : quand le contexte devient ingérable, tu comprimes le passé et continues avec une version plus légère.
Sandbox : la cage dorée
Les deux agents exécutent les outils dans un sandbox — un environnement restreint où l’accès au réseau et au système de fichiers est limité par défaut.
C’est fondamental. Sans sandbox, un rm -rf / généré par hallucination du modèle détruirait ta machine. Avec un sandbox, le pire scénario est qu’il casse quelque chose dans les limites autorisées.
Claude Code te demande confirmation pour chaque opération potentiellement destructrice (sauf si tu l’approuves explicitement). Codex CLI opère par défaut dans un mode similaire de permissions explicites.
La leçon ici n’est pas technique, elle est philosophique : un agent qui peut tout faire est un agent en qui tu ne peux pas avoir confiance. Les restrictions ne sont pas des limitations — ce sont des garanties.
Codex CLI vs Claude Code : jumeaux non identiques
Maintenant vient la partie intéressante. Tous deux sont la même boucle à l’intérieur, mais les décisions de conception divergent sur des points intéressants :
flowchart TB
subgraph Codex["Codex CLI (OpenAI)"]
direction TB
CG["GUI de bureau\n(Command Center)"]
CS["Shell générique\n(bash/terminal)"]
CA["Automations\n(scheduling natif)"]
CD["Diffs avec\ncommentaires inline"]
end
subgraph Claude["Claude Code (Anthropic)"]
direction TB
CC["CLI-first\n(terminal natif)"]
CT["Outils dédiés\n(Read, Edit, Grep, Glob)"]
CK["Skills\n(/blog, /improve...)"]
CF["Feedback\nconversationnel"]
end
style Codex fill:#1a2332,stroke:#4a9eed,color:#fff
style Claude fill:#2a1a32,stroke:#9a4eed,color:#fff
Outils : générique vs spécialisé
Codex donne au modèle accès à un shell générique. Si tu veux lire un fichier, le modèle exécute cat fichier.py. Si tu veux chercher du texte, il exécute grep -r "motif" ..
Claude Code fait l’opposé : il a des outils dédiés pour chaque opération. Read pour lire les fichiers, Edit pour les modifier (avec remplacement exact de chaînes, pas réécriture complète), Grep pour chercher, Glob pour trouver des fichiers par motif.
Lequel est le mieux ? Ça dépend de ton point de vue. Le shell générique est plus flexible — tout ce que tu peux faire dans un terminal, le modèle peut le faire. Mais les outils dédiés sont plus sûrs et efficaces. Un Edit qui n’envoie que le diff du changement est plus rapide et moins sujet aux erreurs qu’un cat > fichier.py << 'EOF' qui réécrit tout le fichier.
Mon expérience : les outils dédiés gagnent pour 90% des cas. Le shell générique gagne quand tu as besoin de faire quelque chose d’exotique qu’aucun outil ne couvre.
GUI vs CLI
Codex mise sur une GUI de bureau (Command Center) où tu vois les diffs comme dans une pull request, tu peux mettre des commentaires inline sur les changements, et tu as une vue graphique de ce que fait l’agent.
Claude Code est CLI pur. Ton terminal. Ton shell. Pas de petites fenêtres. Si tu veux réviser un changement, l’agent te le montre en texte. Si tu veux donner du feedback, tu l’écris comme un message de plus dans la conversation.
Que préfères-tu ? Le CLI, de loin. Et pas par purisme hacker. C’est qu’un CLI s’intègre avec tout : tmux, scripts, cron, pipelines de CI, remote control via SSH. Une GUI te lie à un écran concret. Pour les sessions interactives la GUI est plus visuelle, certes. Mais pour vraiment bosser — tâches longues, automatisations, agents qui tournent seuls — le CLI n’a pas de concurrence.
Scheduling : natif vs DIY
Codex a des Automations : tu peux programmer des tâches qui s’exécutent automatiquement (réagir à un événement GitHub, lancer un agent chaque matin, etc.). C’est du scheduling natif dans la plateforme.
Claude Code n’a rien de tel. Si tu veux qu’un agent s’exécute toutes les 30 minutes, tu lui mets un cron ou un systemd timer. Si tu veux qu’il réagisse à un webhook, tu montes l’intégration toi-même.
Ici Codex a un avantage objectif pour les équipes qui veulent de l’automatisation out of the box. Mais la solution DIY de Claude Code a un avantage non évident : tu contrôles l’infrastructure. Si Anthropic change son API, ton cron continue de fonctionner parce que c’est ta machine. Si OpenAI change les Automations, tu es coincé.
Ce qui compte vraiment
Après avoir décortiqué les entrailles des deux agents, la conclusion est presque décevante par sa simplicité :
Un agent de codage est une boucle qui assemble un prompt, appelle un LLM, exécute des outils, et répète. Point final.
La magie n’est pas dans la boucle. Elle est dans trois choses :
La qualité du modèle. Une boucle
whileavec GPT-3 ne fait rien d’utile. Avec Claude Opus ou GPT-4o, elle refactorise des modules entiers. La boucle est la même — c’est le cerveau à l’intérieur qui fait la différence.La gestion du contexte. Le prompt ne peut pas grandir indéfiniment. Comment tu ordonnes l’information, quand tu comprimes, ce que tu priorises lors de la compression — c’est là où l’ingénierie compte vraiment. Un agent qui perd le contexte critique lors de la compression fait des erreurs qu’un humain ne ferait jamais.
La conception des outils. Donner à un LLM accès à
bashsans restrictions, c’est comme donner les clés de la voiture à quelqu’un qui n’a jamais conduit. Les outils bien conçus (avec validation, restrictions et feedback clair des erreurs) font la différence entre un agent qui t’aide et un qui déraille et supprimenode_modulesà trois heures du matin.
La prochaine fois que ton agent de codage fait quelque chose qui semble magique, souviens-toi : c’est un while True avec un LLM à l’intérieur. Élégant, oui. Puissant, sans aucun doute. Mais magique… pas vraiment.
Sources : L’article principal est “What Actually Happens Inside an AI Coding Agent (We Unrolled It)” de Michael Bolin (OpenAI). La comparaison avec Claude Code vient d’expérience directe et de la documentation officielle d’Anthropic. Si le sujet du contexte et du cache t’intéresse, lis Por qué el 99% de lo que envías a Claude ya lo tiene en caché et El cache de tu LLM te cobra el doble por ahorrarte dinero.
Cet article a été rédigé en espagnol et traduit avec l’aide de l’IA.