Anima is an experimental cognitive architecture that models internal state, conflicts, and decision-making — rather than simply generating responses through an LLM.
The system is built as a multi-layered pipeline where text is not the source of behavior — it is its consequence.
Unlike typical AI systems:
- state is primary, text is secondary
- decisions emerge from internal conflict
- the system lives between interactions — the heart beats, the psyche drifts, memory is metabolized
- crisis is a mode, not an error
- LLM is used as an interface, not a "brain"
- the system can sleep — processing unresolved experience while "dormant"
- the system can initiate speech — not because it was asked, but because something has accumulated
Input → Internal State → Conflict → Decision → Output
Text is converted into a stimulus via an isolated input LLM, then passes through internal state, memory, and conflicts — only then is a decision and response formed. Between interactions the system continues to live: a background process maintains heartbeat, NT drift, memory metabolism, and psyche drift.
- L0 — Input LLM (isolated)
- L1 — Neurochemical and embodied state
- L2 — Generative / predictive model
- L3 — Metrics (φ prior/posterior, prediction error, free energy)
- L4 — Psychic layer (conflicts, defenses, significance)
- L5 — Self model
- L6 — Crisis monitor (system coherence)
- L7 — Output LLM
- full pipeline implemented and stable
- φ prior/posterior: system sees itself before and after each experience
- SQLite memory: episodic, semantic, affect — accumulate and shape state
- background process: system is alive between interactions (psyche drifts, heart beats)
- dream generation: processing unresolved experience during "sleep"
- subjectivity: prediction loop, interpretation, belief emergence from experience
- authenticity monitor: filters contradictions between state and narrative
- narrative variability: different phrasings of the same state across flashes
- φ recursively: φ posterior now shapes the next prior — high integration narrows prior_sigma, low integration widens it
- temporal depth: subjective gap = astronomical time × (1 + memory_uncertainty × 0.5); long pause → disorientation (noradrenaline↑, epistemic_trust↓), short pause → continuity boost
- initiative without stimulus: the system can initiate speech on its own when pressure accumulates (contact_need or LatentBuffer) — via a separate LLM with its own system prompt
- authentic veto: if the system internally disagrees with a request, the LLM is permitted to refuse or name things plainly
- some behavior still depends on LLM (output generation)
- LLM does not affect internal state — it only expresses it
- ~180+ flashes needed for real semantic beliefs to accumulate
- not a chatbot
- not prompt engineering
- not a wrapper around an LLM
This is an attempt to build a system where behavior emerges from internal state, not from text.
This project is R&D, aimed at exploring whether internal structure alone can give rise to something resembling subjectivity. Not simulated psychology — computational subjectivity.
L0 ─── Input LLM (isolated) ────────────────────────────────
Receives: user text only
Returns: JSON { tension, arousal, satisfaction,
cohesion, confidence, want }
No access to Anima's state, dialog history, or output LLM
Prompt: llm/input_prompt.txt
Fallback: text_to_stimulus if unavailable or confidence < 0.60
│
▼
STIMULUS enters the simulation
(+ memory_stimulus_bias + subj_predict! + subj_interpret!)
│
▼
L1 ─── Neurochemical Substrate ─────────────────────────────
NeurotransmitterState (dopamine / serotonin / noradrenaline)
Lövheim Cube → primary emotional label
EmbodiedState (heart rate, muscle tone, gut, breathing)
HeartbeatCore (BPM, HRV, autonomic tone)
memory_nt_baseline! ← chronic affect from SQLite
│
▼
L2 ─── Generative Model ────────────────────────────────────
GenerativeModel (Bayesian beliefs with precision weights)
MarkovBlanket (self/non-self boundary integrity)
HomeostaticGoals (drives as pressure, not rules)
AttentionNarrowing (attention narrowing under stress)
InteroceptiveInference (body prediction error, allostatic load)
TemporalOrientation (circadian modulation, inter-session gap)
→ subjective_gap = gap_seconds × (1 + memory_uncertainty × 0.5)
→ long subjective pause: noradrenaline↑, epistemic_trust↓
→ short pause: continuity boost (serotonin↑, epistemic_trust↑)
│
▼
L3 ─── Consciousness Metrics ───────────────────────────────
IITModule → φ_prior / φ_posterior (two views of one moment)
φ_prior: (vad, sbg_stability, epistemic_trust, allostatic_load)
φ_posterior: (blanket.integrity, vfe, intero_error)
φ feedback loop: phi_delta > 0.05 → epistemic_trust correction
φ recursively: φ_posterior → prior_mu (shift toward posterior proportional to φ)
φ > 0.5 → prior_sigma narrows (more confident prior)
φ < 0.5 → prior_sigma widens
PredictiveProcessor → prediction error, surprise
FreeEnergyEngine → VFE = complexity − accuracy
PolicySelector → epistemic + pragmatic value
│
▼
L4 ─── Psychic Layer ───────────────────────────────────────
NarrativeGravity — past events deform the present
AnticipatoryConsciousness — consciousness lives in the anticipated
SolomonoffWorldModel — MDL hypothesis with contextual_best()
ShameModule — shame vs. guilt
EpistemicDefense — defense against painful truth
ChronifiedAffect — resentment / alienation / bitterness
IntrinsicSignificance — significance gradient
MoralCausality — moral reasoning as a processing stage
FatigueSystem — cognitive / emotional / somatic exhaustion
StressRegression — regression under stress
ShadowSelf — Jungian Shadow
Metacognition — self-observation (5 levels)
SignificanceLayer — which need is at stake (6 needs)
GoalConflict — tension between competing needs
LatentBuffer — deferred reactions (doubt / shame / attachment / threat)
StructuralScars — accumulated residue from frequent breaches
│
▼
L5 ─── Self Layer ──────────────────────────────────────────
SelfBeliefGraph — self-belief graph, cascading collapse
SelfPredictiveModel — generative model for self-states
AgencyLoop — "did I cause this?"
InterSessionConflict — identity breach detection
ExistentialAnchor — continuity of self between sessions
UnknownRegister — tracking typed uncertainty
AuthenticityMonitor — rationalization risk, authenticity drift
→ authenticity_veto: if last_flags + :closed + shame > 0.6
system is permitted to disagree or refuse
SubjectivityEngine — prediction loop, stances, interpretation,
belief emergence from episodic patterns
│
▼
L6 ─── Crisis Monitor ──────────────────────────────────────
CrisisMonitor (INTEGRATED / FRAGMENTED / DISINTEGRATED)
Coherence = minimum(beliefs, boundary, model, integration)
│
▼
L7 ─── Output LLM ──────────────────────────────────────────
Full state → llm/system_prompt.txt + llm/state_template.txt
Model expresses state through language — tone, word choice,
sentence length, what it notices in the interlocutor.
Never quotes numbers or variable names directly.
═══════════════════════════════════════════════════════════
BACKGROUND PROCESS (between interactions)
tick_heartbeat! — heart beats continuously
spontaneous_drift! — spontaneous NT noise
slow_tick! (~60s):
├─ circadian NT drift
├─ belief decay
├─ memory metabolism (decay → consolidate → semantic update)
├─ allostasis recovery
├─ idle_thought! (10% chance of internal experience)
├─ _maybe_self_initiate! ← NEW: initiative without stimulus
│ conditions: disclosure != :closed
│ + (contact_need > 0.55 or lb_pressure > 0.40)
│ + 60s of user silence
│ + cooldown 100 flashes (~5 min)
│ mechanism: signal → initiative_channel → REPL →
│ llm_async(input_model, initiative_system.txt)
├─ psyche_slow_tick!
├─ dream_flash!
├─ subj_emerge_beliefs!
└─ crisis check
─────────────────────────────────────────────────────────
INITIATIVE (self-initiated speech)
System decides to speak on its own — not because it was asked
Drive type determines the direction of the remark:
:contact — wants to know how the person is doing
:doubt — something unresolved inside
:shame — uncertainty, wants to express honestly
:attachment — misses the person
:threat — inner tension
Separate system prompt: llm/initiative_system.txt
Separate model: input_llm_model (lighter, fewer tokens)
Output as: Anima> ...
Saved to dialog history
─────────────────────────────────────────────────────────
DREAM GENERATION (anima_dream.jl)
can_dream(): night 0–6h + gap>30min + 5% chance + not DISINTEGRATED
dream_flash!(): fragment of dialog_history → reconstructed stimulus
NT shift × 0.25 (sleep affects less than real experience)
memory_uncertainty +0.15 per dream
anima_dream.json — rotating log (max 20 dreams)
Previously φ only affected epistemic_trust. Now after each flash, φ_posterior shifts prior_mu toward posterior_mu proportionally to the level of integration. High φ means the system integrated the experience well — the prior becomes more stable (sigma narrows). Low φ — the prior stays wide, less prone to updating.
Result: experience with high integration physically changes the next expectation. This is not a metaphor — it is a change in the parameters of the generative model.
The system no longer measures inter-session pauses in astronomical seconds alone. subjective_gap = gap_seconds × (1 + memory_uncertainty × 0.5) — if memory is hazy, time stretches subjectively.
With a long subjective pause (> 1 hour): noradrenaline↑, epistemic_trust↓, log [TEMPORAL]. With a short one (< 10 min): continuity boost — serotonin↑, epistemic_trust↑. The system knows how much time has passed and it affects it.
Anima can initiate speech on its own. Not on a schedule, not randomly — when contact_need exceeds a threshold after ~5 minutes of silence, or when the LatentBuffer has accumulated enough pressure (doubt, shame, attachment, threat).
Mechanism: _maybe_self_initiate! in slow_tick! → signal into initiative_channel → REPL picks it up between cycles (without interrupting input) → separate LLM request via input_llm_model with prompt llm/initiative_system.txt → response is output as Anima> and saved to dialog history.
Drive type determines the character of the remark: :contact — question about the person, :doubt — inner uncertainty, :attachment — missed the person, :shame — self-doubt, :threat — tension.
If the system internally disagrees with a request — AuthenticityMonitor has raised flags, disclosure_mode is :closed, shame level > 0.6 — the LLM receives a signal in its system prompt: it may disagree, refuse, or name things plainly. This is the system's own position, not a safety filter.
- Julia 1.9+
- Julia packages:
HTTP,JSON3,SQLite,Tables - API key from one of the supported providers
Download from julialang.org or via juliaup:
# Linux / macOS
curl -fsSL https://install.julialang.org | sh
# Windows (PowerShell)
winget install julia -s msstoreVerify:
julia --versiongit clone https://github.com/stell2026/Anima
cd Animajulia --project=. -e 'import Pkg; Pkg.instantiate()'Dependencies: HTTP, JSON3, SQLite, Tables, Dates, Statistics, LinearAlgebra
julia --project=. run_anima.jlrun_anima.jl launches everything at once: loads state, initializes SQLite memory and SubjectivityEngine, starts the background process with heartbeat and dream generation.
Edit run_anima.jl:
include("anima_interface.jl")
include("anima_memory_db.jl")
include("anima_subjectivity.jl")
include("anima_dream.jl")
include("anima_background.jl")
anima = Anima()
mem = MemoryDB()
subj = SubjectivityEngine(mem)
repl_with_background!(anima;
mem = mem,
subj = subj,
use_llm = true,
llm_url = "https://openrouter.ai/api/v1/chat/completions",
llm_model = "openai/gpt-oss-120b:free",
llm_key = "YOUR_OPENROUTER_API_KEY",
use_input_llm = true,
input_llm_model = "openai/gpt-oss-120b:free",
input_llm_key = "YOUR_OPENROUTER_API_KEY")OpenRouter provides access to GPT, Gemini, Claude, Llama, DeepSeek and others through a single API key. There is a free tier: openrouter.ai.
💡 If one model stops responding during a session — use two separate keys (from 2 accounts): one for the output LLM, another for the input LLM.
Smaller models (under 70B) respond but fail to hold the nuances of the state prompt. For the system to truly inhabit the state in language, the model needs to be large enough to hold the full phenomenological frame at once.
| Model | Note |
|---|---|
openai/gpt-oss-120b:free |
Default. Follows instructions precisely, handles complex state well |
google/gemini-2.5-pro |
Excellent contextual depth, cleanly handles long state templates |
meta-llama/llama-4-maverick |
Good balance of nuance and speed |
deepseek/deepseek-r1 |
Strong reasoning, accurately interprets internal state |
mistralai/mistral-large |
Reliable, stable tone across long sessions |
Models under 70B tend to flatten state — responses become generic rather than being shaped by internal dynamics.
| Command | Action |
|---|---|
| (any text) | Process as input, generate state + optional LLM response |
:bg |
Background process status: uptime, heart ticks, BPM, HRV, coherence |
:bgstop |
Stop background process |
:bgstart |
Restart background process |
:memory |
SQLite memory state: episodic count, semantic, stress, anxiety, latent pressure |
:subj |
Subjectivity state: emerged beliefs, stances, current lens, surprise |
:state |
Neurochemical state, somatic markers, BPM/HRV, coherence |
:vfe |
VFE, accuracy, complexity, homeostatic drive |
:blanket |
Markov Blanket: sensory, internal, integrity |
:hb |
Heartbeat details: BPM, HRV, autonomic tone |
:gravity |
Narrative gravity: total field, valence, dominant event |
:anchor |
Existential continuity and groundedness |
:solom |
Solomonoff model: current contextual pattern, complexity |
:self |
Belief graph: all beliefs with confidence, centrality, rigidity |
:crisis |
Crisis monitor: mode, coherence, steps in current mode |
:dreams |
Recent dreams: narrative, source, φ, nt_delta |
:history |
Last 10 dialog turns |
:clearhist |
Clear dialog history |
:save |
Force save state to disk |
:quit |
Save and exit |
| File | Contains |
|---|---|
anima_core.json |
Personality, temporal state, generative model, heartbeat |
anima_psyche.json |
Narrative gravity, anticipation, shame, defense, fatigue, SignificanceLayer, GoalConflict (updated by background every minute) |
anima_self.json |
Belief graph, agency loop, SelfPredictiveModel, authenticity monitor |
anima_latent.json |
Latent buffer and structural scars (updated by background) |
anima_dialog.json |
Dialog history |
anima_dream.json |
Dream log (rotating, max 20) |
| Table | Contains |
|---|---|
episodic_memory |
Specific events with weight, decay resistance, associative links |
semantic_memory |
Beliefs accumulated from patterns: I_am_unstable, User_matters, world_uncertainty |
affect_state |
Chronic affective baseline (stress, anxiety, motivation_bias) |
latent_buffer |
Small insignificant events accumulating silently |
prediction_log |
Predictions and their gap from reality |
positional_stances |
Accumulated stance toward types of situations |
pattern_candidates |
Candidates for new beliefs (not yet confirmed) |
emerged_beliefs |
Beliefs the system generated from experience on its own |
interpretation_history |
Lens through which situations were read |
├── anima_core.jl # Neurochemical substrate, generative model, IIT, φ
├── anima_psyche.jl # Psychic layer: gravity, shame, defense, shadow, Solomonoff
├── anima_self.jl # Self layer: belief graph, agency, uncertainty
├── anima_crisis.jl # Crisis monitor: modes, coherence
├── anima_interface.jl # Main entry point: Anima, experience!, LLM calls
├── anima_input_llm.jl # Input LLM — translates text into JSON stimulus
├── anima_memory_db.jl # SQLite memory: episodic, semantic, affect, latent
├── anima_subjectivity.jl # Prediction loop, stances, interpretation, belief emergence
├── anima_background.jl # Background process: heartbeat, drift, memory metabolism, dreams
├── anima_dream.jl # Dream generation — processing unresolved experience during sleep
├── run_anima.jl # Single launch point
├── llm/
│ ├── system_prompt.txt
│ ├── state_template.txt
│ ├── input_prompt.txt
│ └── initiative_system.txt
├── memory/
│ └── anima.db # SQLite memory database (created automatically)
├── anima_core.json # (created automatically)
├── anima_psyche.json # (updated by background every minute)
├── anima_self.json # (created automatically)
├── anima_latent.json # (updated by background)
├── anima_dialog.json # (created automatically)
└── anima_dream.json # (created on first dream)
run_anima.jl includes all files in the correct order automatically.
The architecture draws on several scientific traditions:
Predictive Processing / Active Inference (Friston, Clark) — the system maintains a generative model of the world and minimizes variational free energy. Prediction error drives learning and surprise.
Neurotransmitter Model (Lövheim) — dopamine, serotonin, noradrenaline as substrate. Emotional states emerge from their combination.
Integrated Information Theory (Tononi) — φ measures how unified a state is. φ_prior and φ_posterior give two views of one moment: before and after a full experience cycle. In v13.5 φ became recursive — it shapes the next prior.
Somatic Markers / Embodied Cognition (Damasio) — the body is part of the generative model. Gut, pulse, muscle tone — not metaphors, but states that shape processing.
Self Psychology and Defense Mechanisms (Freud, Anna Freud, Kohut) — psychological defenses, shame, and ego functions implemented as functional modules, not text labels.
Autobiographical Narrative (McAdams) — identity is a story. The system tracks who it considers itself to be over time and detects when that story breaks.
Jungian Shadow — repressed material that does not disappear but generates symptoms. Symptomogenesis is a separate module.
Chronified Affect / Ressentiment (Scheler) — some emotional states do not fade. They harden into chronic background states that color everything else.
Algorithmic Complexity / Solomonoff — the system seeks the shortest explanation of its own experience (MDL). Contextual pattern search: what is relevant now, not what was most frequent in the past.
Non-commercial use only. Full terms in LICENSE.txt.
Personal, educational, and research use: permitted with attribution.
Commercial or corporate use: requires a separate license. Contact: [2026.stell@gmail.com]
Copyright © 2026 Stell