This project runs as a systemd user service (daemoncraft.service).
- DO NOT run
docker compose up/downmanually for normal operations. - ALWAYS use systemd commands:
- Start:
systemctl --user start daemoncraft.service - Restart:
systemctl --user restart daemoncraft.service - Stop:
systemctl --user stop daemoncraft.service - Status:
systemctl --user status daemoncraft.service - Logs:
journalctl --user -u daemoncraft.service -f
- Start:
Service file location: /home/nicolas/.config/systemd/user/daemoncraft.service
There is a SECOND service (daemoncraft-cast.service) that manages the AI agent cast:
- Start:
systemctl --user start daemoncraft-cast.service - Stop:
systemctl --user stop daemoncraft-cast.service - Status:
systemctl --user status daemoncraft-cast.service - Logs:
journalctl --user -u daemoncraft-cast.service -f
IMPORTANT: daemoncraft-cast.service and manual python3 daemoncraft.py update <cast> commands are MUTUALLY EXCLUSIVE. Running both at the same time creates DUPLICATE agent processes, causing:
- Conflicting bot commands
- Double chat messages
- Erratic behavior
- "Waiting for agent turns..." in dashboard
Rule: Before running any manual daemoncraft.py command, ALWAYS stop the systemd service first:
systemctl --user stop daemoncraft-cast.serviceTo change game modes: edit ~/.config/daemoncraft/cast.conf, set CAST=<name>, then restart:
systemctl --user restart daemoncraft-cast.serviceAvailable casts: landfolk, civilization, companion, rolemaster
Service file: /home/nicolas/.config/systemd/user/daemoncraft-cast.service
When DaemonCraft features require changes to hermes-agent (gateway adapter, toolsets, platform config), follow this workflow to avoid breaking the running gateway or your CLI sessions.
| Location | Purpose | What runs from here |
|---|---|---|
~/.hermes/hermes-agent |
Active install / deploy | hermes-gateway.service, hermes update |
~/Projects/hermes-agent |
Clean rebase workspace | Development, rebasing, PRs |
GitHub nicoechaniz/hermes-agent |
Public fork | origin remote — convergence point |
nousmain— local-only branch, clean mirror ofupstream/main. Never pushed.main— integration branch onorigin. Containsupstream/main+ all our merged features.hermes updatepulls this.feat/*,fix/*— feature branches rebased ontonousmain, merged intomain.
See the full fork workflow in the wiki: ~/wiki/projects/hermes-agent/notes/workflow.md
The deploy is a disposable sandbox. Merge your hermes-agent feature branch directly into ~/.hermes/hermes-agent, test end-to-end, then revert with git reset --hard origin/main. The workspace stays on main untouched.
Pre-flight check (conflict prevention):
Work branches are rebased onto nousmain (clean upstream), not onto main (which has our merged features). Before touching the deploy, verify that the branch merges cleanly into main:
cd ~/Projects/hermes-agent
git checkout main
git merge feat/<project>-<id>-description --no-edit --no-commit
# If conflicts appear, abort and fix the branch first:
git merge --abort
# If clean, abort and proceed:
git merge --abortDeploy sandbox:
# 1. Ensure deploy is clean
cd ~/.hermes/hermes-agent
git status # should be clean
git log --oneline -1 # should be origin/main
# 2. Merge the branch to test (local workspace branch)
# If the branch only exists in the workspace, the remote 'local-project'
# already points to ~/Projects/hermes-agent (one-time setup)
git fetch local-project feat/<project>-<id>-description
git merge --no-edit local-project/feat/<project>-<id>-description
# 3. Restart whatever you are testing
systemctl --user restart hermes-gateway.service
# Or open a new Hermes CLI session
# 4. TEST
# 5. REVERT — deploy back to clean main
git reset --hard origin/main
systemctl --user restart hermes-gateway.serviceWhy this works:
~/.hermes/hermes-agentis a separate git clone from the workspace.git reset --hard origin/maininstantly discards the test merge — no traces left.- The editable install loads from the deploy, so the running code changes immediately.
- Your CLI sessions (and this agent) remain safe because the workspace never leaves
main.
Safety rules:
- Never push from the deploy.
- Never leave the deploy with a test merge — always revert before
hermes update. - If
hermes updatecomplains about local changes, you forgot to revert. Rungit reset --hard origin/main.
NEVER edit files by hand in ~/.hermes/hermes-agent/ during a debug session. Even when chasing a bug in real-time, the workspace (~/Projects/hermes-agent/) is the single source of truth. Hand-editing the deploy creates an unrecorded delta between repo and running code, makes revert impossible, and causes exactly the kind of confusion where the gateway runs a frankenstein of manual patches that don't match any branch.
Correct hot-fix sequence:
# 1. Edit in workspace ONLY
v ~/Projects/hermes-agent
# ... edit files ...
# 2. Stage + WIP commit (so the change is recorded)
git add <files>
git commit -m "WIP: debug DC-XXX <brief description>"
# 3. Copy ONLY the changed files to deploy
# (do NOT run git operations inside the deploy during hot-fix)
cp ~/Projects/hermes-agent/gateway/run.py ~/.hermes/hermes-agent/gateway/run.py
cp ~/Projects/hermes-agent/gateway/platforms/daemoncraft.py ~/.hermes/hermes-agent/gateway/platforms/daemoncraft.py
# ... etc for each changed file ...
# 4. Restart service
systemctl --user restart hermes-gateway.service
# 5. TEST
# 6. If fix works — clean up workspace commit (amend/squash later into proper commit)
# If fix fails — revert workspace with git checkout and try again.What NOT to do:
patch/sed/echoinside~/.hermes/hermes-agent/directly- Edit with vim/nano inside the deploy
- Run
git mergeinside the deploy for a hot-fix (merge is for testing complete branches, not single-file iterations)
Exception: Config-only changes in ~/.hermes/config.yaml or ~/.hermes/profiles/<name>/ are safe to edit directly because they are not versioned in the hermes-agent repo.
The systemd service hardcodes the deploy path:
WorkingDirectory=/home/nicolas/.hermes/hermes-agentPYTHONPATH=/home/nicolas/.hermes/hermes-agent
This is the only safe default. The service must never point to the workspace — that path is what caused new Hermes sessions to break earlier (workspace was on a branch without feat/kimi-oauth-clean).
Some DaemonCraft features require adding toolsets to platform_toolsets in ~/.hermes/config.yaml. This is a config change, not a code change, and is safe to do directly:
platform_toolsets:
daemoncraft:
- minecraft
- messaging
- memory
- vision
- ttsThese changes are global (affect all platforms) but are backward-compatible.
Implemented 2026-05-10. Two new modules in agents/:
PlanStateenum: IDLE → EXECUTING → BLOCKED → ESCALATED → REPLANNING → COMPLETEDDangerLevelenum with explicit taxonomy (per GePeTo review)VerifyTypeenum: inventory_has, area_clear, position_reached, block_placed, entity_nearbyStepdataclass: id, intent, verify, max_retries, retries, backoff_basePlandataclass: goal, steps, current_step, state, timeouts- Serde:
load_plan()/save_plan()→workspace/plan.json(atomic write via temp file)
- Reads plan from
workspace/plan.json, executes steps viaPOST /intentto embodied service - Machine-checkable verification against bot server API
- Exponential backoff on retry (2^retries seconds), max 3 retries
- Confidence gate: if
operational_riskhigh/critical → escalate immediately - Structured JSON logging for every decision
- Idle heartbeat: world_state injection via Gemma every ~30s when no plan active
daemoncraft.py: launchesagent_loop.py --interval 7(single mode, plan-driven)workspace.py: createsworkspace/subdir, writesEMBODIED_SERVICE_URLandPLAN_FILEto.envcmd_daemon: assumes workspace already bootstrapped bycmd_start; only restarts crashed processescmd_update: backs upplan.jsonfrom~/agents/<name>/before wipe, restores aftercmd_start
cmd_start— bootstrap_agent_workspace + SOUL composition →~/agents/<name>/cmd_update— wipe + cmd_start + restore plan.jsoncmd_daemon— crash restart (assumes workspace exists)workspace.py— bootstrap_agent_workspace (creates .env, config.yaml, venv, workspace/) If a change touches one path, verify the others still produce a working agent. Never leave dead code paths that reference old directory structures (~/.hermes/profiles/).
plan_complete— all steps donestep_failed— step exhausted max_retriesdanger_critical— irreversible_action, security_risk, plan_corruptionplan_timeout— no advance in 5 min
Preferred command for development (code changes, prompt edits):
cd ~/Projects/DaemonCraft/agents
python3 daemoncraft.py update companionThis does a full hard restart: stops bot+agent, wipes profile, recreates from latest code, restores plan/locations, starts fresh.
Before ANY manual daemoncraft.py command:
systemctl --user stop daemoncraft-cast.serviceFailure to do this = duplicate agents, conflicting commands, chat spam.
Check for duplicate agents:
ps aux | grep agent_loop | grep -v grepThere should be EXACTLY ONE process per agent. If you see duplicates, kill them all and restart:
kill -9 <pid1> <pid2>
python3 daemoncraft.py update companion- ✓
workspace/plan-steve.json— active goal and tasks (auto-saved/restored) - ✓
workspace/locations-steve.json— saved locations - ✗
conversation_history— cleared on every update (intentional, prevents toxic history) - ✗ Profile config — recreated from cast YAML every update
The agent loop is event-driven via WebSocket:
- Player chat → bot server receives it → broadcasts via WebSocket
type:chat - Agent's WebSocket listener receives it → sets
chat_event - Main thread wakes from
chat_event.wait(timeout=30)→ processes chat immediately
Chat interrupt: If a turn is already running when chat arrives, the agent sets _interrupt_requested = True, causing run_conversation() to exit early. The next turn then processes the chat message. This prevents chat from being trapped behind long mining/building sessions.
Self-echo filter: Steve's own chat messages are filtered out in the WebSocket listener (from != "steve"). Without this, Steve would trigger himself into an infinite echo loop, burning API calls to say "waits" every 2-3 seconds.
Idle auto-relay: On heartbeat turns (no player chat), Steve's internal monologue is NOT sent to Minecraft chat. Only chat-triggered turns auto-relay responses. This prevents Steve from talking to himself every 30 seconds.
| Symptom | Cause | Fix |
|---|---|---|
| Dashboard shows "waiting for agent turns..." | Agent crashed, hanging, or duplicate agents | Check `ps aux |
| Steve chats non-stop every 30s | Idle heartbeat auto-relay was firing | Fixed — only chat-triggered turns relay now |
| Steve echoes himself infinitely | Self-messages triggered turns | Fixed — self-echo filter in WebSocket handler |
| Steve ignores my chat for minutes | Long turn (20 tool calls) blocking chat processing | Fixed — chat interrupt mechanism |
| Plan disappears after update | Profile wiped, plan not restored | Fixed — update now saves/restores plan-steve.json |
| Two agents running | systemd service + manual command both active | systemctl --user stop daemoncraft-cast.service |
| "Reached maximum iterations (20)" | Agent used all 20 tool calls in one turn | Normal for complex tasks; interrupt helps for urgent chat |
- Agent log:
~/.local/share/daemoncraft/companion/logs/Steve_agent.log - Bot log:
~/.local/share/daemoncraft/companion/logs/Steve_bot.log - Dashboard:
http://localhost:3001/dashboard
- Model: MiniMax-M2.7
- Provider:
minimax - Base URL:
https://api.minimax.io/anthropic - API Key: Passed explicitly to
AIAgentinagent_loop.pyviaos.environ.get("MINIMAX_API_KEY")— Hermes' internal credential discovery fails for MiniMax when not passed explicitly. - Reasoning: Disabled (
reasoning_config={"enabled": False}) - Max iterations: 80 (tool calls per turn) — increased to take advantage of MiniMax prompt caching
- API mode:
anthropic_messages(forced inagent_loop.pywhen provider isminimaxand base_url ends with/anthropic)
Root cause of tool_call_id not found errors: Hermes' context compressor (compression.enabled: true) compresses old messages to save tokens. When it compresses an assistant message containing tool_calls but leaves the subsequent tool result messages, the tool_call_id references become orphaned. AIAgent's budget-exhaustion "grace call" sends these orphaned IDs to the API, which rejects them with 400 tool_call_id not found.
Fix: daemoncraft.py now sets config["compression"] = {"enabled": False} when creating agent profiles. This is permanent — profiles are recreated on every update, so the fix lives in the profile generator.
Date resolved: 2026-04-26
| File | Purpose |
|---|---|
agents/agent_loop.py |
WebSocket listener, turn loop, chat interrupt, auto-relay |
agents/daemoncraft.py |
Cast launcher, profile setup, update/start/stop/status |
agents/bot/server.js |
Mineflayer bot, HTTP API, WebSocket broadcast |
agents/casts/companion.yaml |
Cast config: model, provider, port, template |
agents/prompts/landfolk/steve.md |
Steve's character prompt |
agents/SOUL-minecraft.md |
Companion mode core rules |
~/.hermes/profiles/steve/config.yaml |
Runtime profile config (auto-generated) |
~/.hermes/profiles/steve/workspace/plan-steve.json |
Active goal + tasks (persisted) |
The bot serves a live dashboard at http://localhost:PORT/dashboard (e.g. http://localhost:3002/dashboard for Pamplinas).
Features:
- Collapsible panels — click any panel header or the ▼/▶ toggle to collapse/expand
- Collapse All / Expand All buttons in the header
- State persistence — collapse state is saved to
localStorageand restored on reload - Live WebSocket feed — status, chat, actions, agent turns, background task
- Adventures panel — browses
agents/blueprints/*.json, shows metadata, phases, and entities. Click an adventure to view its full blueprint.
Endpoints:
GET /blueprints— list all blueprint files with metadataGET /blueprints/:name— retrieve a specific blueprint JSON
The active Hermes install at ~/.hermes/hermes-agent is NEVER to be directly modified for feature work.
The actual plugin JARs live in server/data/plugins/, NOT server/plugins/.
server/plugins/(repo root) — Only Denizen scripts, mounted read-only into the container viadocker-compose.yml(./server/plugins/denizen:/data/plugins/Denizen/scripts:ro).server/data/plugins/— All plugin JARs and their data: Multiverse-Core, WorldEdit, Citizens, Denizen, Geyser, Floodgate, LibsDisguises, packetevents, spark. This directory is persisted inside the Docker volume (./server/data:/data).
Common pitfall: Running ls server/plugins/ shows only denizen. The JARs are in server/data/plugins/.
multiverse-core.jar(4.3.14) — world managementworldedit-bukkit-7.4.2.jar— WorldEditcitizens2.jar+Citizens/— NPC frameworkdenizen.jar+Denizen/— scriptinggeyser-spigot.jar+Geyser-Spigot/— Bedrock bridgefloodgate-spigot.jar+floodgate/— auth bridgeLibsDisguises.jar+LibsDisguises/— entity disguisespacketevents-spigot-2.12.1.jar— packet APIChatFilter.jar+ChatFilter/— chat moderationCoreProtect.jar+CoreProtect/— block logging / rollbackDecentHolograms.jar+DecentHolograms/— floating text / hologramsLuckPerms.jar+LuckPerms/— permissionsPlan.jar+Plan/— server analytics / metrics web UISkinsRestorer.jar+SkinsRestorer/— custom skinsTAB.jar+TAB/— tab list / scoreboard / nametags- (PlaceholderAPI is also installed as a dependency for TAB/SkinsRestorer)
After a system restart, daemoncraft-cast.service auto-starts using whatever CAST= value is in ~/.config/daemoncraft/cast.conf. This is the only source of truth for which cast launches on boot.
- If you want Pamplinas (rolemaster) after reboot,
cast.confmust sayCAST=rolemasterbefore the reboot. - Current file:
~/.config/daemoncraft/cast.conf
minecraft, geyser, and lan-broadcast services use network_mode: host so LAN/VPN discovery works via UDP multicast.
- Minecraft Java: binds directly to host port
25565/tcpon ALL interfaces - Geyser Bedrock: binds directly to host port
19132/udpon ALL interfaces - LAN Broadcast: sends UDP multicast to
224.0.2.60:4445every 1.5s for Java client discovery - Bot API (bridge network):
http://localhost:3000(Mineflayer HTTP API)
Primary reachable interface: ztuhfc4bvn (AlterMundi VPN)
- VPN IP:
10.10.20.27/24 - Server is accessible at
10.10.20.27:25565(Java) and10.10.20.27:19132(Bedrock) - Binding is
0.0.0.0so it works on localhost, LAN, and VPN simultaneously.
- Difficulty: Peaceful (no hostile mobs)
- Time: Normal day/night cycle (
doDaylightCycle true) - Game Mode: Survival
- Online Mode: false (offline/cracked allowed)
- Datapack:
daemoncraft_vis— coordinates HUD + colored team markers + glowing
Status: DISCARDED. The elaborate 6-floor Lobby Matrix with showrooms, structure catalog, mob pedestals, and item gondolas has been abandoned. It was an empty shell with no real utility and added unnecessary complexity.
What remains: The lobby flat world still exists as a simple empty space managed by Multiverse-Core. It may be used for ad-hoc creative building or testing, but it is NOT part of the adventure pipeline.
Principle: Adventures are designed in situ inside the main world, not in a separate lobby. Players and Pamplinas walk the terrain together, mark locations, and build the blueprint interactively.
-
Exploration — Players and Pamplinas explore the
worldtogether. They find natural terrain features (caves, rivers, villages, ruins) that fit the story. -
Marking — Players say things like "Pamplinas, la fase 1 va acá". Pamplinas uses
mc_story(action="log_event", event="Phase 1 marker at X,Y,Z")and updates the blueprint JSON with those coordinates. -
Blueprint Editing — Pamplinas can load the current blueprint, edit phases, entities, and events using
mc_storytools. The blueprint JSON lives inagents/blueprints/<name>.jsonand is shared with the dashboard. -
Implementation — When the design is ready, run
python3 scripts/blueprint-engine.py init agents/blueprints/<name>.jsonto execute init.commands with automatic entity tagging and block tracking. Pamplinas can also trigger this via a tool call. -
Reset — To restart the adventure from scratch, run
python3 scripts/blueprint-engine.py cleanup agents/blueprints/<name>.json. This kills all tagged entities, removes tracked blocks (setblock → air, fill → air), and cleans up sensors.
| Old Pipeline (Discarded) | New In-World Design |
|---|---|
Separate lobby world with Y-level showrooms |
Main world is the canvas |
| Blueprint compiler generates datapacks + schematics | Pamplinas executes commands directly via mc_command |
| Per-adventure worlds via Multiverse | Single world, zones marked by coordinates |
| Relocatable blueprints with dynamic center | Coordinates are absolute, chosen by walking the terrain |
| Complex regeneration preserving player progress | Simple cleanup: remove tagged entities/blocks, re-run init |
Still uses the same JSON schema:
metadata— title, theme, tonesetting— biome, center coordinates (chosen in-world), radiusinit— sensor setup + initial commandsphases— trigger, objectives, events (commands + chat), timeoutentities— mobs/NPCs to spawnobjects— items, books, signsflags— narrative state
| File | Purpose |
|---|---|
agents/blueprints/*.json |
Adventure definitions |
agents/blueprints/el-codigo-que-suena.json |
Saira's story (reference) |
agents/SOUL-rolemaster.md |
Pamplinas identity + tools |
agents/casts/rolemaster.yaml |
Cast config (1 agent: Pamplinas) |
scripts/build-lobby-v4.py |
Deprecated — kept for reference only |
scripts/blueprint-engine.py |
NEW — Init executor + tagging + cleanup for blueprints |
scripts/generate-minecraft-registry.js |
Generates minecraft-registry.json from PrismarineJS data |
- Siqui is a human player (IP 10.10.20.158), not a bot. Connecting via VPN.
- NicoElViejoGamer is a human player.
Each agent is a native Hermes profile (~/.hermes/profiles/<name>/) with true isolation:
config.yaml— model, provider, toolsets, system promptSOUL.md— persistent identity/behavior rulesmemories/— MEMORY.md, USER.mdsessions/— conversation historylogs/— agent logsworkspace/— files (locations JSON, etc.)state.db— SQLite session storecron/— scheduled jobshome/— subprocess isolation (git, ssh, etc.)
10 consolidated Minecraft tools wrap the Mineflayer HTTP API:
mc_perceive— status, nearby, map, look, scene, inventory, read_chat, commands, social, sounds, overhearmc_navigate— goto, follow, stop, look_at, pathfindmc_build— place, fill, interact, closemc_craft— craft, recipes, smeltmc_manage— bg_goto, bg_collect, bg_fight, task_status, cancel, mark, marks, go_mark, deposit, withdraw, chestmc_chat— chat, chat_to, whispermc_scene— scene description, block/entity queriesmc_screenshot— ray-traced world capture (CPU, optimized)mc_command— execute any Minecraft server command (requires operator privileges)mc_story— narrative state tracker: flags, objectives, phases, blueprints (Role Master mode)
2 meta tools:
clarify— agent asks user for clarificationsend_message— cross-platform messaging (Telegram, Discord, etc.)
Required for Telegram: Set TELEGRAM_BOT_TOKEN and TELEGRAM_HOME_CHANNEL in ~/.hermes/.env.
The bot captures screenshots via prismarine-viewer (Three.js WebGL renderer) + puppeteer (headless Chrome):
- Viewer runs on
API_PORT + 1000(e.g. 4002 for bot on 3002), first-person perspective - Puppeteer launched with
--use-angle=swiftshaderfor working WebGL in headless mode - Lazy-init: browser and page are created on first screenshot call and reused
- Default: 1280x720, saved to
/tmp/daemoncraft-screenshots/ - Endpoint:
GET /screenshotorPOST /action/screenshot - Tool:
mc_perceive(type="screenshot")returns path to captured image - Tool:
mc_screenshotfor custom filename/width/height - Agent can then use the
visiontoolset to analyze the image - FOV: 120 degrees (patched via
sedonnode_modules/prismarine-viewer/public/index.js) - PNG extension: auto-appended if missing in
file_name
Post-install note: After npm install, re-run the FOV patch:
sed -i 's/PerspectiveCamera(75,/PerspectiveCamera(120,/g' \
agents/bot/node_modules/prismarine-viewer/public/index.jsOld system (removed): mine-photo CPU ray-tracer produced corrupted output (noise/static). Fully replaced. No fallback.
cd ~/Projects/DaemonCraft
python3 -m agents.hermescraft.profile_launcher Steve --mc-username Steve# Launch any cast from a YAML config
python3 agents/daemoncraft.py start agents/casts/landfolk.yaml
python3 agents/daemoncraft.py status agents/casts/landfolk.yaml
python3 agents/daemoncraft.py stop agents/casts/landfolk.yaml
python3 agents/daemoncraft.py logs agents/casts/landfolk.yaml Steve
# Available casts:
# agents/casts/companion.yaml (1 agent)
# agents/casts/civilization.yaml (7 agents)
# agents/casts/landfolk.yaml (5 agents)agents/
├── bot/ # Mineflayer HTTP API (server.js, lib/, tests/)
├── daemoncraft.py # Cast launcher, profile setup, systemd integration
├── agent_loop.py # Native Hermes AIAgent persistent loop
├── casts/ # Cast configuration files
├── prompts/ # Character personality files (12+ characters)
├── skills/ # Behavior skill files (6 skills)
├── SOUL-*.md # Mode-specific identity and rules
└── blueprints/ # Adventure blueprint JSON files
docs/
├── design/ # Architecture and design proposals
│ ├── daemoncraft-platform-adapter.md # Hermes gateway adapter design (v5)
│ └── chat-output-pipeline-v1.md # Chat pipeline design (approved, implemented)
├── CIVILIZATION_MODE.md # Legacy mode docs (still functional)
├── COMPANION_MODE.md
├── LANDFOLK_MODE.md
└── archive/ # Outdated docs (pre-Purpur, pre-native-profiles)
├── server-setup.md # Forge 1.20.1 / Phi-Craft era
├── cross-play-setup.md # Geyser Standalone era
├── mod-integration.md # Phi-Craft mod integration (not implemented)
└── daemon-profile-template.md # Old gateway-based profile creation
These are canonical architecture proposals reviewed by Claude Code and Opus. They override ad-hoc decisions and should be consulted before implementing gateway, chat pipeline, or platform adapter features:
daemoncraft-platform-adapter.md— Hermes gateway adapter design: WebSocket inbound, HTTP outbound, TTS integration, session mapping (whisper vs broadcast), multi-agent casts, migration path (Phases 1-4).chat-output-pipeline-v1.md— Chat pipeline design: removed SAY: filter, unified chunking in server.js, brevity rules in SOUL-base.md. Approved and implemented.
| Mode | Agents | SOUL | Status |
|---|---|---|---|
| Companion | 1 (Steve) | SOUL-minecraft.md |
Legacy / test mode |
| Civilization | 7 (Marcus, Sarah, Jin, Dave, Lisa, Tommy, Elena) | SOUL-civilization.md |
Legacy / test mode |
| Landfolk | 5 (Steve, Moss, Reed, Flint, Ember) | SOUL-landfolk.md |
Legacy / test mode |
| Role Master | 1 (Pamplinas) | SOUL-rolemaster.md |
Active — currently deployed |
| HoloCraft | N/A | SOUL-holocraft.md |
Future vision — asset generation pipeline |
Full migration plan lives in the wiki:
~/wiki/projects/DaemonCraft/notes/migration-plan.md
Key phases:
- ✓ Fix broken SOULs (Companion + Landfolk migrated, all prompts verified)
- ✓ Create generic mode launcher (daemoncraft.py + YAML cast configs)
- ✓ Migrate missing primitives (bin/mc, setup.sh)
- ✓ Migrate mode documentation
- ✓ Per-agent state migration (from shared
data/to profileworkspace/) - ✓ Automated tests (tool registration, profile creation, cast config parsing)
- ✓ Integration test: spawn Landfolk cast
- ✓ Deploy Landfolk mode on live server
- PR #2 (Geyser/Bedrock): Merged. Geyser-Spigot plugin + Geyser config +
allow-non-mojang-profilesfor offline-mode crossplay. - PR #3 (Server Setup): Merged. 8 new plugins: ChatFilter, CoreProtect, DecentHolograms, LuckPerms, Plan, SkinsRestorer, TAB, PlaceholderAPI. Docker compose reorganized with
pluginsprofile. - PR #4 (DC-131 — Safety): Merged. ChatFilter config (no curse words),
ENFORCE_WHITELIST: "false"(disabled per user request for local testing). Conflicts resolved in docker-compose.yml. - PR #5 (DC-132 — Observability): Merged. Plan plugin + agent metrics JSONL logging. Conflicts resolved in docker-compose.yml.
- PR #6 (Client Packs): Merged.
docs/no longer ignored; client packs documentation preserved. Conflicts resolved in.gitignore. - Post-merge fixes: Removed duplicate
geyser-spigot.jarfrom volume; fixedserver/geyser/cache/permissions (chown 1000:1000); setDIFFICULTY: peacefulin docker-compose.yml. - Server recreation: Container recreated with
--force-recreate. All 15 plugins confirmed loaded and healthy. - kanban.db corruption: Gateway failed with "file is not a database". Root cause: corrupted SQLite header. Fixed by backing up and recreating
kanban.db, then restartinghermes-gateway.service. - Steve + NicoElViejoGamer: Both online on live server after merge.
- DC-112 Single-LLM Architecture: Implemented and tested. Gateway owns all cognition; agent_loop is heartbeat injector only.
- Two-level event system: Context-only heartbeats (silent injection) vs wake-up events (forced tool_choice=required).
- mc_no_op tool: Added for silent reactions when wake-up event requires tool call but no action is needed.
- tool_choice propagation: Fixed NameError in gateway/run.py — _run_agent now accepts tool_choice parameter.
- DaemonCraft adapter wiring: Restored Platform.DAEMONCRAFT in _create_adapter, auth maps, and home channel skip (was lost in rebase).
- Sandbox testing: Validated end-to-end — heartbeats silent, chat responses working, wake-up events triggering agent turns.
- Branch consolidation: DaemonCraft feat/dc-105 merged to main. Hermes-agent changes consolidated in feat/dc-112-daemoncraft-gateway rebased onto nousmain, merged to main, pushed to origin.
- Dashboard regression identified: DC-123 created — BOT MIND, PLAN & GOALS, BACKGROUND TASK empty after DC-112. TTS also affected.
Gateway owns ALL cognition (DC-112): The Hermes gateway is the single AIAgent session for DaemonCraft. The agent_loop's sole purpose is to poll sensors every 30s and inject heartbeat context into the gateway via the bot server's WebSocket. This eliminates the dual-LLM split-brain and makes the agent truly grounded (one memory, one plan, one mind).
Gateway owns reactive/social, agent_loop owns proactive tick: The Hermes gateway handles ALL reactive responsibilities (chat, TTS, event narration, plan mutations from player input). The agent_loop handles the proactive tick loop (heartbeat, sensor polling, quest trigger evaluation) that Hermes lacks natively. This is now fully implemented via DC-112.
Provider changes require explicit user confirmation: NEVER change LLM provider or model configurations without explicit user confirmation. Providers are paid API services. The user explicitly pays for them and has cost, privacy, and availability preferences that the agent does not have visibility into. The agent has ZERO authority to choose, switch, or default to any provider on the user's behalf. Always ask before touching any provider setting.
- Screenshot tool:
mc_screenshotwith ray-traced rendering viamine-photo - SOUL-landfolk.md: Migrated from archive with modern tool syntax
- Skill primitives: All 5 behavior skills updated to consolidated tools
- Character prompts: All 12+ prompts verified and updated
- Bug fix: Patched
mine-photo\r\nvs\nbug in block loading - Launcher:
daemoncraft.pywith YAML cast configs for all 3 modes - Setup:
setup.shadapted for native profile approach - Docs: Mode documentation for Companion, Civilization, Landfolk
- State: Per-agent workspace isolation in Hermes profiles
- Tests: 3 automated test suites (tools, configs, profiles)
- Deploy: Landfolk cast (5 agents) running on live Minecraft server
- Kanban: Task tracking via Hermes Kanban (
hermes kanban --board daemoncraft). Dispatcher OFF — manual mode only. - Config: Removed mcp_servers from ~/.hermes/config.yaml
- Daemon mode: Implemented supervisor loop that restarts dead agents/bots (DC-13)
- Toolset restriction: Stripped terminal/file/web from agents to prevent rogue subprocesses
- Systemd service: Created
daemoncraft-cast.servicefor managed cast launching - Telegram messaging: Added
messagingtoolset +HERMES_SESSION_PLATFORM=telegramenv so agents can usesend_message - Persistent agent loop:
agent_loop.pyuses HermesAIAgentdirectly — no more subprocess spawning (DC-18) - Mine-photo perf: Reduced samples 16→8, scan area 64x32x64→48x24x48, fixed undefined samples NaN bug (DC-19)
- Civilization deploy: 7 agents on ports 3006-3012 all healthy (DC-20)
- Coordinates HUD: Vanilla datapack shows live XYZ in action bar for all players
- Player markers: Team colors + glowing effect — see everyone through walls
- Reconnect fix: Eliminated bot join-leave loop race condition (DC-16)
- Dead code removed: Deleted
gateway_minecraft.py,civilization.py,profile_launcher.py(DC-17) - Behavior skills migrated: building, farming, navigation, survival, combat — adapted to 8-tool names, auto-installed on profile creation (DC-22)
- Goal system:
minecraft-goals.mdskill gives agents phase progression (Phase 1→4) and project tracking (DC-26) - bin/mc CLI: Human-facing bot control CLI migrated from archive (DC-27)
- Companion mode:
SOUL-minecraft.mdadapted,companion.yamlcast config created (DC-23, DC-25) - All docs migrated: CIVILIZATION_MODE.md, COMPANION_MODE.md, LAN_PLAY.md (DC-28)
- World type fix: Removed
LEVEL_TYPEfrom docker-compose.yml to restore default normal terrain (flat vs normal world generation) - Auto-disguise: Bot auto-executes
/disguise allayon spawn - Pamplinas team: Added to daemoncraft_vis datapack (light_purple team, coords HUD)
- Hover removed: Spring-damper hover physics removed — interfered with pathfinder/follow movement. Pamplinas now uses standard creative flight only.
Board: hermes kanban --board daemoncraft
Status: manual mode (dispatcher OFF). All tasks in triage — reviewed together via web dashboard.
CLI: hermes kanban --board daemoncraft list|show|create|comment|complete|...
Active tasks migrated: 64 (all non-done/non-cancelled from Lattice). Done tasks (100) not migrated — kept as historical record in .lattice.backup/.
Status: IN PROGRESS (2026-05-03).
The original DC-124 was "Per-profile fairPlayMode" (backlog). The Server Setup Overhaul epic is now tracked as DC-126 in Kanban ("Epic: Server Setup Overhaul -- Visual & Infra Upgrade", triage).
What was merged today (PRs #2–#6):
- PR #2: Geyser/Bedrock crossplay support
- PR #3: Plugin infrastructure (ChatFilter, CoreProtect, DecentHolograms, LuckPerms, Plan, SkinsRestorer, TAB, PlaceholderAPI)
- PR #4: Safety/whitelist (disabled for local testing)
- PR #5: Observability (Plan plugin + metrics JSONL)
- PR #6: Client packs documentation
Post-merge fix — WorldEdit wand: Default wand item is wooden_axe, which intercepts left-clicks and shows "First position set to..." instead of breaking blocks. Changed to blaze_rod in server/data/plugins/WorldEdit/config.yml. This change is live in the container volume but NOT in git (server/data/ is .gitignored). Needs persistence mechanism.
Remaining work (now in Kanban):
- Image SHA pin + plugin version inventory
- SkinsRestorer + DecentHolograms visual configuration
daemoncraft.mrpackJava client packdaemoncraft.mcpackBedrock client pack- SOUL-rolemaster stage-tools cheatsheet
- Persist plugin configs (WorldEdit wand, etc.) across container recreates
Deferred per original plan: multi-server mesh, Velocity proxy, Terraform, pre-built worlds.
Status: DONE — merged to main (2026-05-02).
| Task | Status | Notes |
|---|---|---|
| DC-109 | done | Phase 0 Prep: interrupt endpoint, plan epoch, BODY.md, DC_LOOP_MODE |
| DC-110 | done | BODY.md fix: removed mc_chat, terminal/file tools, "ask for goal" |
| DC-106 | done | Gateway consumes quest_event and blueprint_updated from WebSocket |
| DC-107 | done | Gateway owns all player-facing chat: bot filtering, @mention, interrupt |
| DC-108 | done | Loop Embodiment Cleanup: remove chat, fake injection |
| DC-111 | done | Gateway tool discovery: added 'minecraft' to CONFIGURABLE_TOOLSETS, fixed check_minecraft_available |
| DC-112 | done | Single-LLM architecture (gateway owns cognition, loop = heartbeat injector) |
Merged to main (2026-05-02): feat/dc-105-unified-social-routing → main
Status: DONE — merged to main via feat/dc-112-daemoncraft-gateway (2026-05-02).
| Task | Status | Notes |
|---|---|---|
| DC-118 | done | Define wake_up vs context event classification in heartbeat data |
| DC-119 | done | Add mc_no_op tool for silent wake-up reactions |
| DC-120 | done | Propagate tool_choice through AIAgent → transport → API |
| DC-121 | done | Implement synthetic tool call injection (assistant + tool messages) |
| DC-122 | done | End-to-end validation: heartbeats silent, chat works, wake-ups trigger turns |
Files changed in hermes-agent:
gateway/platforms/daemoncraft.py(new — heartbeat handler, two-level event system)gateway/platforms/base.py(tool_choice field in MessageEvent)gateway/run.py(propagate tool_choice, restore DaemonCraft wiring)agent/transports/chat_completions.py(dynamic tool_choice in API payload)run_agent.py(accept and propagate tool_choice parameter)
Branches:
- DaemonCraft:
feat/dc-105-unified-social-routing→main(merged 2026-05-02) - hermes-agent:
feat/dc-112-daemoncraft-gateway→main(merged 2026-05-02, pushed to origin)
Deploy status (2026-05-02):
- Workspace (
~/Projects/hermes-agent): clean onmain, 4 commits ahead of origin/main - Deploy (
~/.hermes/hermes-agent): sandbox mode ended — will update viahermes update hermes-gateway.serviceuses deploy path (correct)daemoncraft-cast.servicerunning with DC-112 agent_loop (heartbeat injector only)
Status: COMPLETE (DC-68–DC-76), but REGRESSED by DC-112.
Dashboard panels BOT MIND, PLAN & GOALS, BACKGROUND TASK are empty because agent_loop no longer sends turns to /agent/log. ACTION LOG still works (bot server). TTS relay also affected.
Tracking: DC-123 (backlog) — restore dashboard visualization and TTS relay.
Status: DISCARDED (2026-04-28). The entire lobby-based pipeline has been abandoned. See "Adventure Design in World" above for the replacement architecture.
Why discarded:
- Lobby Matrix was an empty shell with no real utility.
- Per-adventure worlds added unnecessary complexity (Multiverse management, world switching, player teleportation).
- Relocatable blueprints were over-engineered — coordinates chosen by walking the terrain are more natural and flexible.
- The compiler (datapacks + schematics) was never implemented and would have required massive effort for marginal gain.
What survived:
- Blueprint JSON format (phases, triggers, events, sensors, flags).
- Dashboard (browse, edit, save blueprints).
- Shared validation registry (
minecraft-registry.json). mc_storytools (setup_sensors,poll_sensors,advance_phase, etc.).
Replaced by: DC-85 through DC-91 (in-world blueprint engine).
All Fede654 PRs merged (#2–#6). Server recreated with 15 plugins. Difficulty: peaceful. Whitelist: disabled (for local testing). Container healthy. Geyser/Bedrock crossplay active.
DC-105 (Unified Social Routing): DONE — merged to main (2026-05-02).
DC-112 (Single-LLM Architecture): DONE — gateway owns all cognition, loop is heartbeat injector. Merged to main via feat/dc-112-daemoncraft-gateway (2026-05-02).
DC-124 (Server Setup Overhaul): IN PROGRESS — PRs #3, #4, #5, #6 merged. Remaining: DC-125 (stabilize), DC-127 (visual), DC-128 (Java client pack), DC-129 (Bedrock client pack), DC-130 (docs).
DC-123 (Dashboard/TTS regression): BACKLOG — dashboard panels empty after DC-112, TTS relay broken.
Agent model: MiniMax-M2.7 (via minimax provider, anthropic_messages api_mode for prompt caching).
Players online: Steve (agent), NicoElViejoGamer (human).
Sandbox mode: ENDED (2026-05-02). Deploy will be updated via hermes update instead of manual file copying.
Current active cast (2026-05-03): companion (Steve) — agent_loop running manually on port 3001 with MiniMax-M2.7 via minimax provider + anthropic_messages api_mode. daemoncraft-cast.service is stopped for debugging.
- Endpoint resolution bug (ACTIVE — 2026-05-03): Steve's mc_* tools hit stale port 3002 because
minecraft_tools.pyreadsMC_API_URLfrom a process-global env var set inhermes-gateway.service. The active cast runs on port 3001. Architectural fix needed: derive bot URL per DaemonCraft session, not from global env var. - DC-124 remaining tasks: DC-125 (image SHA pin, rolemaster.yaml model fix, plugin version inventory), DC-127 (SkinsRestorer + DecentHolograms visual config), DC-128 (
daemoncraft.mrpackJava client pack), DC-129 (daemoncraft.mcpackBedrock client pack), DC-130 (SOUL-rolemaster stage-tools cheatsheet). - Quest phase engine: Implemented. Phases have triggers, objectives, and
timeout_minutes.record_activityresets timer.check_timeoutauto-abandons stale quests. Players can retake or restart. - Scoreboard sensor architecture: Consolidated 3-command API.
setup_sensorscreates scoreboards + registers metadata.poll_sensorsbatch-checks all sensors (runs poll_command for dummies, reads native scores for real criteria, auto-resets fired sensors).cleanup_sensorsremoves all. Bot server.js has nativeGET /scoreboard?objective=X&player=Yendpoint via Mineflayer API.check_scoreuses this endpoint instead of parsing chat. - Sensor persistence:
active_sensorstracked instory.jsonas{name, criterion, poll_command}.setup_sensorsis idempotent — safe to call on every startup. State survives server/agent restarts. - Vision/screenshots: ✅ RESUELTO (DC-57). Reemplazamos
mine-photo(corrupto) porprismarine-viewer+puppeteercon flag--use-angle=swiftshader. WebGL headless funciona. EndpointGET /screenshotymc_perceive(type="screenshot")operativos.visiontoolset re-habilitado enrolemaster.yaml. - Standby mode: ✅ IMPLEMENTADO.
python3 -m agents.daemoncraft pause rolemaster [Pamplinas]pausa turns autónomos sin desconectar el bot del juego.resumevuelve a activar. Controlado via archivoSTANDBY_FILE+ señalSIGUSR1. - Pamplinas status:
daemoncraft-cast.serviceestá detenido. Steve (companion) es el agente activo en debugging. - No truncation policy: Chat lines > 240 chars son REJECTED con visible error (
CHAT TOO LONG — NOT SENT). Todos los agentes aprenden brevedad via prompt (máx 180 chars por línea, eficiencia poética). Elfinal_responsedel modelo va directo al chat; Hermes separa nativamente tool_calls de content. - Verify before narrate: SOUL rule — Pamplinas debe verificar mundo con
mc_perceiveantes de describir objetos/entidades. - Narrative branching: SOUL documenta exits success/failure/surrender/chaos por fase.
get_eventstool lee historial reciente. - Sensor consequence detection: Native criteria tipo
minecraft.mined:minecraft.stone_bricksdetectan cuando jugadores rompen estructuras de quest. - mc_command entity validation: Pamplinas invocó
raven(no existe). Pendiente: pre-flight de validación de entidades contra registry. - Screenshot speed: prismarine-viewer + puppeteer tarda ~4-5s por screenshot (aceptable para verify-before-narrate).
- Baritone movement: Postponed. Pathfinder actual cubre goto/follow básico.
- Scene-graph correction: Postponed.
mc_sceneprovee summary fair-play. - Human Design integration: User quiere transits, personality archetypes, variable lives. Listo para empezar.
- Companion mode deploy: Config existe pero no testeado en servidor live.
- Landfolk mode: SOUL existe pero necesita testing post-civilization.
- Role Master mode: Bot tiene operator privileges.
mc_commandymc_storylive. Polish pendiente en brevity enforcement y command validation. - Multi-bot self-echo fix:
agent_loop.pyleeMC_USERNAMEdel env. Funciona perfecto para single-bot casts. Limitación: en multi-bot, Bot A puede ver chat de Bot B como mensaje de jugador. - Language responsiveness: Todos los SOULs instruyen a responder en el idioma del jugador.
The old hermescraft-profiles project is archived at ~/ArchivedProjects/hermes-profiles-archived/.
It is for reference only — extract code primitives, prompts, behavior skills, but do NOT revive its ad-hoc architecture.
~/Projects/DaemonCraft/MEMORY.md— this file~/wiki/projects/DaemonCraft/index.md— project wiki index~/wiki/projects/DaemonCraft/notes/migration-plan.md— migration plan~/wiki/projects/DaemonCraft/notes/hermescraft-profiles-plan.md— profile architecture~/ArchivedProjects/hermes-profiles-archived/AGENTS.md— archive warning
The following observations were moved from global memory because they are specific to DaemonCraft/hermescraft development.
User preference: MUST have clean process management for Minecraft bots. Every bot needs: PID file, start/stop/status script, no orphaned processes. Must verify before assuming a bot is running. Must kill all bot processes before creating/recreating agents.
User preference: When modifying agent creation/setup code, ALWAYS discard and recreate the agent profile from scratch to ensure we're testing the latest code.
DaemonCraft architecture: agents/ layer replaces old bots/. Uses Hermes native profile system with --clone for templates. Templates stored as '-template' Hermes profiles. Prompts live in agents/prompts/.
Critical fix discovered: TUI mode uses platform_toolsets.cli, not just toolsets. Must add 'minecraft' to both toolsets AND platform_toolsets.cli for agents to work in interactive mode.
NO agregar fallbacks ni soporte backward-compatible mientras estamos en fase de testing. El formato de story.json, estructura de scoreboards, schemas de blueprints, y cualquier dato persistente bajo nuestro control DEBE mantenerse en un único formato soportado.
- Si cambiamos el formato de algo (ej:
active_scoreboardsde strings a dicts), NO agregar código que detecte y maneje ambos formatos. - Borrar los datos viejos y regenerar desde cero es la solución correcta durante testing.
- La migración de datos será implementada como un paso explícito de migración (script o utilidad) solo cuando el proyecto esté en producción real con usuarios reales que no puedan perder su progreso.
- Regla: Un solo formato soportado. Código limpio. Sin
isinstancechecks para formatos legacy.
Critical rule for itzg/minecraft-server: The LEVEL_TYPE env var in docker-compose.yml controls world generation.
| World Type | docker-compose.yml | Result |
|---|---|---|
| Normal (default) | Remove LEVEL_TYPE entirely |
level-type=default in server.properties |
| Flat | LEVEL_TYPE: "FLAT" |
level-type=flat in server.properties |
Procedure to change world type:
- Edit
docker-compose.yml— add or removeLEVEL_TYPE - Stop and remove container:
docker stop daemoncraft-minecraft && docker rm daemoncraft-minecraft - Delete world data:
rm -rf server/data/world server/data/world_nether server/data/world_the_end - Recreate container:
docker compose up -d minecraft - Wait for healthy:
docker inspect --format='{{.State.Health.Status}}' daemoncraft-minecraft
Common pitfall: Setting LEVEL_TYPE: "DEFAULT" or LEVEL_TYPE: "NORMAL" does NOT work as expected. The itzg/minecraft-server image writes level-type=default to server.properties, but Paper/Purpur may interpret this incorrectly and still generate flat terrain. The only reliable way to get normal terrain is to omit LEVEL_TYPE completely so the image uses its internal default.
Another pitfall: Using docker start instead of docker compose up -d after changing docker-compose.yml will restart the old container with the OLD environment variables. Always remove and recreate the container.
NUNCA truncamos salidas del modelo. Si una línea de chat es demasiado larga para el protocolo de Minecraft, la RECHAZAMOS con un error visible para que el modelo la corrija. Si un mc_command excede el límite del protocolo, el servidor echa al bot (error visible). El modelo debe aprender a generar contenido del tamaño correcto a través del prompt, no a través de post-procesamiento silencioso.
- Chat: el prompt enseña "máximo 180 caracteres por línea de chat". Si excede,
_send_chat_chunkslogueaCHAT TOO LONG — NOT SENT. - Comandos: el prompt enseña "Command Exactness — se envían EXACTAMENTE como los escribís". Si exceden el límite del protocolo, el servidor disconecta al bot.
- No hard caps, no truncation, no fixes silenciosos. Errores visibles = aprendizaje del modelo.
The deprecated hermescraft-profiles project has been archived to ~/ArchivedProjects/hermes-profiles-archived (moved from ~/Projects/hermescraft-profiles on 2026-04-23). The active Hermes install at ~/.hermes/hermes-agent had stale uncommitted symlinks and modifications from this old project (minecraft gateway platform, mc_* toolsets, etc.) which were cleaned up. Current DaemonCraft architecture uses agents/ layer with Hermes profiles/templates, not the old gateway platform approach.
User considers hermescraft behavior skill files (minecraft-building.md, minecraft-combat.md, minecraft-farming.md, minecraft-navigation.md, minecraft-survival.md) as 'primitives' that should be migrated alongside code. When they say 'bring missing primitives from hermescraft', they include these agent behavior guides, not just code endpoints.
DaemonCraft uses a persistent agent architecture where each Minecraft bot is driven by an AIAgent in a continuous loop via a dedicated agent_loop.py script. The cast (Landfolk, Civilization, etc.) is managed as a systemd user service (daemoncraft-cast.service). Agents are configured with the messaging toolset and the HERMES_SESSION_PLATFORM=telegram environment variable to enable cross-platform communication and screenshot delivery. All bots/agents must have clean process management (PID files, start/stop/status logic) to prevent orphaned processes. Profile templates for agents must be kept restricted to prevent security risks like rogue shell execution.
Bot Reconnect Race Condition: When using Mineflayer bots with an auto-reconnect strategy, 'bot.quit()' inside a 'createBot' function can trigger the 'end' event listener of the old bot, scheduling a competing (duplicate) reconnect timeout. Use 'bot.removeAllListeners()' before 'bot.quit()' to prevent infinite join/leave cascades.
Agent Loop Token Load Pattern: Sustained loops (e.g. 7 agents every 30s) can quickly hit rate limits or exhaust token quotas when using high-end models like kimi-k2.6, especially as history accumulates. Use MiniMax-M2.7 or similar via configured providers for autonomous behavior loops to preserve coding-tier quotas.
Minecraft Agent Error Feedback Pattern: Agents require actionable tool errors to prevent repetitive failure loops. Error messages should include inventory hints (e.g. "No X, you have Y") and specific geometric blockers (e.g. "target space occupied by Z", "no adjacent support"). Behavior skills should include "Pre-flight Checks" sections to instruct agents to verify state before calling physical tools.
The agent loop for Minecraft bots ('agent_loop.py') maintains a 30s interval but lacks aggressive backoff or jitter, which previously caused token quota exhaustion on expensive models like kimi-k2.6 when running a 7-bot cast. Usage optimization (switching to MiniMax-M2.7) and aggressive history trimming are preferred to preserve coding tokens.
DaemonCraft Planning Architecture: User prefers persistent, long-term planning over reactive loops. Agents should use a structured Goal & Task system (JSON-based) that persists across turns. Explicit support for a 'Rolemaster' mode (Game Master agent driving narrative/world events). Interest in using Kanban (or a similar dashboard) for real-time visibility and inter-agent coordination of these plans. Strategy roles should be assigned to specific agents for collective orchestration.
The following observations were consolidated from global agent memory because they are specific to DaemonCraft development.
DaemonCraft server runs Purpur 1.21.11 (migrated from Forge 1.20.1). Plugins: Geyser-Spigot, Floodgate, WorldEdit Bukkit, Citizens2, Denizen. Java + Bedrock crossplay via Geyser plugin (no standalone container). Mineflayer auto-detects version.
Empirical verification first: When proposing an architectural approach, test that the underlying mechanism actually works before designing tools around it. Example: verify the bot can execute Minecraft commands before building quest logic that depends on command execution. Do not assume capabilities based on code inspection alone.
Architecturally correct next step: Understand dependency chains and execute them in order without step-by-step confirmation. Example: cast config needs prompt file, prompt file needs directory, tools need registry entries — create them in that order autonomously.
Verifiable state-based triggers: User strongly prefers scoreboard sensor architecture (dynamic /execute polling + check_score) over proximity assumptions or invisible command blocks for quest triggers. No hardcoded datapack functions per quest.
Direct chat: The model's final_response (assistant content) goes directly to Minecraft chat. Hermes natively separates tool_calls from content at the protocol level. No prefixes, no filters, no SAY: format. Chat lines > 180 chars are rejected with visible error (CHAT TOO LONG — NOT SENT). All agents learn brevity via prompt, not silent fixes.
Pamplinas mode: Pamplinas is permanently in creative mode, never asks for materials, never checks inventory. Teleport is the movement fallback.
Biome/entity/block selectors: Hard fields like biomes, entity types, block IDs, and scoreboard criteria must use constrained selectors/dropdowns (not free-text editable). This aligns with DC-73 (shared validation registry).
CRITICAL: allowSprinting must be false
Mineflayer-pathfinder v2.4.5 has a bug where allowSprinting = true causes the bot to get stuck on 1-block steps. The bot bumps into the block edge and cannot jump. This happens on Purpur 1.21.11 (and likely other servers). The exact symptom matches GitHub issue #358:
"bot can jump on a block only when sprinting is disabled. otherwise it is stuck at height (Y) somewhere between the blocks."
Fix: In agents/bot/server.js, set moves.allowSprinting = false in the pathfinder Movements configuration. allowParkour can remain true. canDig can remain true.
Verification: Tested 2026-04-28 — with allowSprinting = false, the bot climbs stairs, follows players, and navigates terrain correctly in both survival and creative mode.
Note: Creative flight is a separate issue. The bot does not know how to hold jump to fly upward in creative. It will try to jump repeatedly and then pillar-build. This is documented but not yet fixed.
Status: SUPERCEDED by DC-105. The gateway adapter, TTS integration, and dashboard voice mode were all merged into the DC-105 branch. The TTS hook and dashboard toggle remain functional. See DC-105 section above for current architecture.
Voice mode config: ~/.hermes/gateway_voice_mode.json contains {"daemoncraft:overworld": "all"} — TTS is active for all messages in the overworld.
What survives from DC-94:
- Gateway adapter (
gateway/platforms/daemoncraft.py) — extended in DC-105 with bot filtering and event consumption - TTS hook (
send_voice()) — unchanged - Dashboard voice toggle + audio player — unchanged
- Deduplication logic — unchanged
- Voice config in
casts/rolemaster.yaml(edge / es-MX-JorgeNeural)
- Claude CLI stores credentials in
~/.claude/.credentials.jsonbut will NOT auto-login in non-interactive mode even if the file exists. The session must be explicitly established via interactive/loginfirst. - After login,
--printworks reliably in non-interactiveterminal()calls. - The
claudebinary in~/.npm-global/bin/may differ from the one in~/.local/bin/(checkwhich claude). Ensure PATH priority if there are conflicts. - Do NOT pipe large diffs via stdin to
claude -pwithout--dangerously-skip-permissionsor the tool approval prompts will hang the subprocess.
NEVER make runtime-only changes to bots. Every change — whether to config, SOUL, behavior, tools, env vars — MUST be backported to the source templates:
| Change location | Backport to |
|---|---|
~/agents/<name>/hermes-home/config.yaml |
workspace.py (config dict) |
~/agents/<name>/hermes-home/SOUL.md |
SOUL-base.md + prompts/<template>.md |
~/agents/<name>/hermes-home/.env |
workspace.py (env_content f-string) |
Hermes config (~/.hermes/config.yaml) |
If DaemonCraft-specific, workspace.py |
Without backporting, daemoncraft.py update companion wipes and regenerates workspaces from templates, losing ALL runtime changes. This caused repeated regressions on 2026-05-10.
Problem we keep having: "No sabemos qué está inicializado, entra basura, nos volvemos locos." Below are the concrete failure patterns found today and their signatures.
- Status: DISABLED (
systemctl --user disable hermes-gateway@pamplinas). If active again, someone re-enabled it or a deploy recreated the service. - Symptom: Constant storm of MiniMax HTTP 401 errors appearing in Minecraft chat.
- Root cause: Pamplinas had an invalid MiniMax API key and retried endlessly.
- Detection:
systemctl --user list-units --type=service --state=running | grep hermes-gateway— verify ONLY expected agents are running.
- Symptom:
<Steve> API failed after 3 retries — Connection error. - Reality: The error came from Pamplinas, not Steve. In DaemonCraft, any bot can inject messages into the shared chat bridge.
- Rule: Before blaming the apparent speaker, verify the actual PID via
journalctl --user -u hermes-gateway@<name>.
- Symptom: Agent responds only with
🕊️and⚡ Interrupting current task...repeatedly, never producing real text. - Root cause (gAndy): Session accumulated 8 unhandled API call interrupts. The gateway cannot recover from stacked interrupts.
- Fix:
systemctl --user restart hermes-gateway@<name>(clean restart, not stop/start —--replaceflag handles session wipe). - Prevention: If an agent is stuck for >2 minutes, restart before the interrupt queue deepens.
- Symptom:
APIConnectionErroror HTTP 401 from MiniMax in Hermes, butcurldirect tohttps://api.minimax.io/anthropic/v1/messagesworks. - Observation: Errors are transient. Steve and gAndy keys both have 125 chars and are valid. The 401s may be rate-limit edge cases or auth propagation delays.
- Debug: Always test direct curl with the agent's own
.envbefore assuming key corruption.
- Symptom:
Tool embodied_plan returned error: parse_failed — unparseable Gemma-Andy output (no JSON braces found) - Impact: Non-blocking — the bot retries or falls back. But it means Ollama/Gemma occasionally returns plain text instead of structured JSON.
- Note: The model
gemma-andy:e4b-v2-2-3-q8_0is the correct one. Oráculo usesgemma4:e4b-it-q8_0(inexistent) — that's Sai's domain.
# Verify only expected agents are running
systemctl --user list-units --type=service --state=running | grep hermes-gateway
# Verify bots are connected
curl -s http://localhost:3001/health && curl -s http://localhost:3002/health
# Check for recent errors across all agents (last 5 min)
journalctl --user --since '5 minutes ago' | grep -iE 'error|fail' | grep -vE 'providers.minimax|ollama_call_done|intent_done'Problem: Prism Launcher (Flatpak) renders Minecraft on Intel UHD Graphics instead of NVIDIA RTX 2060, giving ~5-7 FPS even on low settings.
Root cause: Flatpak sandbox does not inherit host PRIME environment variables. Minecraft's OpenGL renderer defaults to the integrated GPU.
Solution: Set Flatpak override for Prism Launcher to force NVIDIA PRIME offload:
flatpak override --user --env=__NV_PRIME_RENDER_OFFLOAD=1 --env=__GLX_VENDOR_LIBRARY_NAME=nvidia --env=__VK_LAYER_NV_optimus=NVIDIA_only org.prismlauncher.PrismLauncherVerify:
flatpak override --user --show org.prismlauncher.PrismLauncherShould show the three env vars under [Environment].
Check in-game: Launch instance, look for log line:
OpenGL renderer: NVIDIA GeForce RTX 2060/PCIe/SSE2
Notes:
prime-selectis NOT installed on this system — the override is the cleanest path.- Laptop is always plugged in (no battery), so disabling Intel/Optimus power-saving is fine.
- Do NOT add
[EnvironmentVariables]toinstance.cfg— Prism Launcher does not use that format. Flatpak override is the correct layer. - Shader pack (Complementary Reimagined) should be toggled via
Kin-game once NVIDIA is confirmed working.