Two LLM agents play Keep Talking and Nobody Explodes against each other: a defuser who can see a simulated bomb but not the manual, and an expert who has the manual but can't see the bomb. They talk to each other in plain text — no shared state, no hidden channel — exactly like the real game.
This is a deliberately naive baseline, built as a teaching/starting point rather than a polished product:
- The expert's entire system prompt is the whole manual pasted in, verbatim.
- Currently using
gemini-3.6-flashwhich is probably much more powerful than we need. - Both agents keep full, unsummarized conversation history in an in-memory session.
- There's no RAG, no context management, no caching, no structured message protocol.
The idea is to give students/experimenters a working end-to-end system they can then improve on (retrieval over the manual, context compression, better protocols, cost/latency optimization, etc.) and measure against.
- A
Bomb(src/main/kotlin/ktane/engine) is procedurally generated with a random serial number and a set of modules, and implements the actual manual logic for each module type — the same rules a human would follow with the real manual. - The defuser agent (
ktane.agents.Agents) only has tools:get_bomb_state,inspect_module(returns a rendered photo of a module), and one action tool per module type (cut_wire,press_keypad_button, etc. — seeDefuserTools.kt). It has no manual. - The expert agent has the full manual text in its system prompt and a reference sheet of keypad symbols, but no tools — it can only talk.
GameOrchestratorrelays messages back and forth (expert → defuser → expert → ...) via the Google ADK Kotlin runner, driving each turn until the bomb is defused, explodes, or a max exchange count is hit.- A Swing window (
BombWindow) shows a live, human-readable view of the bomb as the agents play, for spectating.
Wires, Keypad, Who's on First, Memory, Password — implemented per the manual in
src/main/resources/manual/manual.md. Battery/port/indicator-dependent rules from the real
game are intentionally out of scope.
- JDK 17+
- A Gemini API key (for the LLM-driven modes)
export GOOGLE_API_KEY=your-key-here # https://aistudio.google.com/apikeyAlternatively, configure Vertex AI instead of an API key:
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=your-project
export GOOGLE_CLOUD_LOCATION=your-locationPlay a full game with the two LLM agents and a live bomb window:
./gradlew runWatch a scripted perfect solver play instead (no LLMs, no API key needed — good for checking the engine/UI):
./gradlew run -Pargs="--auto"Bomb customization:
--modules LIST Comma-separated module list (repeats allowed) from:
wires, keypad, whosonfirst (wof), memory, password
(default: one of each of the five)
--time N Countdown seconds (default 600)
--strikes N Strikes that detonate the bomb (default 3)
--serial STR Fixed serial number (default: random, e.g. TR2XL7)
--batteries N Batteries on the casing, cosmetic (default 2)
--seed N Random seed for reproducible bombs
--no-speedup Timer does not speed up after strikes
Run modes:
--auto No LLMs: a scripted solver plays (engine/UI demo)
--model NAME Gemini model for both agents (default gemini-3.6-flash)
--defuser-model N Override model for the defuser only
--expert-model N Override model for the expert only
--max-exchanges N Stop after N defuser<->expert exchanges (default 200)
--no-ui Headless: no live bomb window
--help This text
Example: a harder, reproducible bomb with two Wires modules and no UI:
./gradlew run -Pargs="--modules wires,wires,memory --seed 42 --time 300 --no-ui"-
RenderTest— renders one image of every module type (plus the expert's keypad reference sheet) torenders/, so you can see exactly what the defuser's photos look like without running any agents:./gradlew run -PmainClass=ktane.RenderTestKt
-
StressTest— runs the scripted solver over 300 seeded bombs and checks that all of them are defused with zero strikes, as a regression check on the module rule logic:./gradlew run -PmainClass=ktane.StressTestKt
src/main/kotlin/ktane/
Main.kt CLI entry point
RenderTest.kt module image dump
StressTest.kt rule-correctness regression check
agents/ LLM agents, tools, and the orchestrator
engine/ bomb/module simulation and rules
render/ Swing UI and module image rendering
src/main/resources/
manual/manual.md the defusal manual given to the expert
symbols/ keypad symbol images