Harness Engineering 101 : comment fonctionnent vraiment les agents de code
Qu'est-ce qu'un harness d'agent ?
Un harness d'agent, c'est tout le logiciel qui entoure un modèle de langage et qui en fait un agent capable de travailler. Birgitta Böckeler, de Thoughtworks, l'a résumé en quatre mots dans un article publié sur le site de Martin Fowler : Agent = Modèle + Harness.
Le modèle, c'est la partie que vous louez. Tout le reste relève du harness : la boucle qui le fait tourner, les outils qu'il peut appeler, ce qui entre dans sa fenêtre de contexte, ce qu'il a le droit de faire, et la façon dont on vérifie son travail avant de l'accepter.
On confond souvent harness et framework, alors que ce n'est pas la même chose. LangChain, Microsoft Agent Framework et l'OpenAI Agents SDK sont des frameworks : des boîtes de pièces détachées pour construire un agent. Le harness, c'est le runtime complet qu'on obtient une fois ces pièces assemblées. Claude Code est un harness. Codex CLI aussi. La frontière se brouille, car plusieurs frameworks livrent désormais leur propre harness clé en main.
Pourquoi le harness compte
Voici une expérience qui mériterait d'être bien plus connue. Prenez un modèle et confiez-lui 169 vraies tâches de correction de bugs tirées de SWE-bench Verified. Ne touchez ni aux poids du modèle, ni aux tâches, ni à la fenêtre de contexte. Ne changez que le code qui tourne autour du modèle. Le nombre de tâches entièrement résolues passe de 43 à 72.
Ce résultat vient d'un article mis en ligne sur arXiv en août, et c'est la façon la plus rapide que je connaisse de dire de quoi parle ce billet. Le modèle était le même dans les deux cas. Le harness, lui, avait changé (le « harnais » de code qui l'entoure).
Je passe désormais l'essentiel de mes journées avec des agents, à en construire et à m'en servir pour écrire du code, et la première question qu'on me pose reste la même : quel modèle choisir ? Elle compte de moins en moins, trimestre après trimestre. Les modèles de pointe sont assez proches les uns des autres pour que le logiciel qui les enveloppe décide de l'essentiel : ce que coûte une tâche, si l'agent va au bout, et si vous pouvez vous fier à ce qu'il vous rend. Ce logiciel, c'est le harness. Le concevoir, c'est ce qu'on commence à appeler le harness engineering.
Prompt, contexte, harness
Le domaine en est arrivé là en trois étapes, et chacune a englobé la précédente.
Le prompt engineering portait sur les mots. Le context engineering, sur tout ce qu'on place devant le modèle en plus de ces mots : des documents remontés par la recherche, de la mémoire, le résumé de ce qui s'est passé dix tours plus tôt. Le harness engineering reprend les deux et ajoute tout ce dont un modèle a besoin pour agir, et plus seulement pour parler.
Toute la boucle en trente lignes
Le plus simple pour comprendre un harness, c'est d'en écrire un. Voici le cœur d'un agent de code en pseudocode. C'est simplifié, mais tous les harness que j'ai lus ont cette forme.
def run_agent(task, model, tools, limits):
context = [system_prompt(), project_memory(), task]
for step in range(limits.max_steps):
if count_tokens(context) > limits.window * 0.8:
context = compact(context) # summarize old turns
reply = model.generate(context, tools=tools.schemas())
if reply.is_done:
report = verify(reply) # run tests, linters, a reviewer
if report.passed:
return reply
context.append(report.as_feedback())
continue
for call in reply.tool_calls:
if not policy.allows(call):
result = ask_human(call) or "denied by policy"
else:
result = tools.run(call) # most of the time: a shell command
context.append(trim(result)) # keep the lines that matter
if same_command_failed(context, times=3):
context.append("That failed three times. Try a different approach.")
return stop_and_report(context)Comptez les lignes qui font intervenir le modèle. Il n'y en a qu'une : model.generate. Tout le reste, c'est du harness, et chacune des autres lignes traduit une décision que quelqu'un a dû prendre. À quel moment compacter ? Quelle part d'un log de tests de 4 000 lignes le modèle a-t-il le droit de voir ? Que répond policy.allows face à un git push --force ? Changez une seule de ces réponses et le même modèle se comporte comme un autre agent.
Les pièces, une par une
La boucle
Planifier, agir, observer, recommencer. Le cœur est vraiment aussi petit que ça : l'agent Pi de Mario Zechner fait tenir son prompt système et ses définitions d'outils sous les 1 000 tokens. Le difficile, c'est tout ce qu'il y a autour. Quand s'arrêter. Quand demander à un humain. Que faire quand l'agent relance pour la cinquième fois la même commande qui échoue : c'est précisément pour ce cas que la ligne same_command_failed existe dans le code plus haut.
Les outils
Les outils sont le seul moyen dont l'agent dispose pour toucher à quoi que ce soit. Pour un agent de code, ça veut dire lire et modifier des fichiers, lancer des commandes, fouiller le dépôt. Pour un agent de support, ce sont le système de tickets et la base de connaissances.
La conception des outils compte plus qu'on ne le croit. Un outil qui déverse 10 000 lignes de log noie le contexte. Un outil qui renvoie les 20 lignes autour de l'erreur laisse le modèle réfléchir. Avec MCP, brancher un outil est devenu trivial, si bien que le vrai travail consiste maintenant à en garder moins et à soigner ce qu'ils renvoient. En pratique, chez les agents de code, un seul outil abat l'essentiel du travail, et il a droit à sa propre section plus bas.
Le contexte
C'est la couche la plus sous-estimée. Toute tâche un peu longue finit par buter sur la limite de contexte, et ce que fait le harness à ce moment-là décide si l'agent ira au bout.
L'article d'août cité plus haut, « Same Model, Different Harness », en est la démonstration la plus nette que j'aie vue. Les deux séries d'essais tournaient avec les mêmes poids, les mêmes 169 tâches de SWE-bench Verified, la même capacité de contexte et le même protocole. Le nouveau harness ne changeait que deux choses. Il raccourcissait par paliers les anciens résultats d'outils à mesure que la fenêtre se remplissait, et quand il surprenait l'agent à répéter des commandes en échec, il lui disait d'essayer autre chose.
Les techniques habituelles :
| Technique | Ce qu'elle fait |
|---|---|
| Compaction | Résume les anciens tours quand le nombre de tokens grimpe |
| Troncature | Rogne les anciennes sorties d'outils et garde les récentes intactes |
| Fichiers mémoire | Des notes chargées au début de chaque session, comme le CLAUDE.md ou l'AGENTS.md d'un projet |
| Sous-agents | Donnent à une tâche annexe un contexte vierge et ne renvoient que la réponse |
| Remise à zéro du contexte | Vide entièrement la fenêtre et repart d'une nouvelle session, à partir d'un fichier de passation rédigé |
La dernière ligne est plus récente que les autres, et elle existe pour une raison qu'on ne devinerait pas. Chez Anthropic, l'équipe qui fait tourner des agents sur de longues sessions de développement d'applications a constaté que « la compaction seule ne suffisait pas ». À mesure que la fenêtre se remplissait, les modèles montraient ce que l'équipe appelle « l'anxiété de contexte » : ils expédiaient la fin du travail parce qu'ils sentaient la limite approcher. Repartir d'une fenêtre vide avec une passation structurée a mieux marché qu'un résumé, avec lequel le modèle se savait toujours à court de place.
Les garde-fous
Un agent qui peut lancer des commandes peut aussi supprimer des choses. Chaque harness se place quelque part sur un spectre, et quand je les ai mis côte à côte, les positions se sont révélées plus variées que je ne l'imaginais :
- Demander systématiquement. C'est le comportement par défaut de Cline : chaque action attend votre accord.
- Laisser trancher un classifieur. Le mode auto de Claude Code (le mode de départ sur les offres Pro, Max et Team) et l'Auto-review de Cursor font examiner les actions par un second modèle au lieu de vous solliciter à chaque fois.
- Cloisonner. Codex CLI tourne par défaut dans une sandbox au niveau de l'OS, limitée au workspace, réseau coupé.
- Faire confiance à l'utilisateur. Pi n'a ni sandbox ni demande d'autorisation. Son auteur parle de « mode YOLO intégral » et conseille de le lancer dans un conteneur.
Aucun de ces choix n'est mauvais en soi. Le bon dépend de ce qu'une erreur peut coûter, et ça, c'est une question qui porte sur votre machine et vos données plus que sur l'outil.
La vérification
C'est la couche qui vous permet de faire confiance à l'agent sans relire chaque ligne qu'il écrit. Böckeler y distingue deux familles de contrôles. Les guides orientent l'agent avant qu'il agisse : instructions, conventions, exemples. Les capteurs examinent le résultat après coup et l'aident à se corriger : tests, linters, vérificateurs de types, agents de revue. Dans le pseudocode, project_memory() est un guide et verify() un capteur.
Le billet d'OpenAI « Harness engineering: leveraging Codex in an agent-first world » pousse cette logique jusqu'au bout. Une équipe partie à trois ingénieurs a livré une bêta interne sans une seule ligne de code écrite à la main, au bout d'environ 1 500 pull requests fusionnées. Codex a écrit l'application, les tests, la configuration de la CI et la documentation. Les humains, eux, ont construit le harness : les contrôles, la structure et les boucles de retour qui maintenaient l'agent sur les rails.
Le problème, c'est qu'un agent juge mal son propre travail. Le même billet d'Anthropic le dit sans détour : quand on leur demande d'évaluer ce qu'ils ont produit, les agents « ont tendance à répondre en faisant l'éloge du travail avec assurance », même quand un humain voit bien qu'il est médiocre. L'équipe a choisi de répartir le travail entre trois agents. Un planificateur rédige la spec, un générateur construit, et un évaluateur distinct teste l'application en fonctionnement avec Playwright, selon des critères fixés avant la première ligne de code. Seul, un agent a mis 20 minutes et coûté 9 $. Le harness complet a pris six heures et 200 $, pour un résultat nettement meilleur. La vérification ne tombe pas du ciel. Quelqu'un doit l'intégrer au harness, parfois sous la forme d'un deuxième agent à part entière, dont le seul rôle est d'être difficile à contenter.
L'extensibilité
Un bon harness vous laisse modifier son comportement sans avoir à le forker. Claude Code expose plus de 30 événements de cycle de vie auxquels on peut accrocher des scripts (les hooks), sans compter les skills, les plugins, les sous-agents et les serveurs MCP. C'est là que viennent se loger les conventions propres à une équipe.
Voici un vrai hook, le genre que j'ajouterais dès le premier jour. Après chaque modification, il passe le formateur sur le fichier touché :
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}Regardez la commande. Le harness transmet l'événement en JSON sur l'entrée standard, jq en extrait un champ, et xargs le passe à un autre programme. C'est un pipeline Unix, et ce n'est pas un hasard.
Pourquoi le shell fait l'essentiel du travail
Mon premier poste, c'était de l'administration de serveurs Linux, et ce qui m'a accroché à l'époque, c'est tout ce qu'on pouvait faire en une seule ligne. On enchaîne quelques petits programmes, et une tâche qui a l'air de demander un après-midi est réglée avant même qu'on ait fini de taper. Voici le genre de ligne qui m'a fait craquer :
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | headÇa donne toutes les adresses IP qui ont tenté de forcer l'accès SSH de la machine, comptées et classées, avec cinq programmes qui ne savent rien les uns des autres. Regarder travailler un agent de code me fait exactement le même effet. Il sort le même genre d'outils, à peu près dans l'ordre où je l'aurais fait :
$ rg -n "InvoiceTotal" src/
$ sed -n '118,160p' src/billing/invoice.ts
$ npm test -- invoice
$ git diff --statPour moi, c'est de là que vient l'essentiel de la capacité d'agir d'un agent de code. Donnez à un modèle un seul outil, un shell, et il récupère au passage tous les programmes de la machine. Personne n'a eu à écrire un outil search_code ni un outil run_tests. rg et npm test existaient déjà, avec des décennies de documentation derrière eux.
Je vois quatre raisons pour lesquelles le shell convient si bien à un modèle de langage.
D'abord, il parle texte. Doug McIlroy a mis la règle par écrit en 1978, dans le Bell System Technical Journal : « Attendez-vous à ce que la sortie de chaque programme devienne l'entrée d'un autre programme, encore inconnu. » Personne aux Bell Labs ne pensait aux modèles de langage, mais un programme inconnu qui lit votre sortie, c'est une assez bonne description de ce qu'ils sont.
Ensuite, les modèles le connaissent déjà. Cinquante ans de pages de man, de scripts shell, de README et de réponses sur les forums se retrouvent dans leurs données d'entraînement. Zechner l'a dit sans détour en expliquant pourquoi Pi n'embarque que quatre outils (read, write, edit et bash) : « Les modèles savent se servir de bash. »
Troisième point, chaque commande rend compte de ce qu'elle a fait. Un code retour à 0 ou différent de 0, c'est un capteur gratuit. L'agent sait si le test est passé sans que personne ait eu à lui écrire une couche de vérification.
Enfin, les programmes se combinent. Un pipe fait de deux petits outils un troisième, à la volée, et le harness n'a donc pas besoin d'un outil dédié à chaque tâche.
Un autre morceau d'Unix travaille ici en coulisses, et l'article de LangChain sur l'anatomie d'un harness en fait « sans doute la primitive la plus fondamentale d'un harness » : le système de fichiers. Un modèle oublie tout dès que son contexte prend fin. Un fichier, non. Une note d'avancement, une liste de fonctionnalités, un log git : c'est ainsi qu'une tâche longue survit d'une session à l'autre, et ce sont les fichiers et git qui s'en chargent, comme ils le font depuis cinquante ans.
Les éditeurs sont arrivés à la même conclusion par l'autre bout. Anthropic décrit le principe de conception de son Claude Agent SDK comme le fait de donner « à vos agents un ordinateur, pour qu'ils puissent travailler comme le font les humains ». Boris Cherny, le créateur de Claude Code, a raconté que les premières versions reposaient sur du RAG avec une base vectorielle locale, et que l'équipe est passée à une simple recherche agentique (le modèle qui lance grep et consorts) parce que ça marchait mieux. De son propre aveu, c'était surtout une impression partagée en interne plutôt qu'un benchmark, mais c'est bien ce qu'ils ont livré. Vercel a réduit un agent de données interne à guère plus qu'un outil bash et annonce qu'il tourne 3,5 fois plus vite avec 37 % de tokens en moins. C'était sur cinq requêtes de test : prenez-le comme une tendance, pas comme une mesure.
Le shell a quand même ses limites, et mieux vaut les connaître. Il ne sait pas cliquer dans une application web, donc le travail sur une interface graphique demande toujours des outils de navigateur ou de computer use. Un produit SaaS sans CLI passe par une API ou un serveur MCP. Et le shell qui lance npm test peut tout aussi bien lancer rm -rf, et c'est bien pour ça que la section sur les garde-fous existe.
Comparatif des agents de code
Voici les harness sur lesquels on m'interroge le plus, dans leur état de septembre 2026. Les réglages par défaut évoluent vite, alors vérifiez la documentation avant de vous fier à une case.
| Agent | Open source | Modèles | Sécurité par défaut | Outils intégrés |
|---|---|---|---|---|
| Non | Claude uniquement | Classifieur sur Pro, Max et Team, sinon demande | 40+, dont le socle Read, Edit, Grep, Glob, Bash | |
| Apache 2.0 | OpenAI par défaut, d'autres via la config | Sandbox OS, workspace seul, réseau coupé | Surtout le shell, plus apply_patch | |
| Apache 2.0 | Gemini uniquement | Pas de sandbox, confirme shell et écritures | Une vingtaine, dont shell et grep | |
| Non | Nombreux fournisseurs | Shell en sandbox, un classifieur examine le reste | Recherche, lecture, édition, shell, navigateur | |
| MIT | Presque tous, via LiteLLM | Sandbox Docker dans l'app web, demande d'abord en CLI | Terminal, éditeur de fichiers, suivi de tâches | |
| Apache 2.0 | Presque tous, locaux compris | Pas de sandbox, un commit git par modification, demande avant les commandes | Pas de boucle d'outils : formats d'édition et carte du dépôt | |
| Apache 2.0 | Nombreux, locaux compris | Demande avant chaque action | 7, avec ripgrep pour la recherche | |
| MIT | 15+ fournisseurs | Pas de sandbox, aucune demande | 4 : read, write, edit, bash |
Lisez la dernière colonne de haut en bas. Les harness qui s'appuient le plus sur le shell embarquent le moins d'outils, et Codex, le plus centré sur le shell des trois grands, est aussi le plus strict pour le cloisonner. Ce couplage est voulu. Aider fait figure d'exception : il est antérieur au tool calling et passe toujours par des formats d'édition et une carte du dépôt, ce qui rappelle que la boucle de mon pseudocode n'est qu'une architecture parmi d'autres.
En dehors du code
Rien, dans le premier schéma, n'est propre au logiciel. Microsoft Agent Framework est passé en 1.0 en avril 2026, et à la Build de juin il s'est doté d'un harness intégré : accès au shell et aux fichiers, validation des appels d'outils, mémoire sur fichiers et compaction automatique du contexte. LangChain Deep Agents et l'OpenAI Agents SDK proposent des briques comparables.
Quand on sort du code, ce qui change tient surtout en une ligne :
| Agent de code | Agent généraliste | |
|---|---|---|
| Boucle | la même | la même |
| Outils | shell, git, fichiers | API, navigateur, e-mail, CRM |
| Contexte | dépôt, diffs | docs, tickets, historique de discussion |
| Garde-fous | sandbox | validation des envois, paiements, suppressions |
| Vérification | tests, intégrés | evals, grilles, relecture humaine |
Un agent de recherche n'a pas de suite de tests. Un agent de support ne peut pas lancer npm test sur une réponse. Le code retour qui rend les agents de code si faciles à vérifier n'existe pas ici, et un harness généraliste doit donc fabriquer ses propres capteurs : des jeux d'évaluation tirés de vrais cas passés, des agents de revue qui notent selon une grille, et des étapes où un humain valide. Si vous construisez un agent hors du code, c'est là que doit aller votre temps, parce que c'est là que ces agents échouent, et le plus souvent sans bruit. J'ai consacré un billet à part à ce à quoi ressemblent ces échecs silencieux en production.
Comment juger un harness
Que vous en choisissiez un ou que vous construisiez le vôtre, mesurez la pile entière, pas le modèle seul :
- Le coût par tâche menée à bien, pas le coût par token.
- Le taux de réussite sur vos propres tâches, pas sur un classement public.
- Les tâches longues : les termine-t-il, ou cale-t-il à mi-chemin ?
- Le modèle de sécurité : que peut-il casser, et qui donne le feu vert ?
- L'adéquation : s'accorde-t-il avec vos outils et vos conventions ?
Le coût, c'est ce que tout le monde sous-estime. Quand Artificial Analysis a lancé son Coding Agent Index en mai 2026, le coût par tâche allait de 0,07 $ à 2,26 $ selon les couples modèle-harness testés. L'essentiel de cet écart tient au modèle, mais c'est le harness qui décide combien de tokens le modèle consomme en route.
La machine en dessous fait bouger les chiffres, elle aussi. L'équipe d'ingénierie d'Anthropic a fait tourner le même modèle Claude dans le même harness sur les mêmes tâches de Terminal-Bench 2.0, et a relevé 6 points de pourcentage d'écart entre les ressources de conteneur les plus serrées et les plus généreuses. Faites donc vos comparaisons sur l'infrastructure que vous utiliserez vraiment.
Et ensuite ?
Une couche au-dessus des harness commence à apparaître. En juin 2026, Databricks a publié en open source Omnigent, qu'il présente comme un « méta-harness » : il se place au-dessus de Claude Code, de Codex, de Pi ou de votre propre agent, et permet de les combiner et de les gouverner depuis un seul endroit. Si l'idée prend, le harness devient un composant interchangeable, un peu comme on change de base de données.
Une partie du harness actuel finira aussi dans le modèle. La meilleure phrase que j'aie lue là-dessus vient de ce billet d'Anthropic : « Chaque composant d'un harness encode une hypothèse sur ce que le modèle ne sait pas faire seul. » Le contrôle same_command_failed de mon pseudocode suppose que le modèle ne remarquera pas qu'il tourne en rond. La compaction suppose qu'il ne peut pas tenir une tâche longue dans une seule fenêtre. À mesure que les modèles progressent, certaines de ces hypothèses cessent d'être vraies, et les pièces construites dessus peuvent disparaître.
Ce que je ne vois pas bouger, en revanche, c'est la frontière des permissions. Un modèle peut apprendre à repérer ses propres erreurs. Ce qu'il a le droit de supprimer sur votre serveur de production reste votre décision, écrite noir sur blanc dans un harness, comme elle l'était dans un fichier sudoers bien avant tout ça.
Si vous réfléchissez à ce que ce harness devrait être pour votre équipe, mon agenda est sur la page contact.
Sources
- Birgitta Böckeler, Harness engineering for coding agent users, martinfowler.com, avril 2026
- Sydney Lewis, Same Model, Different Harness: Different Coding-Agent Results, arXiv, août 2026
- OpenAI, Harness engineering: leveraging Codex in an agent-first world
- Anthropic, Building agents with the Claude Agent SDK
- M. D. McIlroy, E. N. Pinson et B. A. Tague, UNIX Time-Sharing System: Foreword, Bell System Technical Journal, 1978
- Mario Zechner, What I learned building an opinionated and minimal coding agent, novembre 2025
- Boris Cherny sur la recherche agentique qui a remplacé le RAG dans Claude Code, février 2026
- Vercel, We removed 80% of our agent's tools, décembre 2025
- Artificial Analysis, Coding Agent Index et son annonce de lancement de mai 2026
- Anthropic, Quantifying infrastructure noise in agentic coding evals
- Anthropic, Harness design for long-running application development, mars 2026
- LangChain, The anatomy of an agent harness, mars 2026
- Microsoft, Microsoft Agent Framework at BUILD 2026
- Databricks, Introducing Omnigent
- Documentation des outils pour le tableau comparatif : outils de Claude Code, modes de permission et hooks ; Codex et sa page approbations et sécurité ; outils de Gemini CLI ; modes d'exécution de Cursor ; OpenHands ; Aider ; outils de Cline ; Pi