Blog AI / Agent

Course AI Coding Agent 2026 : que se disputent vraiment Claude Code, Codex, OpenCode et DeepSeek Agent ? L’architecture Agent Harness vue par le JSON Tool Calling

Les classements demandent encore qui score plus haut. Ouvrez un terminal : ce qui modifie vraiment les fichiers, lance les tests et parle à MCP, ce n’est pas cette réponse en langage naturel.

Claude Code, Codex, OpenCode et DeepSeek Agent ont l’air de vendre un Coding Agent qui fait le travail. L’écart réel, c’est l’Agent Harness : qui possède un saut JSON Tool Calling, des arguments aux effets de bord.

Cet article explique :

Retenez ceci : La course 2026 n’est pas « qui complète la ligne suivante plus juste ». Le modèle émet un tool call ; les arguments sont du JSON. Le harness décide s’il peut parser, s’il faut demander, dans quel sandbox ça tourne, et comment le résultat revient. Claude Code ancre des hooks autour de chaque appel. Codex fait du sandbox et de l’approbation la frontière par défaut. OpenCode fait des modèles et des permissions une config interchangeable. DeepSeek Agent découpe tout le pipeline en plugins.

Ce qui se dispute vraiment, ce n’est pas la complétion

La complétion répond à « que mettre sur la ligne suivante ». Un Coding Agent répond à « comment finir cet objectif dans un vrai dépôt » : lire le contexte, choisir un outil, modifier le code, lancer une commande, lire le résultat, décider à nouveau.

Les quatre interfaces ressemblent à un chat. La boucle en dessous est presque la même :

La boucle Agent partagée par les quatre
User goal
  → Agent loop
  → LLM emits tool_call (JSON arguments)
  → Harness parses / validates / gates / executes
  → Tool result returns to context
  → Agent decides again

Le modèle raisonne et choisit « qui appeler ensuite ». Le harness décide quels outils le modèle voit, si les arguments comptent comme valides, si une action à haut risque exige un humain, ce que l’outil fait vraiment, comment la session est enregistrée, et ce qui compte comme terminé.

Les checklists de fonctionnalités vont se ressembler. Tout le monde a Skills, MCP, sous-agents et interrupteurs de permission. La différence, c’est où siège le contrôle. Pour le positionnement produit, voir Les AI Coding Agents ne se limitent plus à la complétion : que se disputent Codex, Claude Code, OpenCode et DeepSeek Harness ?. Pour le tour de la boucle, voir Comment fonctionnent les AI Coding Agents ?. Cet article ne découpe qu’un saut : ce que le harness fait après que le JSON Tool Calling a quitté le modèle.

Qu’est-ce qu’un Agent Harness

En 2026, la couche a un nom. Une anatomie du code source de onze Coding Agents de production l’appelle Harness Engineering : un Agent, c’est un modèle plus un harness — le runtime qui couple un LLM au monde réel par une boucle, des outils, du contexte, des contrôles de sécurité, de l’orchestration et des surfaces d’extension.

Une autre expérience de comparaison pose la question plus nettement : changer de harness fait-il résoudre plus de tâches au même modèle ? Les scores moyens restent souvent proches ; les tâches dépôt et les tâches concours peuvent partir en sens inverse ; coût et taux d’annulation changent. La leçon n’est pas « le harness natif gagne toujours ». C’est « vous achetez un chemin d’achèvement, pas un point au classement ».

Donc les quatre ne se disputent pas qui a livré un bouton de plus. Ils se disputent qui organise le plus clairement le contrat d’outil, la frontière d’exécution et le veto humain.

Couche Possède Ne possède pas
Modèle Choisir un outil, remplir les arguments JSON, lire le résultat, décider à nouveau Écrire le disque, lancer le shell, joindre le réseau, autoriser
Contrat JSON À quoi ressemblent arguments et résultats Si cet appel doit avoir lieu
Agent Harness Outils visibles, validation, approbation, sandbox, réinjection, session Inventer l’objectif métier à votre place

Pour les couches de la pile, voir Pile technique Agent IA 2026 : comment combiner LLM, MCP, Function Calling et JSON Schema ?.

Le fil commun : JSON Tool Calling

Le Tool Calling (aussi appelé Function Calling) n’est pas un autre nom pour « le modèle sait écrire du code ». C’est un appel structuré : le modèle choisit un nom dans les outils que vous avez déclarés, puis génère du JSON qui doit coller au contrat de paramètres.

Sur une API compatible OpenAI, le champ parameters de la définition d’outil est lui-même du JSON Schema :

Définition d’outil (parameters = JSON Schema)
{
  "type": "function",
  "function": {
    "name": "run_tests",
    "description": "Run the project test suite and return a structured summary.",
    "parameters": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "suite": { "type": "string", "enum": ["unit", "integration", "e2e"] },
        "path": { "type": "string", "minLength": 1 }
      },
      "required": ["suite"]
    }
  }
}

Quand le modèle répond, arguments est souvent une chaîne, pas un objet déjà parsé :

Un tool_call du modèle (arguments est une chaîne)
{
  "id": "call_7f21",
  "type": "function",
  "function": {
    "name": "run_tests",
    "arguments": "{\"suite\":\"e2e\",\"path\":\"tests/checkout.spec.ts\"}"
  }
}

Donc le harness fait au moins deux choses : parser la chaîne en JSON valide, puis vérifier champs, types et enums contre le schema que vous avez déclaré. Guillemets manquants, virgules en trop et clés non déclarées se jouent sur ce saut.

MCP branche le même fil sur un Server externe : inputSchema / outputSchema restent du JSON Schema, et tools/call reste un appel structuré. Plus de Servers, plus de descriptions et de schemas dans le contexte du modèle, plus de portes à tenir pour le harness. Pour le partage de sécurité, voir Vulnérabilités de sécurité MCP expliquées.

Le champ de bataille : sept sauts dans un tool call

Étalez les quatre produits : les noms de fonctionnalités diffèrent. Le tuyau a la même forme. La course, c’est qui tranche chaque saut :

  1. 1
    Présenter

    Quels outils et quelle tranche de schema entrent dans cette requête. Un outil invisible, le modèle ne peut pas l’appeler.

  2. 2
    Émettre

    Le modèle choisit un nom et génère une chaîne arguments. Ce saut ne dit que l’intention d’appeler.

  3. 3
    Parser

    La chaîne devient un objet. Un JSON invalide doit échouer avant la couche d’exécution.

  4. 4
    Valider

    Vérifier champs requis, types, enums et additionalProperties contre JSON Schema.

  5. 5
    Porte

    allow / deny / ask. Une forme valide n’est pas une autorisation.

  6. 6
    Exécuter

    Exécuter pour de vrai dans un sandbox, un espace de travail, ou les privilèges complets de l’hôte. Les effets de bord commencent ici.

  7. 7
    Réinjecter

    Le résultat devient du texte ou du JSON, s’enregistre dans la session, et nourrit le tour suivant. Les échecs ont aussi besoin d’une structure — pas seulement « ça a planté ».

Les quatre parcourent ces sept sauts. La différence : où atterrissent les hooks, à quel point le sandbox par défaut est serré, si le modèle se change, et si le tuyau lui-même se remplace.

Claude Code : des hooks avant et après l’appel

Claude Code renforce l’agent principal : Skills, MCP, sous-agents et CLAUDE.md s’enroulent autour du même Claude Agent. Ce qui mord vraiment le JSON Tool Calling, c’est le hook déterministe autour de chaque appel.

Dans le cycle de vie officiel, chaque appel d’outil de la boucle passe par PreToolUse et PostToolUse. On peut aussi intercepter l’invite de permission (PermissionRequest) ou décider après un échec si un retry est permis (PermissionDenied / PostToolUseFailure).

Le hook lit du JSON d’événement, pas de la prose. Il peut réécrire les entrées, refuser l’appel, demander confirmation, ou après succès ajouter des logs, lancer un formateur, et réinjecter du contexte. Il ne peut pas défaire un effet de bord déjà produit — PostToolUse arrive trop tard.

Les règles de permission se résolvent deny → ask → allow, et deny gagne. Un hook qui renvoie allow saute seulement l’invite interactive ; il ne passe pas outre une liste deny gérée par l’entreprise. Même avec bypassPermissions, un PreToolUse qui renvoie deny bloque encore l’appel.

Le compromis d’ingénierie est net : un agent probabiliste plus une porte déterministe. Lancer les tests après une modification, bloquer les commandes dangereuses, exiger une approbation sur les chemins protégés — le modèle ne doit pas « s’en souvenir » à chaque fois.

Convient si les workflows sont stables et que vous voulez ancrer Skills, sous-agents et hooks sur la boucle principale, et empaqueter l’expérience en unités réutilisables.

Codex : sandbox et approbation avant l’exécution

Codex (y compris Codex CLI) pousse la question à la couche d’exécution. Dès qu’un agent modifie des fichiers, lance le shell, installe des dépendances, et touche le réseau et les identifiants, il doit répondre à deux choses différentes à la fois : la frontière de capacité, et si cette action est permise maintenant.

Mécanisme Question tranchée Interrupteurs typiques
Sandbox Que peut-il techniquement toucher ou changer ? read-only / workspace-write / danger-full-access
Approval Cette action est-elle autorisée maintenant ? untrusted / on-request / never

Le récit par défaut, c’est le moindre privilège : d’abord serrer l’environnement, l’ouvrir au besoin. Un répertoire untrusted démarre en lecture seule. Une fois l’espace de travail de confiance, le preset courant est workspace-write plus on-request — lectures, écritures et commandes courantes dans l’espace de travail tournent toutes seules ; sortir de l’espace de travail ou toucher le réseau exige une approbation. Le réseau est fermé par défaut, à ouvrir explicitement.

Les versions récentes décrivent le système de fichiers et le réseau avec un permission profile. Ne pas le mélanger avec l’ancien sandbox_mode. Les noms changent. La découpe non : un cadran « ce qu’il peut toucher », l’autre « a-t-il le droit maintenant ».

Convient si les effets de bord sont lourds, que la trace d’exécution doit être auditable, et que l’isolation plus l’approbation sont des citoyens de première classe. Dépôt open source : openai/codex.

OpenCode : modèles interchangeables, permissions en config

La différence d’OpenCode n’est pas « encore une syntaxe Skills ». La posture par défaut : les modèles sont interchangeables. Licence MIT, terminal d’abord, plusieurs fournisseurs et modèles locaux. La flexibilité vit surtout dans la config — provider, model, permission, agent — pas dans l’éclatement du noyau harness en bus de plugins.

Les permissions sont passées du booléen précoce tools à permission : chaque action est allow, ask ou deny. On écrit des règles par nom d’outil, motif de commande, ou sortie de l’espace de travail (external_directory). La dernière correspondance gagne. Un sous-agent peut être plus strict que l’agent principal — un rôle review qui deny edit d’emblée, par exemple.

OpenCode écrit la porte en config JSON
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "git push *": "deny"
    },
    "edit": "allow",
    "external_directory": "deny"
  }
}

Il gagne en général sur : le multi-modèle par défaut, pas en extra vendeur ; une licence open source et une communauté ; « changer de modèle » comme opération de première classe. Le coût est clair : frontières d’exécution et profondeur de plugins ne sont pas automatiquement l’argument n°1. Vous achetez un harness à modèles interchangeables, pas le produit sandbox le plus lourd, ni un noyau de plateforme « Everything is a plugin ».

Convient si vous vous méfiez d’un seul fournisseur, ou qu’il faut changer de modèle — y compris des poids locaux — dans la même boucle.

DeepSeek Agent : le pipeline lui-même est un plugin

DeepSeek pousse la question d’un cran. Le produit en preview publique est DeepSeek Harness (dsh). Le contrat externe est l’interface Agent ; l’implémentation par défaut est un agent-loop remplaçable. Le slogan : Everything is a plugin — modèle, outils, Skills, session, sandbox, stockage, loop, scheduling et UI sont tous interchangeables.

Ce qui s’aligne sur Tool Calling, c’est le pipeline d’outils, pas une autre boîte de chat. Un ToolDefinition dans le registre porte des paramètres et sorties typés. Le modèle ne voit que name, description et parameters. execute, timeouts, drapeaux de concurrence et présentateurs UI ne doivent pas fuiter dans la requête.

Chaque appel emprunte une cascade fixe :

Le pipeline d’outils de DeepSeek Harness
tools/pre-execute   → allow / deny / ask
monotonic guards    → 只收紧,不能再放行
tools/execute       → 真正派发(可包超时 / 重试)
tools/post-execute  → 检查或替换结果
finalizeContent     → 定义自己的收尾
tools/result        → 冻结后的权威结果

Il peut passer par Function Calling natif, ou PTC (le run_code réservé comme transport ; les sous-appels restent dans le même pipeline). La concurrence se classe par appel : les exclusifs font barrière, les parallélisables entrent dans un pool borné ; les événements s’écrivent toujours dans l’ordre du modèle.

Convient si vous voulez le runtime lui-même comme plateforme, pas seulement un assistant plus fort. Pour la couche modèle, voir Qu’est-ce que DeepSeek V4-Pro ?.

Le même JSON, quatre portes

Le même JSON de tool call heurte une porte différente chez chaque produit :

Ce saut Claude Code Codex OpenCode DeepSeek Agent
Surface d’outils montrée au modèle Outils intégrés + Skills + MCP ; les schemas peuvent charger à la demande Boîte à outils de session + notes projet (AGENTS.md) Intégrés + MCP + recoupe par agent Un registre à périmètre projette ToolSchema via une liste d’autorisation
Avant que arguments atteigne l’exécution Les hooks peuvent lire le JSON d’événement tool complet D’abord la capacité sandbox, puis la politique d’approbation Les règles permission filtrent nom d’outil et entrée Après le parse, la cascade pre-execute et les gardes monotones
Comment un humain oppose son veto PermissionRequest ; deny bat un allow de hook on-request / untrusted ; peut passer à un relecteur ask ; un sous-agent peut être plus strict Une décision ask est un résultat de première classe dans le pipeline
Où se produisent les effets de bord Outils locaux + post-hooks Sandbox OS ; pas de réseau par défaut, espace de travail inscriptible Exécution locale, snapshots git, undo Un plugin sandbox remplaçable
Comment les résultats reviennent PostToolUse / hooks d’échec ajoutent du contexte Événements JSONL, faciles à auditer en CI Les diagnostics LSP peuvent réentrer dans la boucle tools/result se fige, puis le journal de session

La dernière ligne n’est pas un classement. Vous achetez un agent principal plus utilisable, un environnement d’exécution plus contrôlable, une couche de config à modèles interchangeables, ou un runtime composable.

Pour la vue produit de la carte du contrôle, voir les quatre centres d’architecture. Pour qui porte la sécurité une fois que MCP élargit la surface d’outils, voir Quand les AI Agents commencent à attaquer Internet : comment JSON devient une frontière de sécurité.

Pourquoi encore regarder JSON Schema

Aussi forts soient les quatre harness, des paramètres sales dans la couche d’exécution deviennent des incidents. Les arguments remplis par le modèle sont une contrainte souple : arguments peut être du JSON cassé, manquer des champs, ou ajouter des clés non déclarées.

Valide pour le schema n’est pas autorisé. Les deux extraits ci-dessous passent un schema lâche qui n’exige qu’un champ sql. Seul le côté serré range l’opération en enum et écrit l’identifiant en pattern :

Contrat lâche vs contrat serré
{
  "loose": {
    "type": "object",
    "properties": { "sql": { "type": "string" } },
    "required": ["sql"]
  },
  "tight": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "op": { "type": "string", "enum": ["get_user_by_id"] },
      "user_id": { "type": "string", "pattern": "^[a-z0-9-]{8,36}$" }
    },
    "required": ["op", "user_id"]
  }
}

Comment écrire le contrat, et en quoi JSON Mode diffère de Strict Schema, voir Pourquoi l’IA a besoin de JSON Schema ? Structured Output, Function Calling et JSON Schema, et Pourquoi les AI Agents ont besoin de JSON Schema ? De Tool Calling à Structured Output.

Découper un tool call dans JSONNote

Le matériau de debug le plus utile est souvent une tranche de JSON : la définition d’outil, les arguments du modèle, les événements de hooks, la raison du deny. Vous pouvez tout ouvrir en local dans le navigateur. Pas besoin d’envoyer le dépôt.

  1. 1
    D’abord voir si arguments est du JSON valide

    Dépliez les échappements de la chaîne et déposez-la dans Formatage JSON. Virgules manquantes, virgules finales et guillemets simples explosent ici.

  2. 2
    Valider contre le schema déclaré

    Mettez les parameters / inputSchema de l’outil et l’objet parsé dans JSON Schema. Voyez si un champ manque, si le type est faux, ou si une clé non déclarée a été ajoutée.

  3. 3
    Différencier « ce que vous avez approuvé » et « ce que c’est maintenant »

    Mettez la liste d’outils de la semaine dernière et celle d’aujourd’hui dans JSON Diff et cherchez surtout les changements silencieux de description et de schema.

  4. 4
    Il faut le montrer à un collègue ? Utilisez le partage Hash

    Les données restent dans le fragment d’URL et ne touchent aucun serveur. Voir Partager du JSON via URL Hash.

FAQ

Que se disputent vraiment Claude Code, Codex, OpenCode et DeepSeek Agent ?

Pas une checklist de fonctionnalités, ni qui complète la ligne suivante plus juste. L’enjeu, c’est l’Agent Harness : qui possède un saut JSON Tool Calling, du parse et du contrat jusqu’à l’approbation, l’exécution sandboxée et la réinjection du résultat.

Qui compte le plus, l’Agent Harness ou le modèle ?

Le modèle raisonne et choisit l’étape suivante. Le harness décide quels outils sont visibles, si les arguments sont valides, si une action à haut risque exige un humain, et où se produisent les effets de bord. Changer de harness ne garantit pas un score moyen plus haut, mais le chemin d’achèvement, le coût et le taux d’annulation changent. Vous choisissez le contrôle, pas un score.

Lequel des quatre choisir ?

Il n’y a pas de champion unique. Hooks déterministes et permissions sur l’agent principal → Claude Code. Sandbox et approbations comme frontière d’exécution par défaut → Codex. Changer de modèle et éviter le verrouillage → OpenCode. Loop, pipeline d’outils et sandbox en plugins remplaçables → DeepSeek Agent (DeepSeek Harness).

Le JSON Tool Calling inclut-il une autorisation ?

Non. Le modèle qui choisit un nom d’outil et remplit arguments ne dit que son intention d’appeler. Bloquer, dans quel sandbox, et renvoyer le résultat au modèle : c’est l’affaire du harness. Sans outil, si la permission est refusée ou si la validation JSON échoue, rien ne se passe sur le disque.

Pourquoi encore valider JSON Schema soi-même ?

Les arguments remplis par le modèle sont une contrainte souple. arguments est souvent une chaîne : champs manquants, mauvais type, ou clés non déclarées. Valide pour le schema n’est pas autorisé. La production a toujours besoin de parse plus validation, puis permissions et sandbox. Aussi forts soient les quatre harness, des paramètres sales dans la couche d’exécution deviennent des incidents.

Résumé

La course des Coding Agents 2026 a l’air d’une guerre de modèles. Dans un dépôt, c’est une guerre de harness.

Le modèle émet du JSON. Le harness décide si ce JSON peut devenir un effet de bord. Les quatre se disputent le contrôle du même tuyau : Claude Code ancre les hooks, Codex serre la frontière d’exécution, OpenCode déverrouille le modèle, DeepSeek Agent fait du runtime lui-même des plugins.

Les fonctionnalités vont continuer à se ressembler. Ce qu’il faut vraiment regarder : qui tranche après qu’un tool call a quitté le modèle.

Ensuite : coller les arguments d’un tool call dans JSONNote

← Retour au blog