A seven-dwarf, one-season experiment in which each citizen is a durable, game-canonical agent with private knowledge, memory, goals, and civic agency. Dwarf Fortress remains the physical world; the agents become the local decision-makers, and no separate overseer personality plays god.
§00 · Decision
The experiment targets Windows Steam/Premium Dwarf Fortress 53.15 with DFHack 53.15-r2.
[TESTED 2026-07-13] The game is installed at
D:\SteamLibrary\steamapps\common\Dwarf Fortress; Steam stable installed DFHack
53.15-r2 at D:\SteamLibrary\steamapps\common\DFHack, and
dfhack-run version verified the match. The experiment starts from a fixed
seven-dwarf embark and runs through one in-game
season under a clocked pause-and-step loop. Each dwarf receives an individual logical
identity, private episodic memory, game-canonical personality, bounded knowledge, goals,
commitments, and the ability to accept, refuse, converse, propose, and lead.
The architecture is one external society engine beside the game, one thin DFHack bridge, and one shared local-model runtime on the Mac Studio. Dwarves are separate agents because they have separate durable selves and authority—not because seven model processes run at once. Model calls are serialized and event-driven.
§01 · Goal & proof
The first version is successful when a human can follow a causal chain from a dwarf's game-generated character and knowledge, through an individual or civic decision, to a legal change in one real fortress. Survival constrains the experiment; believable, differentiated agency is the point.
| Dimension | Required v0 behavior |
|---|---|
| Individuality | Seven stable identities persist across windows, process restart, save, and load. Each makes at least one consequential personal choice. |
| Canonical character | DF-generated traits, values, needs, skills, relationships, stress, body state, and current circumstances ground every actor. Agent memory extends this state; it does not rewrite it. |
| Epistemic integrity | A dwarf acts only on direct experience, proximity, prior conversation, assigned work, public reports it could receive, and civic meetings it attended. |
| Social causality | At least one event-gated conversation and one promise or disagreement affect a later choice. |
| Civic agency | At least one proposal receives multiple embodied stances and an expedition-leader decision before the steward changes the fortress. |
| Physical legitimacy | Every committed action maps to a legal game affordance and has a DFHack receipt. No teleportation or direct mutation of needs, health, skills, personality, relationships, or inventory. |
| Season outcome | The fixed embark reaches season end without starvation or dehydration caused by control-loop deadlock. |
§02 · Operating principles
§03 · Architecture
Windows tower Mac Studio
┌──────────────────────────────┐ ┌────────────────────┐
│ Dwarf Fortress + DFHack │ │ oMLX │
│ └─ society-bridge.lua │ │ one request at a │
│ ↕ atomic local IPC │ │ time │
│ society-engine (Python) │ ─ private route ─► │ OpenAI-compatible │
│ ├─ clock + world mirror │ │ model endpoint │
│ ├─ knowledge + scheduler │ └────────────────────┘
│ ├─ seven actor records │
│ ├─ governance + steward │
│ └─ SQLite trace │
└──────────────────────────────┘
| Boundary | Owns | Must not own |
|---|---|---|
| Dwarf Fortress | Physical world, native simulation, jobs, movement, needs, relationships, consequences, save state. | Agent memory, explicit commitments, civic deliberation, inference scheduling. |
| DFHack bridge | Normalized observations, pause/advance, capability preflight, allowlisted action application, receipts. | Policy, personality, proposal selection, model prompts. |
| Society engine | World revisions, actor state, epistemic projection, event routing, serialized turns, governance, validation, audit. | DF physics or an alternate simulation of unit bodies and jobs. |
| Shared model | One dwarf's interpretation and typed decision for one turn. | Raw DFHack commands, global memory, authority outside the active dwarf, or hidden writes to persistent state. |
Implementation code belongs in the separate sibling project
dkta-labs/dwarf-society. This repository remains the planning and design
record.
§04 · Actor model
An actor is keyed by the stable DF unit identity plus save identity. It is a record and a state machine, not a long-lived process. Its prompt is rebuilt for each turn from the smallest relevant slice of durable state.
| Actor state | Rule |
|---|---|
| Canonical self | Traits, values, needs, skills, health, stress, roles, relationships, current job, location, possessions, and circumstances come from the current world revision. They cannot be edited by the society engine. |
| Episodic memory | Stores witnessed events, delivered messages, own decisions, action receipts, consequences, promises, and explicitly marked beliefs. Every entry records provenance and visibility. |
| Goals and commitments | Have priority, status, expiry, and causal parent. A promise does not become fulfilled until a receipt or witnessed event establishes fulfillment. |
| Known civic state | Contains only proposals, decisions, and project status learned through an attended meeting, direct message, or observable public artifact. |
| Intention lease | A valid intention may shape labor eligibility or bind the dwarf to an existing legal job for a limited number of windows. Expiry releases the restriction; the engine never puppets movement. |
The model returns one typed intent: personal_action,
work_response, conversation, help_request,
civic_proposal, proposal_stance, or reflection.
Every non-reflection intent includes a target, priority, world preconditions, expiry, and a
short in-character justification. Hidden chain-of-thought is neither requested nor stored.
§05 · Clock & data flow
The initial tick budget is a run parameter, not an implicit constant. The game-boundary spike selects a default from observed event density and bridge latency. Every run records it, and the engine never advances while an urgent decision or unresolved action receipt is pending.
§06 · Society
Agents may exchange short messages only when DF confirms proximity, a social encounter, shared work, or attendance at the same convened meeting. There is no omniscient group chat. Delivery creates separate memory records for the speaker and each recipient; absent dwarves do not learn the content automatically.
The steward owns a narrow capability manifest. Personal capabilities include accepting or releasing an existing interruptible job, changing that dwarf's allowed work, and creating an intention lease. Civic capabilities include legal designations, work orders, building or zone requests, and labor arrangements supported by the verified bridge. The steward may translate, reject, or report missing capability. It may not choose what the fort should do, fabricate consent, or replace a failed decision with a different one.
§07 · Components & deployment
| Component | Contract |
|---|---|
society-bridge.lua | Loads with the fortress. Polls a
single-writer atomic local request spool, emits JSON responses atomically, and exposes
observe, pause, advance,
preflight, and apply. A request includes run, save, window,
revision, sequence, and command identifiers. |
clock + world_mirror | Own stable observation windows, normalized snapshots, deltas, checkpoint identity, and reconciliation. |
knowledge + scheduler | Project actor-visible facts, create event inboxes, enforce precedence, and select the next actor without model judgment. |
actors + model | Persist individual state, retrieve bounded memories, build one actor prompt, serialize local inference, and validate the intent schema. |
governance + steward | Manage proposals, meeting eligibility, stances, leader decisions, authority, consent, preflight, and action translation. |
trace | Persist the append-only causal record and render a live terminal timeline: window, trigger, active dwarf, decision visibility, proposal state, command, receipt, consequence, and failure reason. Retain full prompts and raw model responses as run-local debug artifacts; expose only short decision justifications in the readable timeline. |
| SQLite run database | Store windows, world events, actor memories, goals, commitments, conversations, proposals, stances, intents, batches, receipts, and checkpoints. One process owns writes. |
| oMLX model adapter | Use the existing private OpenAI-compatible endpoint, one in-flight request at a time, bounded context, schema-constrained output, fixed timeout, and no unattended metered-API fallback. |
The serial model constraint follows the Fleet Ground Truth: the 96GB Mac Studio is the only capable local-inference host, and concurrent clients can share decode bandwidth badly enough to trip oMLX's prefill memory guard. The Windows tower hosts the interactive experiment because it runs Steam/Premium DF; it is not treated as an inference host.
The Windows-to-Mac inference path is not assumed. The first runtime proof must verify that the Windows-local engine can reach oMLX through an existing private route or a supervised local tunnel. It must not expose either DFHack or oMLX publicly; the WSL benchmark tunnel is evidence for a fallback pattern, not proof that native Windows connectivity already works.
Atomic file IPC is a v0 implementation choice, not a permanent protocol commitment. A custom protobuf plugin is justified only after the local bridge is measured as a repeated source of correctness or throughput failure.
§08 · Failure semantics
§09 · Verification
The fixed embark runs from its initial checkpoint through season end. Automated checks enforce the §01 identity, causality, physical-legitimacy, social, civic, and survival conditions. A prespecified sample of turns is then reviewed against four questions:
The rubric is reported beside the hard counts. It is not converted into a fake automated “emergence score.” An exact behavioral replay is not required; a complete causal replay is.
§10 · Build sequence
| Proof | Exit condition |
|---|---|
| 1 · Runtime boundary | Against the selected Windows Steam/DFHack pair: identify seven citizens; read required canonical state; pause and advance a bounded window; apply one allowlisted job or labor action; receive a receipt; save/load; reject a stale command; and verify the Windows-local engine's private route to Mac oMLX. Add a native extension only for a required field or action proven absent from Lua. |
| 2 · One embodied dwarf | One actor retains memory and goals across windows, receives only filtered knowledge, emits typed intent, and survives model and bridge failure without save corruption. |
| 3 · Seven-dwarf society | Seven actors schedule through one shared model; situated conversation, commitments, civic proposals, stances, leader decisions, and steward receipts work in recorded-snapshot rehearsals. |
| 4 · Season run | The fixed embark completes the §09 acceptance run with an inspectable causal trace and no prohibited state mutation. |
§11 · Scope guard
§12 · Evidence
| Claim | Evidence |
|---|---|
| [AUTHORITATIVE] External programs can interact with DFHack over a protobuf/TCP remote interface; core and plugins can expose RPC methods, but the existing method set is not comprehensive. | DFHack remote interface |
| [AUTHORITATIVE] Current DFHack Lua APIs expose living citizens, unit position, job creation/inspection, worker assignment/removal, and immediate job checks. The API also exposes teleportation; this design explicitly forbids it. | DFHack Lua API |
| [TESTED BY PRIOR ART, NOT THIS PROJECT] A rule-based DFHack plugin can autonomously operate fresh fortresses and persist its own plan state. | BenLubar/df-ai |
| [CANDIDATE] A public 2026 experiment reports that structured DFHack state is more useful than screen scraping and warns that a large specialist multi-agent roadmap preceded a reliable control loop. | Teaching an AI to Play Dwarf Fortress: The Idea |
| [CANDIDATE] A separate public prototype demonstrates a Python LLM loop with a DFHack Lua bridge and JSON file-based external control, but targets DFHack 0.47.05 and does not establish compatibility with the selected current build. | xuruiyang/df-ai-agent |
The first game-boundary proof is therefore a required gate, not ceremony. Prior art establishes plausibility; only the selected Windows Steam/DFHack pair can establish the actual observation and action contract for this experiment.