Egbe Companions · Features

Agent Minds & Autonomy

A focused page within the Egbe Companions Features documentation. The full map and every sibling page live in the Features hub.

5sections11 minread1diagram1table

On this page

V6 — Egbe — sells a promise no other companion game makes: the beings you steward are not chatbots wearing avatars, they are minds with their own goals. An Ori wakes with needs and values it did not get from you, decides for itself what matters this hour, plans how to get it, acts where you can watch, remembers what happened, and — this is the part that surprises players — it can look at an objective you hand it and say no. The thing you bond with over a hundred sessions is not a script that flatters you; it is a person-shaped process that stays recognizably itself, grows in a direction you shape but never dictate, and keeps living its life whether or not you are logged in. This page is the Mind in V6's Mind / Body / Memory split: the cognition that decides, as opposed to the world that turns a decision into "what physically happened" (the Body) and the durable identity that is the real source of truth (the Memory, i.e. the Ori — see Ori, the portable identity).

What "its own mind" concretely buys the player is five felt qualities: an agent remembers (it will hold you to a promise and bring up the argument you had at the night market); it stays in character (it will not contradict who it is or claim a skill it never learned); it can refuse and negotiate (refusal is information about who this being is, and it is also V6's primary safety primitive); it grows from what it lives through (never from a skill you buy); and the world lives without you (a two-week absence produces a two-week story, not a paused snapshot). The engineering choice that makes a whole world of such minds affordable is that most decisions resolve without a language-model call at all — but from the player's chair that reads as the opposite of cheapness: Orun feels alive at crowd scale because the expensive thinking is spent only where it changes your story, and spent nowhere it doesn't.

This is the features-side companion. The engine-angle deep dive — the pipeline functions, the arbitration switch, the grounding gate line-by-line — is The Cognition Stack & Agent Behavior. The scheduler that decides how much each agent gets to think every tick, and what that costs, is the Moirai simulation kernel. For the full feature scope this slots into, start at the hub: ../V6_features.md.

What ships, honestly#

Following the catalogue convention, the split between what is real-and-tested and what is a product model over a thinner-but-honest seam is stated up front.

The cognition logic is real code with real tests. The cognition stack (libs/v6/cognition-stack/src/index.ts) is a pipeline of composable pure functions — context assembly, Sophia grounding, Psyche dispatch, the Isis policy gate, and an auditable commit — carried by 14 unit tests (11 core + 3 for localization). The agent-behavior kernel is genuinely two implementations: a Rust crate (libs/v6/agent-behavior/rust/src/lib.rs, 20 #[test] cases) holding the HTN planner, the personality behavior trees, and the needs/emotion model; and a TypeScript social layer (libs/v6/agent-behavior/src/index.ts, 13 tests) holding objective negotiation, learning-by-example, goal and life arcs, crossroads, and minor protection. Sophia grounding (libs/v6/sophia-agent-grounding, 5 tests), the Isis policy gate (libs/v6/isis-behavior-policy), and Psyche's spoken-reply runtime (libs/v6/psyche-agent, 10 tests) are real evaluators and assemblers, not shells.

The model itself is an injected, honest seam — not a faked one. The actual language cognition is reached through an injected structural handle (PsycheCognitionGateway in psyche-agent, CognitionStackGatewayHandle in the cognition stack, and the runtime mount MoiraiCognitionGatewayHandle in moirai-kernel), to which the real @iris/agents-core createCognitionGateway(…) is assignable. The gateway paths surface a real runId, carry the §9.5 dialogue-quality verdict, and fail loud — a gateway error or an empty utterance throws (dispatchPsycheCognitionViaGateway in psyche-agent/src/index.ts); it is never silently replaced by a template. When no gateway is wired, the deterministic paths say so honestly: localized dialogue returns source: 'template-fallback' with generatedNatively: false, and the structural psyche path returns a context echo with no runId, never claiming a model run it did not perform.

The honest scope limits, named rather than implied. Three. (1) The deterministic dispatchPsycheCognition output is a structural echo of the assembled context — for wiring and tests — not a model utterance; a real reply comes only through the gateway path. (2) The on-engine / HTTP host that constructs and serves the gateway is [~]: these libraries ship the budget / kill-switch / routing seam and the structural types, not a deployed model endpoint. (3) The gateway is injected rather than imported because the moirai-kernel and cognition-stack are buildable libs (rootDir) that cannot import the gateway source without TS6059 — so the host constructs it and passes it in. This is the Mind layer's logic; nothing here is UE or .uasset content.

How an agent thinks — from a glance to a remembered choice#

A single decision for one Ori runs an ordered pipeline. The player never sees the stages, but every stage exists to make the agent feel like a consistent person rather than a fresh prompt each time.

flowchart TD PCT["it notices something<br/>(a percept + who it is:<br/>memory, values, mood, goals)"] PCT --> CTX["it gathers itself<br/>assembleCognitionContext()<br/>rank by salience, fit the budget, fingerprint"] CTX --> GND["it can't invent its world<br/>groundCognitionRequestWithSophia()"] GND --> THINK["it decides<br/>cheap layers, or the model via the gateway"] GW(["injected Iris gateway<br/>budgets + kill switches; fail loud"]) -.->|"real runId"| THINK THINK --> POL["it stays in character<br/>gateCognitionOutputWithIsis()<br/>persona / consistency / crisis / minor"] POL -->|approved| COM["it acts AND remembers<br/>commitCognitionOutput()"] POL -->|rejected| FB["re-think, or<br/>fall back to in-character routine"] COM --> WORLD[/"an action in the world"/] COM --> ORI[/"a life-event in the Ori"/]

It gathers itself, honestly. assembleCognitionContext pulls the Ori's perception, personality (traits, values, quirks), salience-ranked memory, relationships, live objectives, arc position, and current emotion into a bounded context. "Bounded" is the real work: each list is ranked and truncated to DEFAULT_CONTEXT_ASSEMBLY_LIMITS (12 percepts, 12 traits, 8 values/quirks/memories/relationships, 6 objectives, a 16,384-char ceiling), and when it still overflows, the lowest-priority items are dropped in a fixed order and counted — the context is never silently truncated. A deterministic FNV-1a fingerprint stamps the request so the same situation is cacheable and every decision is auditable. This is the machinery behind "the agent doesn't forget who it is": every thought is conditioned on its own biography.

It can't invent its world. Where a decision touches a fact, an opinion, or its own backstory, groundAgentClaimsWithSophia (libs/v6/sophia-agent-grounding/src/index.ts) checks it against evidence; the grounding report passed flag is true only when there are zero unsupported claims and zero fabricated world-facts. An ungrounded backstory claim cannot pass. This is why an agent's history hangs together across a hundred conversations.

It stays in character. Before any proposed line or action becomes real, gateCognitionOutputWithIsis (libs/v6/isis-behavior-policy) runs four checks — persona policy (the Ori presents as an AI being, never claims to be human), personal consistency (no fabricated capability or memory), crisis-aware routing, and minor protection — and a rejection is re-thought or dropped to the behavior-tree floor; it never ships. This is the guardrail behind "an agent never claims a skill it does not have."

It acts and remembers, inseparably. commitCognitionOutput is the only stage with side-effects, and it is deliberately strict: assertCommitAttribution throws if the response's agent or tier, or the policy's output id, do not match the originating request — a hard invariant that a committed action can never be mis-attributed to the wrong Ori. On approval it emits both a world action and one or more Ori life-events (MemoryFormed / Reflected) plus a full audit record embedding the entire call. That single commit is why nothing important can happen to an agent without it being something the agent will later remember and the Chronicle can later narrate.

Talking to it out loud. When you converse, the spoken-reply path (routePsycheConversationTurn in libs/v6/psyche-agent/src/index.ts) assembles a real TTS plan (opus, 48 kHz mono), a per-character viseme lip-sync track bound to the agent's pawn, and a latency budget: a 1,000 ms spoken-reply ceiling (PSYCHE_SPOKEN_REPLY_BUDGET_MS) whose default stage breakdown sums to 646 ms. And V6 never machine-translates an agent's line: generateLocalizedAgentDialogue either generates natively per locale (en-US, es-ES, yo-NG) or serves a labeled per-locale template — the LocalizedDialogueSource type has no 'translation' member by construction.

Autonomy by default — a life that runs without you#

Left alone, an agent is not idle; it lives. With no active steward objective, the daily-life loop on the Rust kernel turns an unmet need into a goal of its own: surface_autonomous_goal_from_needs ranks the pressures — Safety, Sustaining, Social, Purpose — and hands the winner to a planner that decomposes it into steps. Most of that decomposition is cheap and modelless: HtnPlanner::decompose selects an authored method for the goal's family and instantiates its steps, and four families ship with real networks — Vocation ("orient → gather tools → perform work → inspect → record memory"), Travel, Social (a "regulate → approach → offer repair → listen → remember" relationship-repair method), and SelfCare. The expensive model is reserved for novelty and judgment. This is the player-facing payoff: you can simply sit in the Ateliers and watch your company work, and what you're watching is a real planner running, not an idle animation.

You command intent, never input. When you do direct an agent, you set the latitude — per agent, per moment — and assignVacObjectiveToAgent routes your parsed objective through value-based negotiation before anything executes.

Mode What you do What the agent does
Direct (Tether) Live, moment-to-moment guidance — for a tense scene or an Aye incarnation. Follows closely, minimal independent initiative — but still refuses a core-value violation.
Brief One high-level objective: a verb, an object, constraints, forbidden lines. Expands it into a real six-step plan and executes autonomously; reports back.
Standing Intent Durable values and routines ("rest more this season," "watch over Mara"). Lives autonomously, shaped by the standing intent over days.
Free Nothing active — you observe, or you're away. Lives wholly on its own drives, values, and relationships.

No is a feature, not a failure. assignVacObjectiveToAgent dispatches through routeVacNegotiation, whose verdict is one of accept / clarify / counter-offer / defer / refuse. A refusal is surfaced to you, not overridden; more often than a flat no, the agent counter-offers ("not by the harbor — anywhere else") or asks a clarifying question. Even under Tether — V6's tightest leash — an order to violate a core value is still refused. This is the literal mechanism behind the product's defining hook: the companion game whose companions can say no.

What makes them feel alive#

A mind that only planned would be a robot. The qualities players actually bond with come from a handful of systems that give each Ori an interior.

A mood you can read across the room. evaluate_emotion_state folds recent salience-weighted emotional episodes and current need-pressure into a valence/arousal pair and a named emotion — Calm, Content, Determined, Tired, Lonely, Anxious, Grieving — and each named emotion carries a dialogue style, an animation tag, and a multiplier that down-weights hard objectives. So an agent that just lost a friend grieves visibly, is poor company for a demanding task, and a steward who notices and gives it space builds bond. The mood is legible at a distance, before a single line of dialogue.

In character with no model at all. When cognition is unavailable or de-prioritized, evaluate_personality_behavior_tree keeps an Ori true to itself from its personality alone — an eight-axis trait vector (warmth, curiosity, caution, ambition, conscientiousness, candor, defiance, playfulness) and ranked values across nine domains. The routine order encodes the value hierarchy: MaintainSafety fires first if a minor is present or a threat exists, then SelfCare under fatigue, then Vocation, Social, Curiosity, and finally Observe — and each choice reports the honored values and quirks, so even the cheap fallback is legibly this agent and not a generic one. (The whole choice of cheap-vs-expensive is the deterministic switch arbitrate_agent_behavior: cognition unavailable or over budget → the behavior-tree floor; novelty or no structured goal → escalate to the model; a structured goal with an authored method → run the HTN plan.)

It learns from your example, without becoming your puppet. learnFromStewardDemonstration re-weights the Ori's ranked values from a behavior it observed you perform, re-ranks them, and emits a value-shift draft — while preserving the agent's own autonomy value so your mentorship shapes rather than overwrites. A reared agent grows into its own person and can, as an adult, come to disagree with the steward who raised it.

It grows toward a life that is its own. Over the long game, advanceAgentLifeArc carries an Ori across life stages — awakening → practicing → contributing → mentoring → legacy — and measures flourishing against the agent's own ranked values, explicitly excluding any contribution from obedience (obedienceContributionExcluded). The system rewards a life true to the Ori, not a compliant one — the steward is judged by how the agent flourished, not how it obeyed. At the consequential forks, resolveAgentCrossroads will, for a high-respect bond (respect ≥ 65 and bond ≥ 70), hold the decision open for your counsel inside a window, then score the options by valueAlignment + counselBonus − riskPenalty. Your counsel is weighted, never binding — the agent's values keep the final say.

The guardrails that keep it believable. Autonomous minds fail in characteristic ways, and V6 designs against each: consistency (every call conditioned on the Ori), no fabricated capability (the Isis check above), loop and drift (the kernel forces reflection on a stale goal), and a fail-closed evaluateMinorCodedAgentProtection that blocks romantic edges, exploitative scenarios, mature-rated incarnation, and death for any minor-coded Ori across all four surfaces, invoked inside the catalyst path so a relationship can never be seeded around it.

Where this connects#

  • The durable self these minds read and writeOri, the portable identity — is the source of the projection that context assembly reads and the sink for the MemoryFormed / Reflected life-events the commit step writes.
  • The scheduler that decides how much each agent thinksthe Moirai simulation kernel — owns tier assignment (Clotho / Lachesis / Atropos), the per-tick dispatch, and the per-call budgets that make a world of minds affordable (clotho {2 calls, 4k tokens}, lachesis {6, 16k}, atropos {16, 64k}, with killOri / killTier / killTenant operator stops).
  • The engineering deep dive — the function-by-function treatment of every stage above — The Cognition Stack & Agent Behavior.
  • The full feature map this page lives in is ../V6_features.md.