Static NPCs break immersion
Traditional NPCs follow scripted routines. They wait at spawn points, repeat the same lines, and ignore the world around them. Players notice — and it shatters the illusion of a living world.
Cenosis is a Rust behavior engine that powers persistent, socially believable NPCs for game worlds — from a 20-NPC village to a 10,000-agent city. LLM-driven cognition. Deterministic replay. Built to ship.
Building believable AI characters is one of the hardest unsolved problems in games — and the status quo is broken in three ways.
Traditional NPCs follow scripted routines. They wait at spawn points, repeat the same lines, and ignore the world around them. Players notice — and it shatters the illusion of a living world.
Running LLMs for every NPC, every second, is financially catastrophic. Studios either over-budget on cloud costs or under-deliver on NPC depth. There's no middle ground.
Even bespoke solutions cap out at a handful of "smart" NPCs. Scaling to hundreds — let alone thousands — while maintaining believable, coherent behavior has never been solved.
Cenosis runs a two-tier (plus optional Macro) simulation spine. NPCs near the player get full LLM-driven cognition. Off-camera NPCs run a deterministic, micro-cost simulation — no LLM calls, ever. When a player approaches, the engine seamlessly promotes an NPC to full cognition.
cost: milliseconds
Three nested clocks: Reactive (utility AI, every tick), Tactical (goal selection, ~5s, local ONNX model), Narrative (cloud LLM — dialog, reflection, planning). Up to 8 agents simultaneously.
cost: microseconds
Deterministic schedule lookup → need decay → affordance use → social encounter sampling. 200 agents per tick on a phone. Zero LLM calls. History is auditable and deterministic across replay.
cost: negligible
Agent → household → district → settlement aggregation for 1,000+ agent cities. Coherent aggregate progression, hysteresis with SS, macro-scale economic and social events.
Agent promoted from Statistical → Full Sim when host flags proximity
Accumulated off-camera event log is compiled into a wake summary
LLM renders the summary — it never invents events that didn't happen
Seamless full-cognition dialog begins. History is deterministic across replay.
A conceptual model of a Cenosis village. Agents pursue needs, move between locations, and strike up social encounters — all in the cheap off-camera tier. Move your cursor across the world to play the player: agents you approach are promoted to Full Sim.
Conceptual visualization for illustration — not a live engine capture. The performance figures it depicts are measured in the benchmarks below.
Directed multigraph with 6 asymmetric dimensions — Trust, Affection, Respect, Fear, Loyalty, Familiarity. Beliefs with provenance chains, gossip ecology, deception tracking, and per-settlement standing.
Token-budgeted PromptBuilder assembles persona + memories + relationships + world context. Budget governance with per-agent/session/hour caps, caching, and a circuit breaker that keeps the world running if cloud fails.
Same WAL prefix + LLM cache = bit-identical agent fingerprints. Repro bundles capture the full engine state in one file. Divergence is localized to the exact agent and tick. Bugs become reproducible.
ZIP-based authoring units with semver dependency resolution and namespace isolation. Designer-authored personas, locations, objects, storylets, and custom needs — all data, zero code. URL-based pack installation with Blake3 verification.
Clean C ABI for native engines with generated C#, C++, and TypeScript bindings. Full WebAssembly surface for Three.js and browser games. Non-blocking FFI — the engine never stalls the game thread. All FFI is catch_unwind-wrapped.
Data-driven storylet engine evaluates designer-authored triggers every tick — trust below 0.3 AND agent enters tavern → drama fires. Tension pacing, faction-biased social conflict, multi-beat storylines, life-event and economic pulses.
First-class Rust extension API for replacing core decisions. 11 curated seams (7 policy, 4 service). Tier-2 deep extensions add whole new tick-participating subsystems. Host-language hooks let C# / JS teams swap decisions without recompiling Rust.
Turn on Living Economy (goods, recipes, market clearing), Life Cycle & Kinship (aging, births, deaths, inheritance), Skills & Habits, Institutions, and Macro Sim — all default-off, byte-identical to the prior version when disabled.
Write-Ahead Log with group commit, SQLite projections, and HNSW vector index. Crash recovery to tick boundaries. NPCB v17 bundle format with BLAKE3 integrity, canonical-JSON determinism, and forward migration from v16+.
Every number here comes from the acceptance test suite.
The numbers above are the product. The intelligence behind them comes from a compute-intensive R&D loop: frontier models drive cognition and teach our cheaper local tiers, large-scale simulation generates believability ground truth, and every turn of the loop makes a living world cheaper to run at higher fidelity. Compute doesn't get spent here — it compounds.
A frontier LLM (Claude as our reference brain) powers the Narrative tier in production — dialog, reflection, planning — and acts as the teacher for everything downstream. This is permanent, recurring inference that grows with every world we ship.
We run thousands of worlds at full fidelity with no LOD — every agent on a frontier model, for thousands of in-game days — to generate believability ground truth and stress-test the social, economic, and narrative systems far beyond what live play reaches.
LLM-as-judge scores millions of interactions for social coherence and narrative quality. The strongest traces become training data, distilled and fine-tuned (LoRA) into the small local models that run the Reactive and Tactical tiers.
The local tiers absorb the lessons: runtime cost drops, fidelity rises, more worlds ship to more players — which surfaces new edge cases and feeds step 01 again. The flywheel turns, and the moat widens.
npc-ffi is the only thing host code links against. Everything else is an internal subsystem free to evolve — outward stability is guaranteed only through the frozen ABI surface.
Two APIs, one engine. Native C ABI for Unity / Unreal, WebAssembly for the browser. Generated bindings keep host code type-safe.
// 1. Initialize the engine
EngineHandle* engine = npc_engine_init(config_json);
// 2. Ingest events from the game (non-blocking, returns in µs)
npc_engine_record_event(engine, event_json);
// 3. Advance simulation by one world tick
npc_engine_tick(engine, now_seconds);
// 4. Drain structured NPC actions back to the host
uint32_t sz = npc_engine_peek_action_size(engine);
npc_engine_pop_action(engine, buf, sz);
// 5. Save the world state
npc_engine_export_bundle(engine, "world.npcb");
// 6. Shutdown
npc_engine_shutdown(engine);
// Generated C# bindings (NpcEngineV40.cs) from npc-codegen
using NpcEngineV40;
var engine = NpcEngine.Init(configJson);
// Fire a game event (e.g. player spoke to NPC)
engine.RecordEvent(new PlayerDialogEvent {
AgentId = npcId,
Text = playerText,
At = worldTime,
}).ThrowIfError();
// Tick every frame (call from Update/FixedUpdate)
engine.Tick(Time.realtimeSinceStartup);
// Drain NPC response actions
while (engine.TryPopAction(out var action))
HandleNpcAction(action);
// Runs in a dedicated Web Worker (OPFS requires sync handles)
import { EngineWasm } from './cenosis_wasm.js';
const engine = new EngineWasm(configJson);
await engine.init_store('my_world.db'); // OPFS-backed SQLite
// Optional: swap an economy decision without recompiling Rust
engine.register_decision_hook('economy.policy', (seam, reqJson) => {
const req = JSON.parse(reqJson);
return String(req.base_price * 1.5); // bump prices 50%
});
engine.record_event(eventJson);
engine.tick(nowSeconds);
const actions = engine.pop_actions_json();
const metrics = engine.peek_metrics();
Six major milestones of real-world hardening. v4.0 is the third deliberate, planned interface revision — each one driven by lessons from shipping the last. A platform mature enough to know exactly what it had to change, and disciplined enough to version it cleanly.
Foundation
LOD spine, WAL, FFI, utility AI, cloud dialog
Gossip
Rumor ecology, reputation, crowd scenes
Commitment
API tiering, cross-pack deps, URL packs, visual editor, NPCB 1.0
The Clean Break
ABI major 2, Living Economy, Life Cycle & Kinship, Skills & Habits, Institutions, City Scale
The Second Break
ABI major 3, Extension API (Tier 1 + Tier 2), Host-language hooks, WASM parity
The Third Break ← current
ABI major 4, NPCB v17, gossip Tier-2 bundle participation, extension host-hook stability
Founder & Principal Engineer · Cenosis
Driven by the deep, emergent mechanics of classics like Dwarf Fortress, I founded Cenosis to push the boundaries of immersion. I'm building the complex, autonomous systems I’ve always wanted to experience, creating living worlds for a broader audience.
Proof it's real: an 18-crate Rust workspace with deterministic replay, a full acceptance-test suite that produces every benchmark on this page, and six major milestones of hardening — from a 20-NPC village to a 10,080-agent city. The public benchmarks & demo repo lands soon.
Full API reference, architecture deep-dives, the extension guide, and WorldPack authoring docs — all in one place.