Architecture

Architecture

πŸ—οΈ Moincraft Architecture#

System Map#

Hermes/Hermit operator ──REST/ops──▢ Relay :55667
       β”‚                              β–²
       └─ persona + memory + skills   β”‚ optional DASHBOARD_API_TOKEN

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      PM2 / launch_all.sh                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  mc-server   β”‚  dashboard   β”‚mindcraft-   β”‚ prismarine- β”‚
β”‚Paper 1.21.11 β”‚Svelte :55666 β”‚bots :55668  β”‚viewer :55669β”‚
β”‚   G1GC JVM   β”‚relay  :55667 β”‚main.js      β”‚viewer.js    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚              β”‚              β”‚             β”‚
    :25565         socket.io      MindServer    Three.js
    TCP/UDP        events         hub + WS      WebGL
       β”‚              β”‚              β”‚             β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    Mineflayer Bots (per agent)

Port Map#

Port Service Notes
25565 Paper MC Server MOINCRAFT_SPIGOT_PORT
55666 Svelte Dashboard UI MOINCRAFT_NEW_DASHBOARD_PORT
55667 Dashboard relay backend DASHBOARD_PORT, Socket.IO
55668 MindServer MINDSERVER_PORT, agent hub
55669 Prismarine Viewer MOINCRAFT_VIEWER_PORT, WebGL
55661+ Per-agent viewer ports base + offset

AIRI-Inspired Layer Split#

  • Soul/Operator: Hermes owns durable persona, memory, skills, and remote messaging
  • Runtime Bridge: Relay :55667 is the stable API boundary β€” prefer extending relay contracts over calling MindServer internals
  • Embodied Agents: Mindcraft/Mineflayer owns Minecraft state, pathfinding, action execution, in-world coordination

Agent Lifecycle#

bootstrap() β†’ Mindcraft.init() β†’ createAgent(settings)
  β””β†’ Agent.start()
       β”œβ”€ ActionManager      β€” action queue + interrupts
       β”œβ”€ Prompter           β€” LLM abstraction (chat/code/vision/embed)
       β”œβ”€ History            β€” sliding window + LLM summarization
       β”œβ”€ Coder              β€” code gen + ESLint lint + SES sandbox exec
       β”œβ”€ NPCController      β€” item/build goals + constructions
       β”œβ”€ MemoryBank         β€” (stub, extend for vector DB)
       β”œβ”€ SelfPrompter       β€” autonomous goal loop (STOPPED/ACTIVE/PAUSED)
       β”œβ”€ VisionInterpreter  β€” screenshot β†’ vision model
       β”œβ”€ CooperationFramework β€” multi-agent levels 1–5
       └─ initModes()        β€” tick-based reactive behaviors

Startup Order (Critical)#

1. Paper MC server          (wait :25565 TCP)
2. mindcraft-bots           (AGENT_STARTUP_DELAY_MS=1500 between agents)
3. prismarine-viewer        (after server ready)
4. dashboard

⚠️ Only ONE orchestrator at a time β€” either moincraft.service (systemd) OR user-level moincraft-*.service β€” NEVER both (causes EADDRINUSE + session.lock conflicts).

Prompter β€” 4 Model Slots#

{
  "model":        "chat model (default fallback for all)",
  "code_model":   "specialized for !newAction codegen",
  "vision_model": "multimodal for !lookAtPlayer etc",
  "embedding":    "semantic search for examples + skill docs"
}

Prompt templates use $VAR placeholders: $NAME $STATS $INVENTORY $MEMORY $COMMAND_DOCS $CODE_DOCS $EXAMPLES $SELF_PROMPT $LAST_GOALS $BLUEPRINTS $CONVO $ACTION $TO_SUMMARIZE

History β€” Memory System#

  • Sliding window: keeps last max_messages (default 15) turns
  • Summarization: when full β†’ LLM compresses oldest 5 turns into memory (≀500 chars)
  • Persistence: bots/{name}/memory.json β€” survives restarts if load_memory: true
  • Full history: appended to bots/{name}/histories/{timestamp}.json
  • Prompt injection: $MEMORY injects summary; recent turns provide context

SelfPrompter β€” Autonomous Loop#

start(goal) β†’ loop {
  send "You are self-prompting with goal: '{goal}'. Use a !command."
  if no command used 3Γ— in a row β†’ stop
  await 2s cooldown
}

States: STOPPED(0) ACTIVE(1) PAUSED(2). Auto-restarts if idle β‰₯ cooldown and state is ACTIVE.

Coder β€” Safe Code Execution#

  • Generates JS code blocks via promptCoding()
  • ESLint lints before execution (catches hallucinations)
  • lockdown() + makeCompartment() via SES for sandboxing
  • Max 5 attempts, max 3 no-code failures before abort
  • Code has access to: bot, skills, world, Vec3 (no require/import)

RAG β€” Examples & Skill Library#

  • Embeds all conversation + coding examples via embedding_model
  • At prompt time: cosine similarity β†’ top-N most relevant injected as $EXAMPLES
  • Skill docs for !newAction: embed task β†’ cosine sim β†’ top-N docs as $CODE_DOCS
  • Always includes: placeBlock, wait, breakBlockAt
  • relevant_docs_count: 5, EXAMPLES_INIT_TIMEOUT_MS=20000
  • Fallback without embedding model: word overlap scoring