Chez Liksi, on travaille surtout avec Claude Code, branché sur Sonnet ou Opus, et à force on ne se pose plus la question de l’outil. Jusqu’au jour où on confie la même tâche, au même modèle, dans un autre outil : l’un termine proprement, l’autre part en boucle ou oublie une consigne donnée dix minutes plus tôt. Même modèle, même prompt, deux issues opposées.
Ce qui change, c’est tout ce qui entoure le modèle : comment on lui présente le contexte, quelles actions on lui permet (lire un fichier, lancer une commande), ce qu’on fait quand la conversation devient trop longue. Cette couche a un nom qui circule de plus en plus dans les discussions techniques : le harness.
Un modèle ne fait que prédire du texte
Un LLM, seul, ne lit aucun fichier, n’exécute aucune commande, ne se souvient de rien entre deux appels. Il prend une séquence de texte en entrée et produit une séquence de texte en sortie. Rien de plus.
Pour qu’il devienne un agent capable de corriger un bug ou de rédiger un document, il faut construire une couche autour de lui : quelque chose qui lui donne des outils, qui décide quoi lui montrer à chaque appel, qui interprète ce qu’il répond et qui le rappelle avec le résultat. C’est cette couche que la documentation de Claude Code désigne directement par ce terme :
« Claude Code is the layer around the model that provides the tools and manages the context the model sees. This surrounding layer is what the term agentic harness refers to. »
Un travail de recherche récent, Harness-Bench, formalise la même idée en la nommant système : le harness est « la couche système qui gère le contexte, les outils, l’état, les contraintes, les permissions, le traçage et la récupération d’erreur ». Le modèle raisonne, le harness agit.
Le harness en quarante lignes
Le concept devient plus concret dès qu’on écrit la version la plus dépouillée possible. Voici une boucle agentique minimale avec le SDK Anthropic : un outil bash, et une boucle tant que le modèle demande à utiliser un outil.
import Anthropic from "@anthropic-ai/sdk";
import { execSync } from "node:child_process";
const client = new Anthropic();
const tools: Anthropic.Tool[] = [
{
name: "bash",
description: "Exécute une commande shell et retourne sa sortie.",
input_schema: {
type: "object",
properties: { command: { type: "string" } },
required: ["command"],
},
},
];
async function runAgent(task: string) {
const messages: Anthropic.MessageParam[] = [{ role: "user", content: task }];
while (true) {
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
tools,
messages,
});
messages.push({ role: "assistant", content: response.content });
if (response.stop_reason !== "tool_use") {
return response.content;
}
const toolResults: Anthropic.ToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type === "tool_use" && block.name === "bash") {
const { command } = block.input as { command: string };
const output = execSync(command, { encoding: "utf-8" });
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: output,
});
}
}
messages.push({ role: "user", content: toolResults });
}
}
Cette boucle fonctionne, on peut vraiment lui demander d’explorer un répertoire ou de lancer des tests. Mais elle casse dès qu’on s’éloigne d’une démo. Si la conversation dépasse la fenêtre de contexte, l’appel échoue, sans mécanisme de repli. L’outil bash exécute n’importe quelle commande sans filtre, y compris rm -rf / : rien dans cette boucle ne fait la différence entre une commande utile et une commande destructrice. Un processus qui plante emporte tout l’historique avec lui, sans possibilité de reprise. Et déléguer une sous-tâche à un agent séparé pour ne pas polluer le contexte principal demande de l’écrire entièrement soi-même.
Tout ce qui manque à cette boucle pour devenir utilisable en pratique, la compaction du contexte, les permissions, la persistance des sessions, les sous-agents, la description qu’on met dans le prompt système, c’est précisément le travail d’un harness. La boucle elle-même est presque triviale ; l’ingénierie se joue dans ce qu’on construit autour.
Anatomie d’un harness
La boucle
Le squelette qu’on vient d’écrire : demander au modèle, exécuter ce qu’il réclame, lui rendre le résultat, répéter jusqu’à ce qu’il s’arrête. Claude Code décrit sa propre boucle en trois phases qui s’enchaînent, rassembler le contexte, agir, vérifier le résultat, jusqu’à ce que la tâche soit jugée terminée.
Les outils
Chaque outil est un pari sur ce que le modèle ne peut pas faire seul. Lire un fichier, l’éditer, chercher dans le code, lancer une commande : la liste des outils disponibles détermine directement ce que l’agent peut accomplir, et leur description consomme du contexte à chaque appel.
Le contexte
C’est la partie la plus coûteuse à gérer. Que voit le modèle à chaque tour ? L’historique complet grossit vite et finit par saturer la fenêtre de contexte. Claude Code répond en libérant d’abord les anciennes sorties d’outils, puis en résumant la conversation si besoin, en chargeant les compétences (skills) et les définitions d’outils MCP à la demande plutôt qu’en les gardant en mémoire permanente.
Le contrôle
Un agent qui peut éditer des fichiers et exécuter des commandes peut aussi faire n’importe quoi de destructeur. Les modes de permission (demander avant chaque action, accepter les éditions sans demander, laisser un classifieur filtrer les actions risquées) et les points d’interception (hooks) sont la manière dont un harness impose des limites sans dépendre uniquement du bon vouloir du modèle.
Le risque ne vient pas que d’une commande mal choisie par le modèle. Un agent qui lit le contenu d’une page web, d’un fichier de code ou d’un ticket peut aussi y trouver des instructions cachées, une injection de prompt qui cherche à détourner sa tâche sans qu’aucune ligne du harness n’ait de bug. Les permissions et les hooks filtrent ce que l’agent décide de faire ; l’isolation de l’exécution (environnement jetable, système de fichiers en lecture seule sur les zones sensibles) limite les dégâts si une action malveillante passe malgré tout entre les mailles du filtrage.
La persistance
Une session qui plante ne devrait pas repartir de zéro. Les journaux de conversation, les points de restauration avant chaque édition, la mémoire qui survit d’une session à l’autre : autant de mécanismes qui donnent à l’agent une continuité que le modèle, sans état, ne peut pas fournir par lui-même.
Pourquoi le sujet est devenu central
Les benchmarks mesurent un couple, pas un modèle seul
Harness-Bench a fait tourner six harnesses configurables sur huit modèles, produisant plus de 5 000 trajectoires d’exécution sur 106 tâches identiques. Résultat : le harness le mieux noté (NanoBot) obtient 76,2 sur l’ensemble des tâches, le moins bon (OpenClaw) 52,4, un écart de 23,8 points avec le même bassin de modèles. Les auteurs en tirent une conclusion directe : la capacité d’un agent devrait se mesurer au niveau du couple modèle-harness, pas être attribuée au modèle seul.
Début 2026, sur Terminal-Bench 2.0, l’équipe Meta-Harness de Stanford a observé le même phénomène dans l’autre sens : avec exactement le même modèle Opus 4.6, son harness obtient un score supérieur à celui d’un harness concurrent, alors que rien n’a changé côté modèle. LangChain a fait la démonstration inverse en conditions réelles sur ce même benchmark : sans toucher au modèle (GPT-5.2-Codex reste fixe d’un bout à l’autre), l’équipe fait passer son agent de la 30e à la 5e place, de 52,8 % à 66,5 %, en ne touchant qu’au prompt système, aux outils et aux hooks qui détectent les boucles infinies. Ce sont ces écarts, reproductibles et documentés, qui poussent les équipes à préciser systématiquement quel harness a servi à produire un score, pas seulement quel modèle.
Depuis fin août 2026, Terminal-Bench est passé en version 4.0 : les meilleurs harnesses avaient fini par résoudre systématiquement une partie des tâches de la 2.0, au point qu’elles ne différenciaient plus grand monde. Le classement doit régulièrement recalibrer ses tâches et en retirer certaines pour rester discriminant, un rappel que le harness comme le benchmark qui le mesure sont des cibles mouvantes.
Les modèles se rapprochent, le harness reste le levier disponible
Quand deux modèles de fournisseurs différents deviennent difficiles à distinguer sur un cas d’usage donné, c’est souvent la couche qui les entoure qui fait la différence perçue. DeepSeek illustre les deux faces du sujet : l’entreprise publie son propre harness open source, DeepSeek Harness (dsh), construit sur une architecture où chaque composant, y compris la boucle agentique elle-même, est un plugin remplaçable. Et dans le sens inverse, ses modèles se branchent directement dans Claude Code via une API compatible Anthropic (ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic) : même harness, moteur différent. Le harness devient la brique qu’on choisit indépendamment du modèle qui tourne derrière.
Les tâches longues forcent l’ingénierie
Quand une session dure des heures et enchaîne des centaines d’appels, le contexte fini n’est plus un détail. Anthropic a documenté ce problème dans deux billets d’ingénierie, l’un sur les agents qui tournent longtemps, l’autre sur la conception d’un harness pour du développement applicatif prolongé. Le second résume bien pourquoi la question ne se referme jamais :
« Every component in a harness encodes an assumption about what the model can’t do on its own, and those assumptions are worth stress testing… they can quickly go stale. »
Un harness fait donc des hypothèses explicites sur les limites du modèle : qu’il perd le fil au-delà d’une certaine longueur de contexte, qu’il termine une tâche trop tôt par anxiété de manquer de place, qu’il a besoin d’un fichier de suivi pour reprendre après une coupure. Ces hypothèses vieillissent mal : un modèle qui s’améliore rend obsolète une partie de l’échafaudage construit pour compenser ses faiblesses d’hier.
Trois réponses à la même question
Il existe des dizaines de harnesses aujourd’hui, chacun avec ses arbitrages. On va en présenter trois dans cet article, et ils ne sont pas choisis au hasard : ensemble, ils couvrent l’essentiel des positions possibles sur un même curseur, celui de la part de travail que le harness prend en charge à la place du modèle. Claude Code pousse ce curseur au maximum, pi le pousse au minimum. DeepSeek Harness refuse de trancher : il rend chaque brique remplaçable.
Claude Code : le harness qui prend en charge le maximum
Claude Code assume un harness riche : gestion de contexte automatisée, permissions configurables, et toute une couche d’extension déclarative construite au-dessus de la boucle de base, hooks, skills, sous-agents, serveurs MCP, plugins. On avait détaillé la distribution de ces extensions dans une équipe dans un article précédent. Le Claude Agent SDK rend ce harness directement programmable : on récupère la même boucle, les mêmes outils et la même gestion de contexte que Claude Code, mais pilotables depuis son propre code Python ou TypeScript.
pi : le pari du minimalisme
À l’opposé, pi, le harness créé par Mario Zechner, part du principe inverse. Son auteur résume sa règle de conception ainsi : « if I don’t need it, it won’t be built ». Concrètement, pi ne propose que quatre outils, read, write, edit, bash, et un prompt système qui reste sous les 1 000 tokens, contre plusieurs milliers pour la plupart des harnesses comparables. Pas de MCP : les descriptions d’outils des serveurs MCP populaires consomment, selon lui, 7 à 9 % du contexte disponible avant même de commencer à travailler. Pas de sous-agents non plus, jugés trop opaques : « you have zero visibility into what that sub-agent does ». pi va jusqu’à se passer des demandes de permission avant chaque commande, un choix qui déplace le risque plutôt que de le supprimer : ce que la section sur le contrôle décrivait plus haut comme un garde-fou devient ici une couche qu’on retire délibérément, en misant sur la fiabilité du modèle plutôt que sur une barrière externe. Le pari sous-jacent est que les modèles récents ont déjà appris, via leur entraînement, ce que signifie être un agent de code, et qu’un harness lourd ajoute plus de bruit que de garde-fous utiles. Un benchmark interne de Databricks, mené sur sa propre base de code de plusieurs millions de lignes, va dans ce sens : en appelant le même modèle avec le même effort de raisonnement via pi plutôt que via Claude Code ou Codex, le coût par tâche est parfois divisé par deux, à qualité équivalente, parce que pi envoie environ trois fois moins de contexte à chaque tour.
DeepSeek Harness : le harness comme framework composable
DeepSeek Harness pousse la logique inverse de pi : au lieu de réduire la surface, il rend absolument tout remplaçable. Construit sur le framework Cordis, sous une architecture qualifiée d’« everything is a plugin », il traite l’adaptateur de modèle, le registre d’outils, le journal de session et la boucle agentique elle-même comme des plugins qu’on peut échanger depuis une configuration, sans toucher au cœur du système. Un principe structure tout le reste du projet : tout ce que le modèle voit doit être reconstructible depuis le journal de session, append-only. Contrairement à Claude Code et pi, le projet est encore en aperçu développeur, avec des changements de compatibilité annoncés à chaque itération : pas de chiffre de performance publié à ce stade, l’intérêt est dans l’architecture, pas encore dans un historique d’usage en production.
| Claude Code | pi | DeepSeek Harness | |
|---|---|---|---|
| Boucle | Trois phases (contexte, action, vérification), extensible par hooks | La même boucle minimale, sans couche ajoutée autour | Un plugin parmi d’autres, remplaçable depuis la configuration |
| Outils | Riche par défaut (fichiers, recherche, exécution, web), extensible par MCP | 4 seulement (read, write, edit, bash), volontairement fermé |
Configurable selon le mode, chaque outil est un plugin |
| Contexte | Compaction automatique, skills et MCP chargés à la demande | Prompt système sous les 1 000 tokens, contexte minimal envoyé à chaque tour | Journal de session append-only, tout ce que voit le modèle est reconstructible depuis le log |
| Contrôle | Modes de permission configurables, hooks, classifieur de risque | Aucune demande de permission par défaut, le risque est assumé plutôt que filtré | Politique d’approbation branchée comme un plugin remplaçable |
| Persistance | Sessions JSONL, points de restauration, mémoire inter-sessions | Historique de session sous forme d’arbre, avec branches | Journal de session comme seule source de vérité, migrations de format versionnées |
| Maturité | Production, large base d’usage | Production, validé par un benchmark tiers (Databricks) | Aperçu développeur, pas encore de données de performance publiées |
Ce qu’on en retient
Évaluer un agent, c’est évaluer un couple modèle-harness, pas un modèle isolé. Un score annoncé sans préciser l’outil utilisé pour l’obtenir ne dit pas grand-chose. Et cet équilibre n’est jamais figé : chaque brique du harness encode une hypothèse sur ce que le modèle du moment ne sait pas faire, et cette hypothèse se périme à mesure que les modèles progressent. Ce qui était une nécessité il y a un an peut devenir un poids mort aujourd’hui.
Pour une équipe qui construit ses propres outils autour d’un LLM, chez Liksi comme ailleurs, c’est justement là que se joue le travail d’ingénierie : dans le choix des outils qu’on donne au modèle, dans ce qu’on décide de garder ou de résumer dans le contexte, dans les garde-fous qu’on met en place avant de laisser un agent agir seul.
Ce travail ne s’arrête pas au choix du harness de développement. Au-dessus de Claude Code, pi ou DeepSeek Harness, une équipe construit en général son propre harness applicatif : des instructions de projet, des skills, des hooks qui configurent l’agent pour qu’il respecte la stack en place, les outils et les conventions de l’équipe, l’architecture cible, plutôt que de repartir d’un agent générique à chaque tâche.
Ressources utiles
Documentation
- Claude Code - How Claude Code works
- Claude Agent SDK - Overview
- DeepSeek Harness - Dépôt et documentation d’architecture
- pi - Site officiel
Articles et billets
- Anthropic - Effective harnesses for long-running agents
- Anthropic - Harness design for long-running application development
- Mario Zechner - What I learned building an opinionated and minimal coding agent