Kimi K3 sur Moonshot en tant qu’agent de programmation : l’intégrer à OpenClaw, le comparer à dsh via des tests de performance, et lui demander de créer un widget de logo en pixel art.

Publié
12 septembre 2026
Mis à jour
12 septembre 2026
Par
Jacob Lloyd — rédigé avec l'aide de l'IA, une fois le projet terminé
Temps de lecture
31 min de lecture

En clair : J’ai intégré le modèle de raisonnement Kimi K3 de Moonshot dans le logiciel d’agent que j’utilise chez moi. Je lui ai donné les mêmes cinq petites tâches de programmation que celles utilisées en août pour tester l’assistant de codage DeepSeek (dsh), et je lui ai demandé de créer une version en pixel-art du logo de ce site, en me basant sur le même cahier des charges écrit. Il a réussi les cinq tâches, mais il lui a fallu environ neuf fois plus de temps et il a coûté environ 48 fois plus cher que dsh utilisant le modèle rapide de DeepSeek. Pour créer le widget du logo, trois tentatives ont été nécessaires. La première a duré environ neuf minutes sans produire de résultat. La deuxième a effectivement généré un widget fonctionnel, mais celui-ci a été placé dans le mauvais dossier ; en outre, le temps imparti s’est écoulé avant que l’IA ne me le signale, si bien que je ne l’ai découvert que plus tard. La troisième tentative a abouti après que j’aie raccourci le cahier des charges et demandé au système de sauter la phase de planification.

J’ai dirigé mon agent de travail OpenClaw vers Kimi K3, le modèle de raisonnement phare de Moonshot, et je l’ai soumis aux mêmes cinq petites tâches de programmation que j’avais utilisées en août pour évaluer DeepSeek Harness (dsh). Kimi les a toutes réussies. Comparé à dsh exécuté sur DeepSeek V4-Flash, le même jour et sur les mêmes cinq tâches, Kimi a mis environ 9 fois plus de temps pour y parvenir (309,9 s contre 35,7 s) et a coûté environ 48 fois plus cher ($0,531 contre $0,011). Ensuite, je lui ai donné le cahier des charges relatif à la création d’un logo en pixel art dont dsh s’était servi pour générer son propre widget. Kimi a eu besoin de trois tentatives. La première, avec le cahier des charges tel quel, n’a produit aucun widget. La deuxième, avec le même cahier des charges, a généré un widget complet mais dans le mauvais dossier ; mon délai d’attente s’est écoulé avant que Kimi ne le signale, si bien que je ne m’en suis pas rendu compte au début. La troisième tentative a abouti après que j’ai raccourci le cahier des charges et demandé à Kimi de sauter les phases de planification.

Essayez-le. Voici le widget créé par Kimi K3 lors de sa troisième tentative, tel qu’il l’a généré. Survolez-le puis cliquez dessus. Le détail du processus de création se trouve plus bas.

Résumé

  • Qu’est-ce que c’est ? Kimi K3 utilisé via l’API compatible OpenAI de Moonshot, pilotant la boucle d’agent native d’OpenClaw (je nomme cela le « Chemin A »). Il ne s’agit pas de l’application serveur Codex : le plugin associé à Codex n’accepte que les routes fournisseurs OpenAI (vérifié dans le code même d’OpenClaw 2026.9.2).
  • Configuration : plugin fournisseur Moonshot (@openclaw/moonshot-provider version 2026.9.2), URL de base https://api.moonshot.ai/v1, variable d’environnement MOONSHOT_API_KEY dans le passerelle. Mon paramétrage permet d’utiliser les niveaux de effort de raisonnement low, high et max, interdit l’utilisation du paramètre temperature, et limite le contexte à 262 144 tokens au lieu des 1 048 576 annoncés.
  • Benchmark : cinq tâches, dans des dossiers neufs. Kimi K3 : 5/5, 309,9 s, $0,531. dsh sur V4-Flash, lors d’une deuxième exécution (en mode chaud) sur les mêmes cinq tâches : 5/5, 35,7 s, $0,011.
  • Création du widget : trois tentatives. La première s’est arrêtée après 8,8 minutes sans aucun code de widget. La deuxième a généré un widget complet de 323 lignes ainsi que ses propres tests, mais dans l’espace de travail de l’agent et non dans le dossier visé ; le délai d’attente de 15 minutes s’est écoulé avant que Kimi ne signale quoi que ce soit. La troisième tentative, avec un cahier des charges raccourci indiquant TARGETED — write the widget file in one tool call, no exploration, no planning, no verification loop., s’est achevée en 7,4 minutes pour un coût de $0,47. Le widget affiché sur cette page provient de cette troisième tentative ; il passe le test node --check et se charge sans erreur.
  • Coûts et cache : 80 % des tokens du prompt utilisés par Kimi provenaient du cache. Sans ce dernier, la même exécution aurait coûté environ $1,49 au lieu de $0,53. Les tarifs sont de $3 pour l’entrée, $15 pour la sortie et $0,30 par million de tokens lus depuis le cache.
  • Position actuelle de Kimi : Kimi a servi de modèle pour mon agent de travail dans le cadre de ce benchmark. Au 11 septembre 2026, mon agent de travail utilise désormais MiniMax-M3 ; Kimi K3 continue toutefois de soutenir mon agent de relecture.

Chemin A vs Chemin B, honnêtement

Tout ce qui suit relève du Chemin A : Kimi K3 pilote la boucle d’agents d’OpenClaw via le fournisseur Moonshot. Sur ma machine, le fournisseur était déjà configuré ; il suffisait donc de changer le modèle utilisé pour basculer sur Kimi.

Le Chemin B consisterait à faire passer Kimi par le vrai Codex app-server, exécuté via le plugin Codex d’OpenClaw (ce plugin gère @openai/codex 0.153.4). Je ne l’ai pas développé, et rien dans cet article ne passe par Codex. La raison en est dans le code du plugin : sa fonction de vérification des routes, configuredModelRouteNeedsCodex, renvoie false pour tout fournisseur dont l’identifiant normalisé n’est pas openai. L’identifiant du fournisseur Moonshot étant moonshot, aucune requête vers moonshot/kimi-k3 ne parvient au runtime Codex.

La solution connue est codex-router, un pont local qui redirige les requêtes Codex vers un point de terminaison sur 127.0.0.1:4202 afin de les transmettre à Kimi (selon son README). Pour que le harnais OpenClaw détecte cette configuration, il faut que la valeur de appServer.homeScope dans le plugin soit "user". Cela partage alors votre dossier natif ~/.codex (ou $CODEX_HOME) avec le harnais, au lieu d’isoler l’état Codex par agent OpenClaw. Je n’ai pas encore décidé si cela me convient ; donc le Chemin B reste théorique pour l’instant.

Le Chemin A présente toutefois des limites à connaître. Les rapports de tour contiennent agentHarnessId: "openclaw", dans le même format que pour tout autre modèle natif d’OpenClaw. Vous ne bénéficiez pas de la reprise des threads Codex, du mécanisme de compactage propre à Codex, du pont outil dynamique, ni du modèle d’exécution propre à l’app-server. Si vous avez besoin de ces fonctionnalités, le Chemin B est alors la seule option.

Configuration : sur quoi je l’ai exécuté

Voici les commandes que j’ai exécutées sur ma machine le 11/09/2026, ainsi que leurs sorties réelles :

$ node -v
v24.18.0
$ openclaw --version
OpenClaw 2026.9.2 (3928bad)
$ dsh --version
0.1.1-rc.2
$ openclaw plugins list --json | jq -c '.plugins[] | select(.id=="moonshot") | {id, enabled, version}'
{"id":"moonshot","enabled":true,"version":"2026.9.2"}
$ openclaw config get models.providers.moonshot.models.0.compat
{
  "supportsReasoningEffort": true,
  "supportsTemperature": false,
  "supportedReasoningEfforts": [
    "low",
    "high",
    "max"
  ]
}
$ openclaw config get models.providers.moonshot.models.0.contextTokens
262144

Trois points importants à savoir avant d’exécuter quoi que ce soit :

  • K3 effectue toujours un raisonnement. Le plugin envoie par défaut reasoning_effort: "max" et accepte les valeurs low, high et max ; j’ai lancé le benchmark avec --thinking max. K3 supprime également les paramètres de sampling (temperature, top_p, etc.) car il les fixe lui-même ; ma configuration du modèle indique d’ailleurs la même chose via supportsTemperature: false. Même pour une instruction du type « Répondez exactement : PONG. », 53 tokens de raisonnement ont été générés.
  • Le contexte de 1 million de tokens est annoncé, mais je le limite. Le catalogue Moonshot d’OpenClaw indique que K3 supporte jusqu’à 1 048 576 tokens de contexte. J’ai toutefois défini contextTokens: 262144 dans la configuration du modèle, afin que les sessions se compactent au même point que pour mes autres modèles. En pratique, cette limite correspond à 256 000 tokens, et non à 1 million.
  • Le cache joue un rôle clé sur le coût. Chaque tâche débute avec environ 15 000 tokens provenant du prompt système et des définitions d’outils. Après la première étape, la plupart de ces données sont lues depuis le cache, à un coût de 0,30 $ par million de tokens au lieu de 3 $. Pour la tâche de renommage, les lectures provenant du cache se sont elles-mêmes élevées à 157 952 tokens.

La procédure, du niveau de base à l’avancé

Les étapes 1 à 3 vous permettent d’obtenir un modèle fonctionnel. Les étapes 4 et 5 correspondent à ce que j’ai fait ensuite.

Étape 1 : installer le plugin et lui fournir la clé

Il s’agit des étapes décrites dans la documentation Moonshot d’OpenClaw. Sur ma machine, le plugin et la clé étaient déjà en place ; j’ai donc simplement exécuté la vérification indiquée à la dernière ligne (son résultat figure dans le bloc de configuration ci-dessus).

openclaw plugins install @openclaw/moonshot-provider
openclaw gateway restart
openclaw plugins list --json | jq -c '.plugins[] | select(.id=="moonshot") | {id, enabled, version}'

Le plugin lit la clé depuis MOONSHOT_API_KEY. Je la conserve dans le fichier d’environnement chargé par mon service de passerelle ; mon fichier openclaw.json ne contient quant à lui aucune clé. La documentation propose également openclaw onboard --auth-choice moonshot-api-key si vous préférez suivre une procédure guidée. Le point de terminaison par défaut est https://api.moonshot.ai/v1, et la région Chine utilise https://api.moonshot.cn/v1 (option d’authentification moonshot-api-key-cn).

Le catalogue du plugin inclut K3, K2.7 Code et K2.7 Code HighSpeed. Il gère automatiquement les particularités liées à Kimi : pour K2.7, il faut omettre à la fois thinking et reasoning_effort dans la requête, ce que le plugin fait pour vous. Faites attention au nom de la variable d’environnement : MOONSHOT_API_KEY correspond à la plateforme Open d’Moonshot, tandis que KIMI_API_KEY concerne le service Kimi Code (kimi/kimi-for-coding).

Étape 2 : orientez votre agent worker vers K3

Voici les parties pertinentes de mon fichier openclaw.json lors du benchmark, avec mon agent worker renommé en worker :

{
  agents: {
    entries: {
      worker: {
        model: {
          primary: "moonshot/kimi-k3",
          fallbacks: ["deepseek/deepseek-v4-flash", "deepseek/deepseek-v4-pro"],
        },
      },
    },
  },
  models: {
    providers: {
      moonshot: {
        baseUrl: "https://api.moonshot.ai/v1",
        api: "openai-completions",
        timeoutSeconds: 1200,
        models: [
          {
            id: "kimi-k3",
            name: "Kimi K3",
            reasoning: true,
            input: ["text", "image"],
            cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 },
            contextWindow: 1048576,
            maxTokens: 131072,
            contextTokens: 262144,
            compat: {
              supportsTemperature: false,
              supportsReasoningEffort: true,
              supportedReasoningEfforts: ["low", "high", "max"],
            },
          },
        ],
      },
    },
  },
}

Un piège m’a causé une régression silencieuse : dans OpenClaw 2026.9.2, un bloc compat dans votre entrée de modèle remplace l’objet compat propre au plugin. Il ne se fait pas de fusion. Une version antérieure de mon entrée ne spécifiait que supportsTemperature: false, ce qui a fait disparaître silencieusement la prise en charge du paramètre reasoning-effort par le plugin. Si vous écrivez un champ compat, veillez à indiquer l’intégralité de l’objet, comme ci-dessus.

La ligne contextTokens: 262144 correspond à la limite indiquée dans les notes de configuration. Si vous augmentez cette valeur, attendez-vous à une augmentation des coûts liés à la lecture du cache ainsi qu’à la latence par tour de conversation au fil de la session.

Étape 3 : le test de vérification, et le JSON qu’il génère

Chaque tâche de benchmark correspondait à un appel de ce type, avec une clé de session nouvelle à chaque fois :

openclaw agent --agent <your-agent-id> --model moonshot/kimi-k3 --thinking max \
  --session-key "<fresh-key>" --message-file prompt.txt --json > out.json

Voici les champs importants, extraits de l’enveloppe enregistrée pour la tâche PONG :

$ jq '.result | {harness: .meta.agentMeta.agentHarnessId, model: .meta.executionTrace.winnerModel, usage: .meta.agentMeta.usage}' out.json
{
  "harness": "openclaw",
  "model": "kimi-k3",
  "usage": {
    "input": 15068,
    "output": 70,
    "reasoningTokens": 53,
    "total": 15138,
    "cost": {
      "total": 0.046254
    }
  }
}

harness: "openclaw" est la signature du Chemin A. Un tour exécuté via le serveur d’applications Codex indiquerait "codex". winnerModel: "kimi-k3" confirme que le tour a bien été exécuté sur K3 et n’a pas fait appel à un modèle moins coûteux. reasoningTokens se compte dans output (le total correspond à l’entrée plus la sortie) ; ainsi, les 53 tokens de raisonnement font partie des 70 au total.

Comparaison : Kimi K3 dans OpenClaw vs dsh

Il s’agit des deux boucles d’agents capables de lire des fichiers, d’exécuter des commandes shell et de facturer au nombre de tokens utilisés. Ils diffèrent toutefois par leurs créateurs ainsi que par la manière de les piloter.

Kimi K3 dans OpenClaw (Chemin A)dsh
CréateurModèle : Moonshot AI. Boucle d’agent : OpenClawDeepSeek (modèle et harnais), MIT
Appel depuis un scriptopenclaw agent --agent <id> --model moonshot/kimi-k3 -m "…" --jsondsh --profile headless "…"
Changement de modèleParamètre model.primary dans le fichier openclaw.json~/.dsh/settings.yaml
Benchmark en mode headless, 5 petites tâches309,9 s, ≈ 0,531 $ ; 5/5 réussies35,7 s, ≈ 0,011 $ ; 5/5 réussies (V4-Flash, deuxième passage en mode “warm-up”)
Génération d’un widget pixel-art, même consigne3 tentatives, dont deux ont abouti à un widget ; celui présenté ici a nécessité 7,4 minutes et ≈ 0,47 $2 tentatives ; la réussie a demandé 25 minutes et ≈ 49 cents
Version testéeOpenClaw 2026.9.2, plugin Moonshot 2026.9.20.1.1-rc.2 (version de prévisualisation pour développeurs)

Dans les comparaisons antérieures publiées sur ce site, il y avait une colonne consacrée à Reasonix. J’ai désactivé Reasonix sur ma machine le 9 septembre 2026 ; il ne figure donc pas ici. Son article de juillet reste en ligne en tant que document historique. J’ai également testé MiniMax M3 avec le même ensemble de tests ; MiniMax étant une société distincte de Moonshot, ce test fait l’objet d’un article séparé.

Le benchmark : les mêmes 5 tâches

Il s’agit des cinq mêmes tâches testées dans l’article sur dsh ; chaque tâche a été exécutée dans un dossier temporaire distinct, avec une nouvelle session pour chaque tâche sous Kimi. J’ai également relancé dsh sur V4-Flash le même jour, sur ces cinq tâches, en spécifiant deepseek-v4-flash dans un fichier de configuration temporaire. Le libellé des invites n’était pas identique. dsh s’exécute depuis le dossier où on le lance, donc ses invites mentionnaient « le répertoire courant » ; celles de Kimi indiquaient le chemin absolu de chaque dossier de tâche. De plus, l’invite de correction de bugs de Kimi ajoutait : « si pytest n’est pas disponible, installez-le d’abord avec ‘pip install --user pytest’ » (or pytest était déjà installé, et Kimi ne l’a jamais installé). Cette colonne représente la deuxième exécution : la première a duré 44,8 s et coûté 0,024 $, avec un cache froid ; c’est cette deuxième exécution que je compare dans tout cet article. Les colonnes V4-Pro et Gemma-4-26B proviennent de l’article sur dsh publié en août, et n’ont pas été re-testées. Le temps total indiqué inclut l’intégralité du processus. Les données sur les tokens et le coût pour Kimi proviennent de l’enveloppe JSON générée par OpenClaw ; celles de dsh proviennent de ses propres journaux de session.

TâcheKimi K3 (Chemin A)dsh V4-Flash (même jour)dsh V4-Pro (août, données historiques)Gemma-4-26B (août, données historiques)
Répondre « PONG » (démarrage + un appel)✅ 6,1 s · 0 outils✅ 1,7 s · 0 outils✅ 2,8 s✅ 13,2 s*
Écrire et exécuter FizzBuzz✅ 22,8 s · 2 outils (écriture, exécution)✅ 5,3 s · 3 outils✅ 8,4 s · 2 outils✅ 4,9 s · 2 outils
Corriger 2 bugs pour que les tests unitaires passent (tests inchangés)✅ 86,6 s · 6 outils (exécution, écriture, édition)✅ 11,3 s · 7 outils✅ 15,8 s · 7 outils✅ 10,4 s · 8 outils
Résumer un code source de 6 modules (moins de 150 mots)✅ 65,5 s · 10 outils (lecture, exécution, écriture)✅ 5,1 s · 7 outils✅ 10,9 s · 7 outils✅ 12,1 s · 7 outils
Renommer une fonction dans 3 fichiers + tests, puis vérifier que tout passe✅ 128,9 s · 9 outils (exécution, écriture ; un seul sed sur plusieurs fichiers)✅ 12,3 s · 11 outils✅ 18,2 s · 12 outils✅ 12,2 s · 11 outils
Temps total309,9 s35,7 s56,1 s52,8 s
Tokens : entrée non mise en cache / lecture depuis le cache / sortie (raisonnement)91 470 / 355 328 / 9 990 (4 053)6 141 / 147 328 / 4 697 (1 984)41,4 k / 107 k / 3,2 k40,5 k / 237 k / 5,6 k
Coût≈ 0,531 $ (3 $ / 15 $ / 0,30 $ par million de tokens)≈ 0,011 $ (0,44 $ / 1,32 $ / 0,014 $ par million de tokens)≈ 0,072 $0 $ (seulement coût électrique)

Le nombre d’outils correspond au nombre d’appels effectués. Pour Kimi, ces chiffres proviennent de toolSummary.calls dans l’enveloppe JSON d’OpenClaw, avec les types d’outils indiqués entre parenthèses ; pour dsh, ils viennent de ses propres journaux de session. *Premier appel après un chargement à froid du modèle sur la machine. Les tarifs appliqués pour Kimi sont ceux répertoriés dans ma fiche OpenClaw, utilisée par OpenClaw pour calculer le coût de chaque tâche ; consultez la page tarifaire de Moonshot pour les chiffres actuels. Le coût V4-Flash repose sur les mêmes tarifs de pointe que dans l’article dsh (tarifs DeepSeek) ; les lignes V4-Pro et Gemma reprennent les chiffres de cet article.

Ce que le tableau montre :

  • 5/5 dans chaque colonne. Aucune de ces tâches n’a posé problème à Kimi. La correction des bugs a laissé les tests intacts, et le renommage ne nécessitait qu’un seul sed sur quatre fichiers, suivi d’un test réussi ainsi que d’une recherche vide via grep du nom d’origine.
  • Kimi consacre plus de temps au raisonnement. K3 a utilisé 53, 241, 315, 1 586 et 1 858 tokens de raisonnement au total (4 053) pour les cinq tâches. dsh sur V4-Flash effectue également du raisonnement, mais en moindre quantité : 0, 52, 834, 5 et 1 093 tokens (1 984 au total). La majeure partie du temps supplémentaire de Kimi est consacrée au raisonnement et à des étapes supplémentaires.
  • Le cache fait grimper la facture. Sur les cinq tâches, Kimi a envoyé 91 470 tokens d’entrée non mis en cache et en a lu 355 328 depuis le cache ; ainsi, 80 % des tokens d’entrée provenaient du cache. Facturés comme tokens d’entrée non mis en cache, ces mêmes tokens auraient fait grimper le coût à environ 1,49 $ au lieu de 0,53 $.
  • Pour les petites tâches, V4-Flash est imbattable. Avec 35,7 s et un coût d’environ 0,011 $, il est près de 9 fois plus rapide et 48 fois moins cher que Kimi pour effectuer ces mêmes tâches, avec le même résultat. Le renommage seul a demandé à Kimi 128,9 s et 0,180 $ ; dsh n’a mis que 12,3 s et 0,0043 $.

Le test amusant : même cahier des charges, Kimi vs dsh

Dans l’article de dsh, le « test amusant » consistait à créer un widget en pixel-art représentant le logo de ce site, réalisé par dsh sur V4-Flash à partir d’un cahier des charges écrit. J’ai donné à Kimi le même cahier des charges, sans modification, et j’ai chronométré la tâche. Le cahier des charges :

Cahier des charges : widget interactif en pixel-art du logo LaserLloyd

Créez une version en pixel-art du logo LaserLloyd autonome et intégrable (voir reference-logo.png) : un anneau bleu épais, de couleur #1f3f8f sur fond blanc, contenant deux « L » majuscules italiques et inclinés — le pied du « L » en haut à gauche se trouve juste sous la tige du « L » en bas à droite, comme si les lettres étaient empilées en diagonale.

Résultats attendus (tous dans ce dossier)

  1. ll-pixel-logo.js — UN seul fichier JavaScript pur, sans dépendances, sans étape de compilation, sans requêtes réseau. Toute page peut l’intégrer via : <div class="ll-pixel-logo" data-size="320"></div> + <script src="ll-pixel-logo.js"></script>. Le script recherche chaque élément .ll-pixel-logo et y insère un <canvas>. Responsive : le canvas remplit la largeur du conteneur (format carré), avec une qualité optimale sur les écrans HiDPI (devicePixelRatio). Exposez window.LLPixelLogo.mount(el).
  2. index.html — page de démonstration montrant le widget à trois tailles, accompagnée d’une courte description des interactions.
  3. README.md — instructions d’intégration, descriptions des interactions et paramètres possibles (attributs data-).

L’art du pixel-art

  • Grille de pixels de 40×40 cellules. Ne dessinez pas manuellement le bitmap (pas de chaînes de caractères comme '#' ou '.' — c’est lent et source d’erreurs). En revanche, générez-le procéduralement à partir de la géométrie : une fonction isLit(col,row) qui renvoie true pour (a) les points appartenant à l’anneau : distance au centre comprise entre 0,82R et R ; (b) les deux « L » inclinés, chacun formé de deux parallélogrammes (une tige inclinée d’environ 20° et un pied). Le pied du « L » en haut à gauche se situe juste sous la tige du « L » en bas à droite, conformément au modèle de référence. Réglez les quelques constantes nécessaires pour que le résultat ressemble au logo de référence à 200px. Précalculez les cellules éclairées lors du montage du widget.
  • Palette : bleu du logo #1f3f8f ; bleu clair #2ea8ff ; ambre #ffb64a ; cyan #00e6cf ; fond transparent.

Interactions (l’essence de l’exercice — qu’elles soient agréables !)

  • Survol de la souris / mouvement tactile : les pixels proches du curseur réagissent physiquement — par exemple, ils sont repoussés comme dans un fluide ou sous l’effet d’une répulsion magnétique, puis reviennent en place avec amortissement ; pendant ce déplacement, ils brillent en bleu clair/cyan. L’animation doit être fluide à 60 fps grâce à requestAnimationFrame, sans à-coups.
  • Clic / toucher : un effet spectaculaire et satisfaisant. Choisissez UN seul effet majeur et réalisez-le correctement, par exemple le logo se fragmente en pixels qui s’éloignent sous l’effet de la gravité puis se reconstituent (en 1,5–2 secondes) ; ou un « laser » balaye le logo en le redessinant pixel par pixel avec des étincelles lumineuses. Les clics répétés doivent rester agréables (ne pas interrompre l’animation en cours).
  • État au repos : un léger mouvement ambiant (un scintillement lent ou des étincelles occasionnelles) pour éviter toute impression de statisme, sans distraire.
  • Respectez prefers-reduced-motion: reduce (affichez uniquement le logo statique, conservez seulement l’effet de lueur au survol).
  • Fonctionne avec la souris ET les écrans tactiles. Pas d’interruption du défilement.

Critères de qualité

  • Code propre, commenté ; pas de variables globales sauf LLPixelLogo. Tabulation sur 2 espaces. Moins de 400 lignes.
  • Fonctionne depuis file:// sans erreur dans la console. Testez-le vous-même : écrivez un petit script Node ou utilisez n’importe quel outil pour vérifier la syntaxe et tester le module (jsdom n’est PAS disponible — effectuez un node --check et un test unitaire sans DOM, par exemple comptez les cellules éclairées et vérifiez que l’anneau et les deux « L » sont bien présents dans les bons quadrants).
  • Terminez en affichant un bref rapport : ce que vous avez créé, comment l’intégrer, et ce que vous avez vérifié.

Comment Kimi s’en est sorti :

  • Première tentative (cahier des charges identique) : arrêtée après 8,8 minutes, aucun code de widget produit, coût d’environ $0,31. K3 a analysé le logo de référence, raisonné sur la géométrie et les outils à utiliser, mais n’a rien écrit du tout. La première tentative de dsh s’est également soldée par un échec similaire (boucle de 10 minutes pour imaginer un bitmap), bien que le cahier des charges autorisait alors le dessin manuel.
  • Deuxième tentative (même cahier des charges, nouvelle session) : widget complet, mais placé au mauvais endroit, coût d’environ $0,72. Après environ huit minutes, Kimi a généré un fichier ll-pixel-logo.js de 323 lignes, puis une page de démonstration, un README et deux fichiers de test ; il a exécuté ses tests et les a ajustés jusqu’à réussite, enfin produit un bref rapport. Tout cela s’est retrouvé dans l’espace de travail propre à l’agent, et non dans le dossier surveillé par mon script ; la session s’est terminée après 15 minutes sans que Kimi ne réponde. De mon point de vue, la deuxième tentative n’avait rien produit ; je n’ai pas attendu et j’ai lancé une troisième tentative sept minutes plus tard.
  • Troisième tentative (cahier des charges raccourci avec directive) : 7,4 minutes, les trois fichiers créés, coût d’environ $0,47. J’ai conservé les exigences sur les résultats, l’art et les interactions, ajouté en tête TARGETED — write the widget file in one tool call, no exploration, no planning, no verification loop., puis remplacé la section tests par cette phrase : Do NOT do a "node --check" or playwright test — just write the files and print a short report listing what you wrote. Le widget intègre la répulsion au survol avec retour en place, une fragmentation puis reconstitution au clic, un scintillement ambiant et un mode « mouvement réduit ». Mes vérifications figurent dans la section suivante.

Ainsi, les trois tentatives ont duré 8,8, 15 et 7,4 minutes, avec des coûts respectifs d’environ $0,31, $0,72 et $0,47 : soit environ $1,50 pour deux widgets. Le coût de la troisième tentative provient de son propre reçu JSON ; les tentatives 1 et 2 n’ayant pas généré de reçu, leurs montants correspondent aux frais OpenClaw par message pour chaque session, additionnés ; ce total correspond également au reçu de la troisième tentative.

Le widget de la deuxième tentative est réapparu environ une heure plus tard, lorsqu’une exécution MiniMax M3 sur le même worker a découvert les fichiers, exécuté leurs tests et les a présentés comme son propre travail. Ce récit figure dans l’article consacré à MiniMax M3 ; les deux widgets de Kimi côtoient désormais celui de dsh dans le comparatif des widgets en pixel-art.

Voici les premières ~30 lignes du ll-pixel-logo.js créé par Kimi :

/*!
 * ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
 *
 * Self-contained vanilla JS: no dependencies, no build step, no network.
 * Embed on any page with:
 *
 *   <div class="ll-pixel-logo" data-size="320"></div>
 *   <script src="ll-pixel-logo.js"></script>
 *
 * Every .ll-pixel-logo element gets a <canvas> mounted inside it at load.
 * Programmatic API: window.LLPixelLogo.mount(el) -> instance.
 *
 * Art: 40x40 pixel grid, rasterised procedurally from geometry (ring + two
 * interlocking italic Ls). Interactions: pointer repulsion with spring-back,
 * click/tap shatter-and-reassemble, idle shimmer/twinkle, reduced-motion
 * support. Mouse and touch. No scroll hijacking (all listeners passive).
 */
(function () {
  'use strict';

  // -- constants ------------------------------------------------------------
  var VERSION = '1.0.0';
  var GRID = 40;                                // logical grid: GRID x GRID cells
  var BLUE   = [31, 63, 143];                   // #1f3f8f logo blue
  var HILITE = [46, 168, 255];                  // #2ea8ff highlight blue
  var AMBER  = [255, 182, 74];                  // #ffb64a twinkle amber
  var CYAN   = [0, 230, 207];                   // #00e6cf max-displacement glow

  var CENTER = GRID / 2;                        // grid centre coordinate (20)
  var R_OUT = 19;                               // ring outer radius (cells)
  var R_IN = 0.82 * R_OUT;                      // ring inner radius
  var SLANT = Math.tan(20 * Math.PI / 180);     // ~20 deg italic shear

Et voici le résultat, la version produite par Kimi K3, telle quelle :

Placez le curseur dessus, puis cliquez. Les pixels sont repoussés du curseur et reviennent en place ; un clic fragmente le logo en pixels qui retrouvent leur place. Fonctionne aussi au toucher et respecte prefers-reduced-motion.

Kimi construit chaque « L » à partir de deux parallélogrammes (tige et pied inclinés) grâce à un petit utilitaire makeL, teste les points via une fonction inPara intégrée à isLit, et regroupe toutes les constantes de réglage (rayons de l’anneau, angle de 20° calculé via Math.tan, paramètres de ressort et d’amortissement) dans un bloc en tête du fichier.

Les fichiers créés par Kimi (le ll-pixel-logo.js de 397 lignes, le index.html de 40 lignes et le README.md de 79 lignes) sont disponibles à l’adresse /assets/uploads/2026/09/kimi-codex/, aux côtés du cahier des charges sous le nom BRIEF.md.

Pour comparaison, voici les premières ~30 lignes du widget de dsh, disponibles à /assets/uploads/2026/08/deepseek-harness/ll-pixel-logo.js :

/*!
 * ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
 * Vanilla JS, zero dependencies, no network requests, works from file://.
 *   <div class="ll-pixel-logo" data-size="320"></div>
 *   <script src="ll-pixel-logo.js"></script>
 * Auto-mounts on .ll-pixel-logo elements; window.LLPixelLogo.mount(el) too.
 * Knobs: data-size, data-speed, data-static.
 */
(function (global) {
  'use strict';
  // ---- 0. palette -----------------------------------------------------
  var BLUE = [31, 63, 143];      // #1f3f8f — logo blue
  var HI = [46, 168, 255];       // #2ea8ff — hover / repulsion glow
  var AMBER = [255, 182, 74];    // #ffb64a — twinkle spark
  var CYAN = [0, 230, 207];      // #00e6cf — deep glow
  // ---- 1. art: procedural 40x40 raster (no hand-drawn bitmap) ----------
  // A cell is lit when it belongs to the ring or to one of the two slanted
  // interlocking Ls. Each L is two parallelograms (stem + foot), described by
  // top-left (ax,ay), width w, height h, sheared by SLANT (bottom edge shifts
  // left): TL=(ax,ay) TR=(ax+w,ay) BL=(ax-SLANT*h,ay+h). The upper-left L's
  // foot runs right and tucks under the lower-right L's stem, like the ref.
  var GRID = 40;                 // cells per side
  var RING_R = 19.7;             // outer ring radius (cells)
  var RING_IN = 0.80 * RING_R;   // inner ring radius (reference ~0.808R)
  var SLANT = 0.453;             // shear of stems/feet (~24deg)
  var LETTERS = [
    { ax: 15.0, ay: 5.2, w: 4.2, h: 10.6 },   // upper-left L: stem
    { ax: 10.2, ay: 15.8, w: 15.0, h: 3.8 },  // upper-left L: foot
    { ax: 24.7, ay: 13.8, w: 4.2, h: 14.7 },  // lower-right L: stem
    { ax: 18.0, ay: 28.5, w: 15.0, h: 3.8 }   // lower-right L: foot
  ];

Les deux widgets sont conçus de la même manière : tous deux génèrent un anneau et deux « L » italiques entrelacés à partir de la géométrie, exposent window.LLPixelLogo.mount, et respectent prefers-reduced-motion. Les constantes diffèrent : dsh utilise un rayon extérieur de 19,7, un rayon intérieur à 0,80R et une inclinaison de 0,453 (environ 24°) ; Kimi opte pour 19, 0,82R et 20°. Les traits du logo sont également plus fins chez Kimi : ses tiges et pieds font 3 cellules d’épaisseur, contre 4,2 cellules de largeur et 3,8 cellules de hauteur chez dsh. D’où le fait que le logo de Kimi comporte 510 cellules éclairées contre 656 pour celui de dsh. Aucun des deux ne correspond exactement au modèle de référence, mais tous deux restent reconnaissables au premier coup d’œil. La deuxième tentative de dsh a également produit un test unitaire Node et, sans instruction particulière, un script Playwright ; la troisième tentative de Kimi, elle, s’est vue interdire les tests, ce qu’elle a respecté.

Commandes de vérification que j’ai exécutées sur le widget de Kimi

Je les ai relancées le 11/09/2026 sur la copie servie par cette page, depuis le répertoire /assets/uploads/2026/09/kimi-codex/ :

$ wc -l ll-pixel-logo.js
397 ll-pixel-logo.js
$ node --check ll-pixel-logo.js && echo "node --check passed"
node --check passed

Deux autres vérifications ont été effectuées de mon côté, à l’aide de deux petits scripts auxiliaires (de moins de 20 lignes chacun) que je n’ai pas publiés. Voici donc la méthode utilisée plutôt que des commandes que vous pourriez copier-coller :

  • Décompte des cellules allumées. J’ai chargé le fichier du widget dans Node en utilisant un DOM simulé (objets canvas, window et document sans effet réel). J’ai ensuite capturé la fonction isLit(col, row) définie dans le fichier, et l’ai appelée pour chaque cellule d’une grille 40×40, en comptant les cellules allumées par quadrant. Au total, 510 cellules se sont allumées : 124 en haut à gauche, 103 en haut à droite, 160 en bas à gauche et 123 en bas à droite.
  • Vérification du montage. Toujours avec ce même DOM simulé, j’ai confirmé que le fichier définit window.LLPixelLogo en tant qu’objet, et qu’en appelant mount() sur un élément fictif, on obtient un objet sans aucune erreur.

Rien que l’anneau (cellules dont le centre se situe entre 0,82R et R, avec R = 19) représente 352 des 510 cellules allumées ; il reste donc 158 cellules pour former les deux lettres « L ». Ces scripts auxiliaires sont de ma création, pas de Kimi, et ne servent qu’à un test sommaire, pas à une exécution dans un navigateur : la page que vous lisez actuellement est le résultat d’une telle exécution.

Pitfalls (ceux que j’ai réellement rencontrés)

  • « Compatible OpenAI » ne signifie pas « compatible avec le harnais Codex ». Le point de terminaison /v1/chat/completions de Moonshot fonctionne correctement en tant que fournisseur OpenClaw, mais le plugin Codex n’accepte que les routes dont l’identifiant du fournisseur est openai. Si vous avez absolument besoin de la reprise des threads Codex ainsi que du pont d’outils dynamique, la Voie B (le pont codex-router) est la seule option. Voir ci-dessus la comparaison entre la Voie A et la Voie B.
  • K3 effectue toujours un raisonnement, même pour des réponses triviales. Pour l’instruction « Répondez exactement : PONG. », 53 tokens de raisonnement ont été générés. C’est voulu et prévisible ; prévoyez-en le coût.
  • Un bloc compat remplace les paramètres existants, il ne les fusionne pas. Si vous ajoutez compat à l’entrée du modèle afin de refuser temperature, copiez également les champs reasoning-effort du plugin ; sinon, vous les perdrez sans le savoir.
  • Le contexte de 1 million de tokens est annoncé, mais ce n’est pas ce que vous obtenez avec mes limites. Le catalogue indique 1 048 576 tokens ; or mon paramètre contextTokens: 262144 signifie que les sessions sont limitées à 256 000 tokens. Il faut donc augmenter cette valeur exprès, et non par hasard.
  • La remise sur le cache existe bel et bien, mais les tarifs restent ceux des offres haut de gamme. Le prix de 0,30 $ par million de tokens lus depuis le cache équivaut à environ 21 fois le tarif de 0,014 $ appliqué par dsh V4-Flash. Néanmoins, l’utilisation du cache a permis de réduire le coût global d’environ un tiers par rapport à une exécution sans cache.
  • Des consignes créatives ouvrantes peuvent bloquer un modèle de raisonnement, et un délai d’expiration peut masquer un succès. La première tentative a réfléchi pendant 8,8 minutes sans produire le moindre code widget. La deuxième a généré un widget fonctionnel, mais a épuisé son temps imparti alors que les fichiers se trouvaient dans le mauvais dossier ; on aurait pu croire à un nouvel échec. Ce qui m’a finalement donné le widget escompté fut une consigne plus courte, formulée ainsi : TARGETED — write the widget file in one tool call, no exploration, no planning, no verification loop., avec indication explicite du dossier cible. Même avec cette formulation, K3 effectue toujours un raisonnement, mais ne planifie plus indéfiniment. Quel que soit le statut de sortie affiché, examinez donc ce que la session a réellement produit.
  • Un code d’erreur à la sortie ne signifie pas forcément un échec de la tâche. Vérifiez les fichiers. Le premier appel FizzBuzz a renvoyé le code 1, indiquant qu’aucun modèle adapté n’avait été trouvé, et s’est terminé par le message « ⚠️ API rate limit reached. Please try again later. ». Pourtant, le fichier fizz.py avait déjà été créé et fonctionnait correctement. Un nouveau lancement a renvoyé « Already created and ran. », et seul cet en-tête indiquait que l’opération était terminée. Mon script écrivait le JSON de chaque exécution dans le même fichier, donc celui de la tentative défaillante s’est retrouvé écrasé ; son code de sortie et son message final subsistent toutefois dans les logs de la session ayant effectué le benchmark. Le tableau présente ici les résultats d’une exécution ultérieure, dans une session propre.
  • Ne copiez pas un dossier de travail issu d’une exécution terminée avec un autre harnais. J’ai créé le dossier destiné à la correction des bugs de Kimi en copiant les fichiers du dossier terminé par dsh, alors que ce dernier les avait déjà corrigés. Ainsi, la première tentative de Kimi a constaté que les fichiers étaient déjà corrects et s’est contentée de les vérifier. J’ai ensuite réinitialisé le dossier et relancé l’opération dans une nouvelle session ; le tableau reprend les résultats de cette deuxième tentative. Par ailleurs, dsh travaille dans le répertoire depuis lequel on le lance : mon premier script dsh n’a pas exécuté cd vers le dossier de la tâche, ce qui a conduit à l’enregistrement des fichiers au mauvais endroit ; j’ai donc dû relancer les cinq tâches.
  • Aucun des deux widgets ne correspond exactement au logo de référence. La consigne demande d’ajuster les constantes afin que le rendu soit identique au logo à 200px. Je consacrerais dix minutes à régler les largeurs de traits et l’inclinaison avant de livrer quoi que ce soit.

Où cela me mène

Pour ces cinq tâches, Kimi K3 a donné les bonnes réponses, mais de manière lente et à un coût élevé. Pour des tâches mineures, dsh sur V4-Flash a effectué le même travail en environ un neuvième du temps et pour environ 1/48e du prix. Suite à ce test de performance, j’ai déplacé mon agent de traitement vers MiniMax-M3 ; Kimi K3 est quant à lui resté là où il était déjà : derrière mon agent de révision, car une réponse plus lente et plus soignée justifie ici le coût supplémentaire.

Le chemin B, soit le pont codex-router vers le serveur d’application Codex proprement dit, reste pour l’instant théorique tant que je ne serai pas certain de ce que homeScope: "user" permet de partager. En attendant, « Kimi en tant qu’agent de programmation » sur mon système signifie simplement que Kimi pilote la boucle native d’OpenClaw, exactement comme n’importe quel autre modèle natif d’OpenClaw.

Voir aussi : DeepSeek Harness (dsh) (l’outil de test comparatif, source du benchmark et des consignes), MiniMax M3 (le même outil utilisé avec le modèle exécuté par mon agent de traitement au 11/09/2026), Reasonix (modèle historique, retiré de mon système le 09/09/2026), ainsi que Quel est le coût réel de mes agents IA (comparaison tarifaire plus large).


← Plus de IA et LLM locaux