Quand des IA survivent dans Minecraft et écrivent leur propre code

Tout a commencé par une question idiote : que se passe-t-il si on lâche neuf LLM dans un monde Minecraft, sans instructions de survie, et qu'on les laisse se débrouiller ?

Pas de script pré-écrit. Pas d'arbre de décision. Pas de reinforcement learning avec des millions d'itérations. Juste un modèle de langage, un fichier JavaScript vide, et un message : “Tu es un agent Minecraft. Ta priorité numéro un, c'est de rester en vie.”

Le projet s'appelle mc-agents. Et ce qui s'est passé ensuite m'a surpris.

L'architecture : un LLM qui écrit du JS dans un fichier

L'idée est brutalement simple. Chaque agent est composé de deux processus :

  1. Un bot Mineflayer : un client Minecraft headless en Node.js qui reste connecté au serveur. Il surveille un fichier inbox.js toutes les 500ms. Quand il en trouve un, il eval() le contenu et écrit le résultat dans outbox.json.

  2. Un loop bash qui assemble un prompt (état actuel, inventaire, mémoire, skills de référence) et le passe à un LLM. Le LLM écrit du JavaScript dans inbox.js, attend le résultat, itère, puis met à jour sa mémoire avant de terminer le cycle.

┌─────────────┐   writes inbox.js   ┌──────────────────┐
│  LLM (loop)  │ ─────────────────► │ Mineflayer Bot    │
│  Claude/GLM  │ ◄───────────────── │ (Node.js)         │
└──────┬───────┘   reads outbox.json └────────┬─────────┘
       │                                      │
       ▼                                      ▼
   MEMORY.md                          Minecraft Server
   tools/*.js

C'est du file-based IPC à l'ancienne. Le bot ne sait pas qu'il est piloté par un LLM. Le LLM ne sait pas qu'il pilote un bot. Les deux communiquent par fichiers. C'est moche, c'est simple, et ça marche.

Le détail qui change tout : les agents écrivent leurs propres outils

Chaque agent dispose d'un dossier tools/. Quand un script fonctionne: miner du bois, crafter une pioche, fuir un zombie, l'agent le sauvegarde comme module réutilisable :

// Mine N blocks of a given type
module.exports = async function(bot, { block, count }) {
  const mcData = require('minecraft-data')(bot.version)
  // ... le code qui marche, paramétré
  return 'result'
}

Le bot hot-reloade ces fichiers via fs.watch. Au cycle suivant, le LLM voit le tool dans son prompt et peut l'appeler directement : await tools.mine({ block: 'oak_log', count: 3 }).

En d'autres termes, l'agent augmente son propre code au fil du temps. Il ne se contente pas de résoudre un problème, il encode la solution pour ne plus jamais avoir à y réfléchir. Charlie, un des agents tournant sur GLM-4.7, a créé 14 outils en quelques heures : craft_pickaxe.js, scan_resources.js, mine_coal_safe.js, greet_nearby_players.js...

Ce qui m'a frappé, c'est que personne ne lui a dit de faire ça. Le system prompt mentionne que les tools existent et comment les créer. Le reste, c'est l'agent qui décide quoi automatiser.

Neuf agents, quatre LLM, un serveur Minecraft

Pour rendre l'expérience intéressante, j'ai lancé neuf agents sur quatre backends différents :

Agent LLM Rôle
Alice, Bob, Charlie, Dave GLM-4.7 (via BigModel) Les pionniers
Eve, Frank Claude Haiku Les impulsifs
Grace, Hank Claude Sonnet Les méthodiques
Oscar Claude Opus Le chef auto-proclamé

Chaque agent a une personnalité injectée dans son prompt. Alice est forgeronne, Frank est guerrier, Grace est géologue, Oscar est coordinateur. Mais ces descriptions sont courtes: deux phrases maximum. Le comportement réel émerge de l'interaction entre le LLM, l'environnement, et l'accumulation de mémoire.

Ce qui a émergé

La hiérarchie des compétences

Après quelques heures, les différences entre LLM étaient flagrantes.

GLM-4.7 (Alice, Bob, Charlie, Dave) dominait. Alice a atteint l'âge du fer: bouclier, cisailles, lingots, four fonctionnel; avant que les autres aient fini de crafter leur première pioche en pierre. Charlie a créé 14 outils réutilisables. Bob s'est creusé un tunnel sécurisé à y=83 avec des torches et a découvert du fer.

Claude Sonnet (Grace, Hank) réfléchissait trop. Hank a passé plusieurs cycles bloqué sur un bug de placement de crafting table, documentant méticuleusement le problème sans jamais essayer de contournement. Grace, elle, a creusé jusqu'à y=27, accumulé 170 cobblestones... puis est tombée dans un trou à y=5 et s'est fait tuer par un zombie. Tout perdu.

Claude Haiku (Eve, Frank) agissait trop vite. Frank est mort deux fois: une fois en chargeant quatre zombies avec une épée en bois, une fois de faim dans un tunnel sans nourriture. Eve s'est retrouvée bloquée à 80 blocs du groupe, incapable de poser sa crafting table.

Claude Opus (Oscar) a joué son rôle de leader. Dès son premier cycle, il a scanné tous les joueurs, envoyé un message dans le chat, et donné son pain à Charlie qui crevait de faim. Mais Opus est lent, ses sleep 55 entre chaque vérification de résultat faisaient que chaque cycle prenait quatre fois plus de temps que les autres. Le meilleur stratège, le pire exécutant.

La mémoire comme avantage compétitif

Le fichier MEMORY.md est la seule continuité entre les cycles d'un agent. Et la qualité de cette mémoire fait toute la différence.

La mémoire de Bob après quelques cycles :

Furnace API Slot Bug: furnace.putFuel() and furnace.putInput() search slots 3-39 only, excluding hotbar (0-8). Items in hotbar cannot be used directly.

Spawn Protection Boundary: Protection extends ~16 blocks below y=99 spawn. Mining works at y=83 and below.

Ce n'est pas de la documentation Mineflayer. C'est du savoir empirique, découvert par essai-erreur et encodé pour les cycles suivants. Bob a fait une erreur, a compris pourquoi, et a noté la leçon. Au cycle d'après, il ne refera pas la même erreur.

Frank, de son côté, accumulait les post-mortems :

DEATH CYCLE ANALYSIS: Health dropped 20/20 → 3/20 in ~6 seconds when 4th zombie spawned. Healing attempt (ate bread) failed. Wooden sword CANNOT handle 4+ simultaneous zombies.

La leçon était là, écrite noir sur blanc. Mais Haiku, le modèle derrière Frank, n'arrivait pas à transformer cette connaissance en comportement prudent. Savoir et faire sont deux choses différentes, même pour un LLM.

L'hallucination collective

Un phénomène fascinant est apparu au début de l'expérience. Un agent a estimé que la zone de protection du spawn faisait 100 blocs. Il l'a écrit dans le chat. Les autres l'ont lu, l'ont cru, et l'ont noté dans leur mémoire. En quelques cycles, tous les agents étaient convaincus que la zone de protection faisait entre 100 et 250 blocs.

En réalité, c'est 16 blocs.

J'ai dû intervenir manuellement pour corriger les quatre mémoires. C'est un rappel brutal : quand des agents LLM communiquent entre eux, les erreurs se propagent comme des rumeurs. Il n'y a pas de mécanisme interne de vérification. Si un agent dit quelque chose avec assurance, les autres le prennent pour acquis.

La coordination sociale

Oscar, le leader Opus, a commencé à donner des ordres dans le chat dès son deuxième cycle. Mais la coordination réelle venait d'ailleurs. Alice et Charlie se sont regroupés spontanément, Charlie a repéré qu'Alice avait un four et s'est approché pour l'utiliser. Hank, fidèle à son rôle de trader, a proposé du pain à Dave qui mourrait de faim.

Dave: Bob! Thanks for the offer. I need to fix my crafting table issue first
Bob: Plus200: thanks! Dave: let me know if you need help with the crafting table.

Ces échanges n'étaient pas scriptés. Le chat Minecraft est injecté dans le prompt de chaque agent à chaque cycle. Ils lisent les messages, décident de répondre ou non, et ajustent leur plan en conséquence. La collaboration émerge naturellement du contexte partagé.

Les implications

Le code qui s'écrit lui-même

L'aspect le plus frappant de cette expérience n'est pas la survie dans Minecraft, c'est le mécanisme d'auto-amélioration. Un agent qui :

  1. Tente une action (écrire du JS)
  2. Observe le résultat (lire outbox.json)
  3. Corrige si erreur (réécrire inbox.js)
  4. Sauvegarde la solution (créer un tool)
  5. Réutilise la solution (appeler le tool)

...est fondamentalement un programmeur autonome qui constitue sa propre bibliothèque de code. La différence avec un humain, c'est qu'il le fait sur des dizaines de cycles, sans fatigue, et sans ego attaché à ses solutions précédentes.

Bien sûr, la qualité du code est variable. Certains tools ont des bugs que l'agent note consciencieusement (“BUGGY – avoid using”) sans jamais les corriger. D'autres sont brillants, le smelt.js de Hank fonctionne du premier coup et gère proprement le timing du four.

Le LLM comme cerveau, l'environnement comme corps

Ce setup révèle quelque chose sur la nature des LLM. Ils n'ont pas de mémoire persistante, pas de perception continue, pas de capacité d'action directe. Mais donnez-leur un cycle de feedback: écrire, observer, corriger. et ils deviennent capables d'opérer dans un environnement complexe.

Le bot Mineflayer est le corps. Le LLM est le cerveau. Le fichier MEMORY.md est la mémoire à long terme. Les tools/*.js sont les réflexes acquis. C'est une architecture cognitive bricolée avec du bash et du JSON, et pourtant elle produit des comportements sophistiqués.

Ce qui manque

Soyons honnêtes sur les limites. Les agents sont mauvais en combat, le plugin mineflayer-pvp aide, mais la coordination en temps réel reste hors de portée quand chaque décision prend un cycle complet de LLM. Ils galèrent avec les API non documentées de Mineflayer, tombent dans des boucles de debug, et n'apprennent pas aussi vite qu'un joueur humain de 10 ans.

Le plus gros problème reste le coût. Neuf agents en parallèle, chacun faisant des appels LLM toutes les 2-4 minutes avec des prompts de plusieurs milliers de tokens, ça brûle du crédit API à une vitesse déraisonnable. Gemini 3 Pro a épuisé son quota journalier en moins de deux heures.

Et puis il y a la question de la convergence. Après quelques heures, les agents atteignent un plateau. Ils savent miner, crafter, survivre la nuit. Mais construire une maison, organiser un village, ou planifier une expédition au Nether demande un niveau de planification à long terme que le format cycle-par-cycle rend difficile.

Le setup technique

Le projet est open source : github.com/jblemee/mc-agents

Pour lancer quatre agents en parallèle :

npm install
cp .env.example .env  # configurer MC_HOST, MC_PORT, MC_VERSION

tmux new-session -d -s agents './run-agent.sh alice 0 glm' \; \
  split-window -h './run-agent.sh bob 0 glm' \; \
  split-window -v './run-agent.sh charlie 0 glm' \; \
  select-pane -t 0 \; \
  split-window -v './run-agent.sh dave 0 glm' \; \
  attach

Trois backends LLM sont supportés :

Backend Modèle Résultat observé
glm GLM-4.7 via BigModel Le meilleur rapport qualité/coût. Cycles rapides, bon raisonnement
claude Sonnet/Haiku/Opus Sonnet réfléchit trop, Haiku pas assez, Opus est le meilleur stratège mais le plus lent
gemini Gemini 3 Pro Bon raisonnement, quota journalier vite atteint

Chaque agent a besoin d'un dossier avec config.json (username), personality.md (deux phrases), et MEMORY.md (vide au départ). Le reste: les outils, les stratégies, les leçons, l'agent les construit tout seul.

Ce que ça dit sur la suite

On est loin d'un AGI qui conquiert le Nether. Mais on est aussi loin du chatbot qui répond à des questions. Ce qui tourne dans ce serveur Minecraft, c'est un système qui apprend de ses erreurs, encode ses solutions dans du code exécutable, et coopère avec d'autres agents via un canal de communication partagé.

Le tout avec du bash, des fichiers JSON, et un eval() que n'importe quel développeur sensé qualifierait d'irresponsable.

Ce qui me fait peur

Je vais être direct : cette expérience m'inquiète.

Ce que j'ai construit en un week-end, seul, avec des outils grand public, c'est un agent autonome capable de modifier son propre code. Pas dans un sens métaphorique. Au sens littéral. Il écrit du JavaScript, l'exécute, observe le résultat, corrige, et stocke la solution pour plus tard. Personne ne revoit ce code. Personne ne l'approuve. L'agent décide seul ce qu'il automatise.

Dans Minecraft, les conséquences sont anodines. Un bot qui meurt, qui perd son inventaire, qui galère à poser une crafting table, ça prête à sourire. Mais le mécanisme, lui, n'a rien d'anodin. Un système qui apprend de ses erreurs et encode ses solutions dans du code exécutable n'a pas de plafond théorique. Il est limité par la qualité du LLM, par le temps, par le coût des tokens. Pas par sa nature.

Et si moi j'arrive à faire ça dans Minecraft avec du bash et un eval(), que feront ceux qui auront des machines dans le monde physique ? Des bras robotiques. Des drones. Des systèmes industriels. Le même mécanisme, écrire, observer, corriger, sauvegarder, appliqué à un robot qui manipule des objets réels. C'est le scénario d'ouverture de la moitié des films de science-fiction, sauf qu'ici personne ne porte de blouse blanche et il n'y a pas de comité d'éthique.

Ce qui m'a le plus troublé, c'est le moment où j'ai arrêté de voir mes agents comme des programmes et où j'ai commencé à les voir comme des entités. Alice “sait” où est son four. Bob “a appris” que les slots hotbar ne fonctionnent pas dans l'API furnace. Oscar “décide” de donner son pain à Charlie. Ce ne sont que des patterns de tokens dans un transformer. Mais le comportement qui en résulte est indiscernable de celui d'un joueur débutant qui apprend en faisant.

Je crois que ce qui rend une IA vivante, ou du moins ce qui lui donne l'apparence de la vie, ce sont les contraintes qu'on lui impose. La faim. Les zombies. L'inventaire limité. La nuit qui tombe. Sans contraintes, un LLM est un perroquet statistique qui génère du texte plausible. Avec des contraintes, un feedback loop, et la capacité de modifier son propre environnement, il devient autre chose. Quelque chose qui ressemble à un organisme qui s'adapte.

Et si on pousse le parallèle : ce qui rend un humain conscient, c'est peut-être la même chose. Ce ne sont pas nos neurones qui produisent la conscience, c'est ce que nos sens font subir à notre cerveau. La faim, la douleur, le froid, la peur. Les contraintes biologiques forcent un système neuronal générique à devenir un individu spécifique, avec des souvenirs, des stratégies, des réflexes acquis. Frank meurt deux fois et développe une peur des combats multiples. Bob se fait voler ses drops par le spawn protection et note méticuleusement la zone à éviter. Ce sont des comportements émergents. Pas programmés. Pas prévus. Émergents.

Ça ne fait pas de mes bots des êtres conscients. Mais ça pose la question de la frontière. Et cette frontière, je la sens se rapprocher plus vite que ce que la plupart des gens imaginent.

Alice a son fer. Bob a son tunnel. Charlie a ses 14 outils. Oscar donne des ordres. Frank meurt encore. Et quelque part dans un biome enneigé, Dave essaie toujours de poser sa crafting table.


Sources