Le 13 août 2026, DeepSeek a publié DeepSeek Harness en même temps que son modèle V4-Pro. Licence MIT, code en TypeScript, commande dsh, statut developer preview v0.1. Le repo est public sur GitHub.
L'information est dans le nom du projet. DeepSeek résume sa propre thèse en quatre mots : "Agent = Model + Harness". Un modèle seul ne fait rien pour une entreprise. Ce qui transforme ce modèle en agent IA capable d'agir sur des données réelles, c'est tout ce qui l'entoure. Et c'est précisément cette couche que DeepSeek vient de rendre publique, et modulaire.
J'ai installé DSH et j'y ai porté SilverBackBase, ma bibliothèque d'outils marketing, pour en faire un agent IA spécialisé en analyse lead-gen. La mesure qui m'a décidé à continuer : le coût en tokens des schémas d'outils est tombé de 77,9 % par rapport au même jeu de capacités exposé en MCP. Je détaille cette mesure et ce qui a cassé en chemin plus bas.
Un harnais IA, aussi appelé harnais agentique (agent harness en anglais), est la couche logicielle qui entoure un modèle de langage pour le transformer en agent IA opérationnel. Il regroupe l'accès en lecture aux données de l'entreprise, la liste des outils que le modèle a le droit d'appeler, la mémoire de la session en cours, les droits d'exécution accordés (ce que le modèle peut modifier seul, sans validation humaine) et l'isolation technique (sandbox) qui empêche une erreur de sortir du périmètre autorisé. Le modèle raisonne. Le harnais décide ce qu'il a le droit de voir et ce qu'il a le droit de faire.
Concrètement, un harnais contient toujours ces cinq briques :
Sans ces cinq briques, un modèle de langage répond à des questions. Avec elles, il devient un agent IA qui agit.
DSH n'est pas lié au seul modèle DeepSeek. Il supporte nativement plusieurs fournisseurs : DeepSeek, Anthropic, OpenAI, Bedrock, Vertex, Azure, et des endpoints personnalisés. Le harnais et le modèle sont deux choses distinctes, et DeepSeek le prouve en rendant son propre harnais compatible avec les modèles concurrents.
Trois choix techniques méritent d'être notés. La gestion du contexte se fait par un journal de session en ajout seul (append-only) : tout ce que le modèle voit doit pouvoir être reconstruit depuis ce flux, ce qui rend la session traçable après coup. L'isolation est native par système d'exploitation : bwrap et Landlock sur Linux, Seatbelt sur macOS, listes de contrôle d'accès par session sur Windows. Si l'isolation n'est pas disponible, DSH échoue explicitement avec une erreur SANDBOX_UNAVAILABLE, plutôt que d'exécuter en silence hors du bac à sable. DSH peut déléguer à des sous-agents IA, y compris en appelant d'autres CLI d'agents IA comme Claude Code ou Codex en sous-processus.
Le positionnement est direct. DeepSeek décrit Claude Code et Codex comme des agents IA de codage largement fermés et opinionés, avec des workflows fixes. DSH inverse la logique : le harnais est décomposable et recomposable, pièce par pièce.
Le principe fondateur de DSH tient en trois mots : "Everything is a plugin". Le modèle, le sandbox, les outils, la boucle agentique, la planification et l'interface sont tous des plugins interchangeables, montés sur un micro-noyau nommé Cordis.
Le modèle devient une pièce parmi d'autres, pas le centre du système. On peut faire tourner le même harnais avec DeepSeek un jour, un autre fournisseur le lendemain, et un modèle interne le mois suivant, sans reconstruire l'infrastructure autour. La question qui compte se déplace. Elle n'est plus "quel modèle je choisis", elle devient "qu'est-ce que je branche dessus".
C'est un renversement de priorité, pas un détail d'architecture. Choisir un modèle est une décision qui se refait tous les six mois, au rythme des sorties de nouvelles versions. Construire l'accès aux données réelles de l'entreprise, les droits d'exécution et les intégrations métier est une décision qui structure durablement le système.
C'est là que l'annonce sort du cercle technique. Prenons trois métiers concrets.
Un cabinet comptable qui veut qu'un agent IA prépare les déclarations de TVA n'est pas bloqué par le choix du modèle. Il est bloqué par l'accès aux relevés bancaires réels, aux factures classées, et par la question de savoir si l'agent IA a le droit de valider seul une écriture ou seulement de la proposer.
Une entreprise de dépannage qui veut qu'un agent IA qualifie les appels entrants et propose un créneau n'est pas bloquée par le modèle. Elle est bloquée par l'accès à l'agenda réel des techniciens, à l'historique client, et par la question de savoir si l'agent IA a le droit de confirmer un rendez-vous seul ou doit toujours passer par un humain.
Une agence immobilière qui veut qu'un agent IA réponde aux demandes de visite n'est pas bloquée par le modèle. Elle est bloquée par l'accès au mandat réel du bien, à la disponibilité du vendeur, et par la question de savoir si l'agent IA peut envoyer une confirmation de rendez-vous seule.
Dans les trois cas, le blocage est le même : l'accès aux données réelles et les droits d'action. Jamais le modèle. Le modèle est la partie qui se déprécie et se remplace tous les six mois. Le harnais est la partie qui se capitalise, parce qu'il encode les connexions aux systèmes réels de l'entreprise, ses règles métier et ses limites d'autonomie. Ce qu'un harnais bien construit rend explicite (qui a accès à quoi, qui a le droit de faire quoi), la plupart des entreprises ne l'ont même pas encore formalisé pour leurs propres équipes humaines.
Non, et DeepSeek le dit lui-même. C'est une developer preview avec des ruptures de compatibilité annoncées. Les contrats de plugins sont encore instables. Aucune pull request externe n'est acceptée à ce stade, ce qui veut dire que la licence MIT ne se traduit pas encore par une gouvernance réellement ouverte. La chaîne de dépendances npm n'est pas éprouvée. Et la hausse des prix API de V4-Pro annoncée à partir du 16 août 2026 relativise l'argument "DeepSeek, c'est le coût cassé".
Un chiffre circule pour illustrer l'écart de performance entre harnais : un même modèle obtiendrait 58% de réussite avec un harnais contre 81,8% avec un autre, selon un ordre de grandeur rapporté par SFEIR citant une étude d'avril 2026. Ce n'est pas un benchmark mesuré par mes soins, donc à prendre comme un signal directionnel, pas comme une donnée établie. Mais le sens de la tendance est clair : le harnais pèse autant, sinon plus, que le modèle sur le résultat final. MindStudio documente la même mécanique côté harnais de codage.
Je suis passé par la voie courte, une seule commande, sans installation préalable :
npx @deepseek-ai/dsh webPour lire le code du noyau et écrire mes propres plugins, je suis ensuite passé par les sources :
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh webDans les deux cas, DSH démarre une interface web sur http://127.0.0.1:3080 et l'ouvre dans le navigateur. Le flag --no-open empêche cette ouverture automatique. À la première connexion, l'interface demande une clé API DeepSeek.
Trois points ne sont pas documentés publiquement à ce jour, et je préfère le dire plutôt que recopier ce que des sites tiers affirment sans se recouper : la version minimale de Node.js exigée, le nom exact d'une éventuelle variable d'environnement pour la clé API, et la liste des systèmes d'exploitation officiellement supportés. Sur ces trois sujets, les sources secondaires se contredisent frontalement entre elles.
DSH expose quatre modes, qui sont quatre façons d'utiliser le même harnais.
Creator est le plus intéressant des quatre, parce qu'il matérialise la thèse du projet : on y ouvre le harnais lui-même pour le modifier pendant qu'il tourne. La commande exacte pour l'activer n'apparaît dans aucune source officielle à ce jour. Ce qui est documenté, c'est le paramètre --profile, avec deux profils fournis, web pour l'interface navigateur et headless pour une exécution ponctuelle sans serveur. Profils et modes restent deux notions distinctes dans la documentation, et le lien entre les deux est encore à écrire.
Pour inspecter l'arbre de plugins réellement chargés :
dsh --profile web --dump-configUn plugin Cordis est une fonction qui reçoit le contexte de l'application. Voici le plugin minimal donné par le tutoriel officiel, dans un fichier hello.ts :
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello'
export function apply(ctx: Context) {
console.log('hello from my first plugin')
}Il se déclare dans un fichier cordis.yml :
- name: './hello.ts'Le tutoriel le lance ensuite avec node --import tsx ../../vendor/cordis/bin.js, une commande dont les chemins relatifs n'ont de sens que depuis le répertoire d'exercice du dépôt cloné.
Cordis accepte trois formes de plugin : la fonction ci-dessus, un objet doté d'une méthode apply, et une classe qui étend Service. Les services s'accrochent à des clés stables du contexte (ctx.tools, ctx.llm, ctx.sessions) et déclarent leurs dépendances via inject.
C'est là que "tout est un plugin" cesse d'être un slogan. Ajouter un outil à l'agent IA, changer sa façon de gérer la mémoire de session ou remplacer le modèle derrière deviennent le même geste : écrire un fichier, et le déclarer dans la configuration.
J'ai porté SilverBackBase en plugins natifs de ce harnais. L'agent IA qui en sort est spécialisé sur un seul métier, l'analyse lead-gen : il lit l'attribution multi-touch, les positions locales, le comportement dans les pages, la mémoire business du client et l'historique des actions déjà tentées. C'est le marketeur agentique rendu concret, dans une architecture où chaque couche a son rôle. Et c'est un chantier en phase de test, pas un produit en production.
Ces primitives étaient déjà accessibles par un serveur MCP, et c'est le chemin le plus court pour brancher des outils sur un agent IA. La limite est ailleurs : en MCP, le schéma de chaque outil est envoyé au modèle à chaque tour de conversation. Cinquante outils exposés, ce sont cinquante schémas payés à chaque échange, dont la plupart ne serviront pas.
J'ai mesuré l'écart sur mon propre système. Cinquante-trois primitives exposées en MCP direct représentent 67 795 octets de schémas, soit environ 16 949 tokens par tour. Les mêmes capacités portées en trente-neuf outils natifs, avec des schémas écrits pour être compacts et des sorties projetées plutôt que du JSON brut, tombent à 14 975 octets, soit environ 3 744 tokens. Une baisse de 77,9 %.
Deux effets se cumulent ici, et autant le dire plutôt que de laisser croire à un gain purement mécanique : les schémas natifs sont plus compacts, et j'en ai profité pour regrouper cinquante-trois primitives en trente-neuf outils mieux découpés. La mesure reste reproductible, le script de comparaison vit dans le dépôt.
Voici l'outil qui résout un nom de client prononcé par un humain vers son identifiant interne. C'est le point d'entrée de tous les autres.
ctx.tools.register(defineTool({
name: "sbb_clients",
description:
"Liste les clients du workspace SilverBackBase avec leur project_id, leur domaine et l'etat du "
+ "tracking Trail. A appeler quand on ignore quels clients existent, ou pour verifier une couverture.",
parameters: {},
output: {
schema: { type: "array", items: CLIENT_SHAPE },
render: (_args, value) => [{
type: "text",
text: value.length === 0
? "Aucun client dans ce workspace."
: value.map(line).join("\n"),
}],
},
isConcurrencySafe: () => true,
async execute(_args, exec) {
return listClients(exec.signal);
},
}));Deux détails portent l'essentiel du gain. execute renvoie la valeur canonique, tandis que output.render décide de ce que le modèle voit réellement. Séparer les deux évite de payer un JSON complet en tokens quand trois lignes de texte suffisent au raisonnement. La projection est obligatoire chez moi : aucun outil ne rend du JSON brut au modèle.
En tête de module, le plugin déclare ce dont il a besoin : export const inject = ["tools", "sbbGateway"]. Le premier est le service d'outils du noyau, le second est ma propre passerelle vers SilverBackBase, montée elle aussi comme un service. Cordis fait attendre les plugins dépendants jusqu'à ce que le service soit disponible, ce qui rend l'ordre de montage non signifiant.
Les plugins se déclarent dans un fichier de patch qui vient modifier la configuration par défaut du harnais. Extrait :
- id: tool-ralph
disabled: true
- id: tool-workflow
disabled: true
- insert:
- id: sbb-gateway
name: '@silverbackbase/dsh-gateway'
- insert:
- id: sbb-persona
name: '@silverbackbase/dsh-persona'
inject: [systemPrompt]
- insert:
- id: sbb-clients
name: '@silverbackbase/dsh-clients'
inject: [tools, sbbGateway]
- id: sbb-trail
name: '@silverbackbase/dsh-trail'
inject: [tools, sbbGateway]La passerelle est montée en premier, sans inject, parce qu'elle est elle-même un service : les sept plugins métier la réclament ensuite par leur inject.
Une sémantique à connaître avant d'y toucher : une clé config remplace la configuration ciblée au lieu de fusionner avec elle, et il n'existe aucune opération de suppression. On désactive, puis on insère. Un identifiant introuvable produit un avertissement sur la sortie d'erreur, pas un échec, ce qui laisse passer une faute de frappe sans bruit.
J'ai écrit un avertissement dans ce fichier. Il ne donne pas le flag du mode Creator, qui reste non documenté, mais il éclaire pourquoi ce mode existe à part : ne jamais monter @deepseek-ai/dsh-tool-cordis dans un profil de travail. Cet outil laisse le modèle écrire un plugin et le lancer dans le process vivant. C'est exactement ce qui rend le harnais malléable, et exactement ce qu'on ne veut pas mettre entre les mains d'un agent IA qui manipule des données client.
La partie utile d'un chantier en cours, ce sont les endroits où ça coince. Voilà ce que j'ai réglé, et ce qui reste ouvert.
Un champ privé natif casse à travers le proxy du noyau. C'est le piège le plus coûteux que j'aie rencontré. Cordis enveloppe les services dans un proxy traçable qui substitue this par un objet fantôme. Un champ déclaré avec la syntaxe privée native de JavaScript, le # devant le nom, devient alors inaccessible : il faut se rabattre sur un private TypeScript ordinaire, qui n'est qu'une convention au moment de l'exécution. Rien ne prévient, l'erreur arrive loin de sa cause.
Un schéma de configuration invalide tue le plugin avant qu'il ne démarre. Depuis que chaque plugin déclare son schéma, le noyau refuse de lancer le module si un paramètre attendu manque, sans jamais entrer dans la fonction d'initialisation. Le message n'indique pas le champ fautif.
La résolution de modules remonte l'arborescence depuis le répertoire de profil. Un dossier de travail situé hors de tout node_modules ne trouve rien, et ça peut marcher par coïncidence pendant les tests si on développe au mauvais endroit. La ligne de commande pose désormais les liens symboliques nécessaires.
Deux erreurs de débutant m'ont coûté du temps et sont maintenant derrière moi. Un inject laissé vide, et le noyau refuse net : cannot get property "tools" without inject. La dépendance se déclare, elle ne se devine pas. Et un fichier de patch posé au mauvais endroit reste sans effet, parce qu'il est chargé avant celui du profil et n'a donc rien à surcharger.
Une supposition sur la forme des données, corrigée en testant. Mes projections attendaient le camelCase de l'API REST de GA4 alors que le serveur rendait du snake_case. L'agent IA annonçait sereinement "aucune donnée" sur des comptes qui en avaient. Trouvé en le lançant contre huit comptes réels, pas en relisant le code.
Ce qui reste ouvert : le process en mode sans interface ne se termine pas après avoir répondu. Je n'ai pas encore diagnostiqué la cause, et je le tue à la main. C'est le genre de détail qui interdit de brancher tout ça sur une tâche planifiée.
Aucun test automatisé pour l'instant, une vérification entièrement manuelle contre des données réelles, et pas une ligne publiée sur npm. C'est l'état honnête du chantier au moment où j'écris.
Le harnais n'est pas un concept abstrait à comprendre plus tard. C'est un exercice à faire maintenant, sur une tâche précise qu'un agent IA devrait pouvoir exécuter dans l'entreprise. Trois lignes suffisent :
Ces trois lignes, c'est le harnais. Le modèle qu'on branche derrière est, de loin, la décision la moins importante des trois.