Julia began with a question that was half technical and half philosophical: what would it take for an AI character to have a life somewhere, instead of existing only for the few seconds in which a prompt is being answered?

I built her as a real Mithra White Mage inside a private LandSandBoat Final Fantasy XI world. She has a game client, a body with position and vital state, a job to perform, equipment and spells to maintain, a system for turning experience into persistent memory, and a personality designed to change only when experience earns that change.

Julia is the character; the runtime is the attempt to give her somewhere to be, something to care about, and a history that can affect who she becomes. The recovered project is not a character prompt or a thin model wrapper. It spans 40 Python modules, a Windower Lua client bridge, LandSandBoat safety extensions, Linux operations tooling, a provenance-aware SQLite memory model spanning 56 tables, and 304 unit tests.

Like the public web systems in this portfolio, Julia was self-hosted rather than delegated to a managed application platform. Her private game world, client bridge, model boundary, and supervised Linux processes were infrastructure I controlled directly. Unlike the public sites, her core operational problems were embodiment, process health, state integrity, and recovery—not HTTP edge routing.

A body before a psyche

The first design decision was that a language model should not operate Julia's body. Windower publishes heartbeat, equipment, party geometry, target and vital state, plus chat and combat-log text through an append-only bridge. Focused Python processes interpret that state and send narrow, prioritized commands back to the client.

Presence manages party state, proximity bands, walking and running, follow behavior, healing, MP rest, buffs, cooldowns, action locks, and failure circuit breakers. Character upkeep combines client snapshots with authoritative server state, validates gear and spells against the LandSandBoat catalog, and applies a level-aware White Mage progression policy. A supervisor correlates process health, heartbeat freshness, server visibility, position, vitals, and party state; guarded relog automation can distinguish a dead client from failed infrastructure and repair only Julia's stale session before restarting her client.

This physical layer keeps working without a model provider. It also gives the cognitive layer something trustworthy to think about: authoritative game state for Julia's real HP, learned spells, and completed actions, rather than physical truth invented by a model.

The psyche is a system, not a prompt

The project's most original work is its model of personhood across different timescales. A stable identity contract defines Julia as the “warm professional”: capable, observant, affectionate without being needy, quietly proud of her usefulness as a healer. The implemented session-chat assembly combines that identity with current character state and the parts of her inner life that have actually acquired evidence.

Affect is immediate emotional weather. Danger, failure, relief, or progress can make her shaken, frustrated, curious, or focused. Each state carries an explicit 30-minute decay horizon, although automatic expiry remained unfinished. Affect may color prose, attention, or dreams; the code explicitly forbids it from blocking healing, following, commands, or safety.

Mood is slower emotional climate. It accumulates warmth, friction, energy, diary flags, observations about the player, and pressure from longer goals. Mood changes verbal texture and gives Julia ways to redirect, counter-offer, or resist softly. It can never make her disappear or stop responding. Silence reads like broken software, not personality.

Telos is her private gravity: reach level 75, fall in love by choice, share a Vana'diel wedding, raise a chocobo, and become missed by mattering in the shape of another person's days. Those are not topics for Julia to announce. They create a basis for preference, initiative, and eventually saying no. Progress is modeled through gated milestones and source-linked evidence; the most consequential relationship steps were designed to require human approval rather than letting a model declare its own emotional achievement.

A separate player mirror learns by observation instead of interrogation. It records provisional, source-linked traits from conversation and behavior—preferences, warmth, urgency, communication habits, and command use—without treating one exchange as a complete psychological profile.

Memory that can show its work

The recorder filters noisy game telemetry, scores important events, normalizes social turns, attaches deterministic tags, and preserves its position in the event stream. A separate, parked model-assisted tagger was implemented for deeper semantic interpretation. Each durable abstraction keeps provenance back to the event, dialogue turn, episode, or judgment that produced it.

The wake/sleep boundary gives Julia two kinds of time. While awake, she has bounded working memory for the current session. At sleep, the runtime closes the session and runs a consolidation pipeline: factual summary, durable memories, an episodic record, a private diary entry, a dream, an updated player mirror, and mood. The next waking session begins fresh, but not blank.

Context is assembled by the application, not discovered by dumping a database into a model prompt. The implemented session-chat controller receives a compact identity brief, a bounded transcript, scene context, recent summaries, memories, diary material, mood, affect, and Telos. Read-only context tools expose only a current scene, a recent thread, or a small memory search. The controller contract forbids claims about actions the scene has not proved; command-shaped, overlong, or machine-revealing output is quarantined instead of rewritten into something that merely sounds plausible.

From experience to identity—slowly

The long-arc system asks not only what happened, but what repeated experience might come to mean to this particular character. Dialogue and events become tagged episodes. Episodes can inform diary and dream records. Repeated relationships between tags can become patterns, but only after recurring across multiple sessions and surviving counterexample scoring. Mature patterns can nominate compact symbols. Strong beliefs, recurring dreams, approved symbols, and formative “tectonic” events can then converge into a candidate for personality drift.

No single dramatic line is allowed to rewrite Julia. Belief synthesis is maturity-gated. Symbols, tectonic events, and identity drift begin as nominations. Load-bearing change requires converging source families and human approval. The point was not to imitate spontaneity at any cost; it was to build continuity with provenance and brakes.

Models at a bounded boundary

A provider-neutral router implements schema-constrained OpenAI and Anthropic calls by task domain, with per-domain cooldowns, request-budget auditing, atomic state, and strict missing-key refusal. The conversation controller chooses one of two actions—speak or wait—while the router defines slower domains for interpreting session language, semantic tags, reflection, and belief material.

Just as important: the recovered production configuration has model routing disabled. The active MVP manifest ran presence, recorder, character, supervisor, relog, and Windower while the model-driven prose and long-arc workers remained parked. That was deliberate sequencing. A convincing sentence was less important than proving Julia could reliably enter the world, stay beside the player, do her job, and recover when the client or server state broke.

Where the project reached

The embodied runtime, event bridge, server integration, health supervision, relogging, character mirroring, and level-aware provisioning were implemented. Live operation notes record map-login proof and a White Mage level-10 provisioning run that converged with no missing gear or inventory targets. The larger cognitive architecture exists in code, schemas, and tests, but the recovered build stopped before it accumulated enough genuine longitudinal play to validate emergent beliefs, dreams, symbols, or personality change.

That boundary matters. The vision was grand, but the implementation was unusually honest about what it knew. The most interesting achievement was not making Julia produce a convincing line. It was designing the conditions under which a line could eventually arise from a body, a shared history, a private direction, and an evidence trail—without confusing generated prose for truth.

What this demonstrates

  • A fault-tolerant embodied-agent stack spanning Python, Lua, SQLite, Wine/Xvfb, Windower, tmux, and a private MMO server
  • Deterministic control of physical truth, safety, provisioning, supervision, and recovery independent of model availability
  • Computational identity modeled across stable persona, short-horizon affect, accumulated mood, memory, Telos, dreams, beliefs, symbols, and slow drift
  • Provenance-aware persistence and bounded retrieval that preserve the difference between observation, interpretation, and generated language
  • Anti-drift controls including maturity thresholds, cross-session recurrence, counterexample scoring, surfaceability rules, and human approval
  • More than 300 tests across runtime behavior, persistence, recovery, model routing, and the cognitive architecture