Skip to content

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.

Harnessce que vous construisezcontexte envoyéaction suivanteautoriséeexécutionsortie, code retourrésultat ajoutéBoucle de l'agentun tour par étape, jusqu'à la finde la tâche ou jusqu'à l'abandonTâcheContextemémoire, compactionModèledécide de la suiteGarde-fousautorisé ou non ?Outilsshell, API, fichiersLe monde réeldépôt, services, internetVérificationcodes retour, hooks
Un tour de boucle par étape. Seuls le modèle et le monde réel sont hors du harness : tout ce que voit le modèle, et tout ce qu'il a le droit de toucher, passe par une pièce que quelqu'un a construite. Chaque tour produit un retour : une sortie, un code retour, ce que remontent les hooks. Lancer les vrais tests, c'est le plus souvent le modèle qui le décide, ou un hook qui l'y oblige.

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.

Harness engineering, 2026quel environnement construire+ outils, boucle, permissions, contrôlesContext engineering, 2024-2025ce qu'on montre au modèle+ recherche, mémoire, compactionPrompt engineering, 2022-2023ce qu'on lui ditles instructions seules
Rien n'a été remplacé. Le prompt et le contexte comptent toujours : ils sont simplement devenus deux des pièces du harness.

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.

python
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.

080 %limiteDébut de tâcheencore de la placeÉtape 9atteint les 80 %Tronquervieux résultats rognésCompacteranciens tours résumésNi l'un ni l'autrefenêtre pleine, arrêtprompt, mémoire, tâcheappel et résultatsortie tronquéerésumé
Chaque appel d'outil ajoute un bloc. Arrivé aux 80 %, le harness doit faire de la place, en rognant les anciennes sorties ou en repliant les anciens tours dans un résumé. S'il ne fait ni l'un ni l'autre, la tâche s'arrête quand la fenêtre est pleine, qu'elle soit finie ou non.

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.

Même modèle, 169 tâches, fenêtre de 20K tokensHarness témoin43 résoluesNouveau harness72 résolueslongueur de barre sur 169 tâchesAvec une fenêtre de 262K, l'écart sur SWE-bench Verified a quasiment disparu.
Tout le gain venait de la façon dont le harness gérait une petite fenêtre de contexte. Donnez de la place au modèle et la stratégie ne pèse plus grand-chose. Et c'est aussi pour ça qu'elle compte en production, où chaque token est facturé.

Les techniques habituelles :

TechniqueCe qu'elle fait
CompactionRésume les anciens tours quand le nombre de tokens grimpe
TroncatureRogne les anciennes sorties d'outils et garde les récentes intactes
Fichiers mémoireDes notes chargées au début de chaque session, comme le CLAUDE.md ou l'AGENTS.md d'un projet
Sous-agentsDonnent à une tâche annexe un contexte vierge et ne renvoient que la réponse
Remise à zéro du contexteVide 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é :

json
{
  "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 :

bash
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 :

bash
$ rg -n "InvoiceTotal" src/
$ sed -n '118,160p' src/billing/invoice.ts
$ npm test -- invoice
$ git diff --stat

Pour 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.

Modèlecommandesortie, code retourbashun seul outilrg, greptrouver le codefind, lsvoir ce qu'il y acat, sedlire un bout de fichiergithistorique, diffs, rollbacknpm test, pytestvérifier le travailcurlparler aux APIdocker, kubectllancer des servicespsql, jqinterroger les données
Un seul outil, et tous les programmes de la machine viennent avec. L'étincelle rejoue dans l'ordre les quatre commandes ci-dessus. Ce qui revient à chaque fois, c'est du texte brut et un code retour, qu'un modèle sait lire sans le moindre adaptateur entre les deux.

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.

AgentOpen sourceModèlesSécurité par défautOutils intégrés
Claude CodeNonClaude uniquementClassifieur sur Pro, Max et Team, sinon demande40+, dont le socle Read, Edit, Grep, Glob, Bash
Codex CLIApache 2.0OpenAI par défaut, d'autres via la configSandbox OS, workspace seul, réseau coupéSurtout le shell, plus apply_patch
Gemini CLIApache 2.0Gemini uniquementPas de sandbox, confirme shell et écrituresUne vingtaine, dont shell et grep
CursorNonNombreux fournisseursShell en sandbox, un classifieur examine le resteRecherche, lecture, édition, shell, navigateur
OpenHandsMITPresque tous, via LiteLLMSandbox Docker dans l'app web, demande d'abord en CLITerminal, éditeur de fichiers, suivi de tâches
AiderApache 2.0Presque tous, locaux comprisPas de sandbox, un commit git par modification, demande avant les commandesPas de boucle d'outils : formats d'édition et carte du dépôt
ClineApache 2.0Nombreux, locaux comprisDemande avant chaque action7, avec ripgrep pour la recherche
PiMIT15+ fournisseursPas de sandbox, aucune demande4 : 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 codeAgent généraliste
Bouclela mêmela même
Outilsshell, git, fichiersAPI, navigateur, e-mail, CRM
Contextedépôt, diffsdocs, tickets, historique de discussion
Garde-foussandboxvalidation des envois, paiements, suppressions
Vérificationtests, intégrésevals, 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 :

  1. Le coût par tâche menée à bien, pas le coût par token.
  2. Le taux de réussite sur vos propres tâches, pas sur un classement public.
  3. Les tâches longues : les termine-t-il, ou cale-t-il à mi-chemin ?
  4. Le modèle de sécurité : que peut-il casser, et qui donne le feu vert ?
  5. 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 ​