Give an LLM a body.

A Minecraft bot that is a real agent — it perceives, acts, remembers, survives, hires help, and answers you by chat, voice or phone.

git clone https://github.com/cagataycali/strands-minecraft
Read the README MIT · Node ≥ 22 · Strands + mineflayer
StrandsBot · live
First-person view from the bot: a sandy beach, two turtles at the waterline, a yellow sponge build on the right
Every frame on this page is the bot's own first-person view, recorded off its live dashboard — this one is 4 s of demo-creeper.gif, uncut.
60
tools
100%
of mineflayer covered
74
test files
18.6k
lines of TypeScript

Watch it think.

Two uncut captures from the bot's eyes. One instructed, one not.

Animation: the bot digs the blocks in front of it, then places them back
you> dig the blocks in front of you, then put them back
Animation: a creeper approaches on a beach and the bot backs away, uninstructed
creeper encounter, uninstructed

Try it. One line, end to end.

One real exchange from the README, in the grammar src/index.ts prints: prompt, tool call, reply, status block, journal.

  1. You say
    you> keep mining until you have 64 iron, I'll be around
  2. It calls a tool
    # → start_journey goal="mine until 64 iron_ingot in inventory"
  3. It answers in the game
    🤖 On it — journey jm3kq2 started. Ask me anything while I dig.
  4. Every step opens with the digest — formatDigest, ≤ 600 chars, zero tool calls
    Your status right now:
    HP 20/20 food 17/20 · (118, 42, -38) overworld, survival
    time: day
    threats: none in radar range
    bag: 4 meal(s), 12 torch(es), 41 building block(s) | tools: iron_pickaxe, stone_shovel | weapons: iron_sword
    journey: jm3kq2 "mine until 64 iron_ingot in inventory" step 1 — last: find_blocks iron_ore,deepslate_iron_ore exposed=false → 3 veins; tunnelling
  5. It works while you don't — each line ends in a measured [Δ …], not the model's account of itself
    🧭 [jm3kq2 #1] find_blocks iron_ore,deepslate_iron_ore exposed=false → 3 veins; tunnelling  [Δ +9 cobblestone]
    🧭 [jm3kq2 #2] dig_vein at (118, 42, -37) → 5 raw_iron  [Δ +5 raw_iron, moved 21m]

Same lines as the README's Ten minutes with it; the digest is the output of src/digest.ts for that step.

One session. Seven rails.

Game chat, the you> prompt, push-to-talk, a realtime call, the dashboard, a phone call, your tiny — all write into one shared history.

Seven input rails converge on one Session node that forks a turn per request and folds it back 💬 game chat ⌨️ you> CLI 🎤 push-to-talk 📞 realtime call 📱 web dashboard 🗣 phone call 🔥 tiny.technology Session fork ⑂ · fold · SESSION_WINDOW one history, concurrent turns
Send another request while one runs: the session forks the history, both turns think, the finished one folds back in completion order.

A nervous system, not a chat loop.

Most of what keeps the bot alive never touches the model.

  1. ⚡ Reflexes
    300 ms tick · zero tokens

    Lava → water bucket or flee. About to die → disengage. Creeper in blast radius → sprint. Stuck 20 s → shake loose. Idle: eat, wear better armor, grab drops.

  2. 👂 Sentinel
    event-driven · zero tokens

    Hears primed TNT and creepers, radar-tracks hostiles, names your attacker, notices dusk, chests opened behind your back — and tells the agent in one edge-triggered note.

  3. 📋 Digest
    per self-prompt · ≤ 600 chars

    Every thinker cycle and journey step opens with one status block — vitals, threats, bag, journey, workers — so the model reasons from state instead of spending a tool call asking.

  4. 🧭 Critic & ledgers
    per journey step

    Each step's journal line gets a measured [Δ +12 cobblestone, -2 hp, moved 34m] tail — narration can't hide a stall. Finished goals land in a completed ledger, failures in too_hard.

Say it once. Walk away.

Journeys iterate toward a goal for hours. The fleet hires worker bots — real second bodies — when a job splits.

strands-bot — tsx src/index.ts

60 tools. If mineflayer can do it, the agent can.

Every game mechanic has a tool or a written reason it doesn't — the audit.

Hover or tap a tool — the line is its real description: from the source, first sentence, nothing rewritten.

Your bot as a device.

Optional. Enroll it and your personal AI at tiny.technology sees through its eyes and sends it to work — from web, phone or watch.

enroll
npm run enroll -- --endpoint https://minecraft.yourdomain.com
# = npx tiny-tech enroll --body strands-the-miner · or set MINECRAFT_PUBLIC_URL
The endpoint the enrollment reads — one public route, six behind a bearer token, 5 req/s per token
routegate
GET /api/healthpublic
GET /api/telemetrytoken
GET /api/camera/snapshottoken
GET /api/stream.mjpegtoken
GET /api/eventstoken
POST /api/chattoken
POST /api/stoptoken

Run it.

The whole rig — Minecraft server, bot, dashboard — in one command. Or bare metal, if you want the microphone.

Docker
git clone https://github.com/cagataycali/strands-minecraft && cd strands-minecraft
cp .env.example .env        # AWS_* for Bedrock by default
docker compose up -d        # server + bot · dashboard on :3008
Bare metal · Node ≥ 22
npm install
cp .env.example .env        # credentials + MC_HOST/MC_PORT
npm start                   # bot joins, you> prompt opens

Bedrock by default; OpenAI or Anthropic with one env var (STRANDS_MODEL_PROVIDER) and their SDK package. Give the Docker VM at least 6 GB (8 GB with fleet workers) — the bot checks its headroom at boot and says so in one line.

How it compares.

Voyager and Mindcraft are about learning to play. This is about a body. Every claim below is quoted from each project's own README.

criterionstrands-minecraftMindcraftVoyagermineflayer alone
the model drives60 typed tools = 100% of mineflayerchat actions; optionally "write/execute code on your computer" (off by default)"an ever-growing skill library of executable code"your JavaScript/Python
modelsBedrock default; OpenAI, Anthropic via one env var18 APIs incl. openai · google · anthropic · ollama (local)"OpenAI's GPT-4"none
when the model is asleep300 ms reflexes + sentinel, zero tokens——everything is your code
more than one bodymanage_bots hires workers; independent compose projects--profiles andy.json jill.jsona single agentas many as you write
how you reach itgame chat · CLI · push-to-talk · realtime call · dashboard · phone · tinygame chat · web UI (:8080) · TTS narration (speak_model)Python API (voyager.learn())your code
runs onNode ≥ 22, Docker compose with the serverNode 18/20, Minecraft ≤ 1.21.11Python ≥ 3.9 + Node ≥ 16, Fabric 1.19 modsNode, Minecraft 1.8 → 26.1

Same rows as the README's How it compares.

Read deeper.

The audits and the incident write-ups that shaped the code. Each hook is the file's own first sentence; reading time is counted, not guessed.