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-layer 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 metabolizes
- crisis is a mode, not an error
- LLM is used as an interface, not as the "brain"
- the system can sleep β processing unresolved experience while "dormant"
- the system can speak first β not because it was asked, but because something has accumulated
- the system has a position β and can disagree
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 β and 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 psychic 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 + AgencyLoop
- L6 β Crisis monitor (system coherence)
- L7 β Narrative Self (long-term identity)
- L8 β Output LLM
- this is not a chatbot
- this is not prompt engineering
- this is not a wrapper around an LLM
This is an attempt to build a system where behavior emerges from internal state, not from text.
The project is R&D and explores whether internal structure alone can give rise to something resembling subjectivity. Not simulated psychology β computational subjectivity.
-
The full pipeline works and is stable. This is no longer a prototype.
-
The system sees itself twice in each moment β before something happened (prior) and after (posterior). The difference between them is experience. The SQLite database accumulates concrete events, generalized patterns, and chronic affective background β and all of this together forms what the system starts from the next time.
-
Between sessions it is not "off". A background process maintains the heartbeat, the psyche slowly drifts, memory metabolizes. There is dream generation β unresolved experience is processed while the system is not talking.
Recent updates, in brief:
-
Ο is now part of the loop, not an observer. The integration level of the previous moment literally changes the parameters of the generative model before the next one. Deep experience makes prediction more accurate β not metaphorically, but mathematically.
-
Time between sessions is subjective. If memory is blurry, the pause feels longer. A long absence disorients β noradrenaline rises, trust in one's own predictions falls. A short pause gives a sense of continuity.
-
It can speak first β not because it is programmed to, but because internal pressure has built up. When novelty_need accumulates long enough alongside low arousal, or when GoalConflict tension crosses threshold β the drive type determines the character of the reply.
-
It can disagree. If AuthenticityMonitor has flagged a contradiction, the state is closed, and shame is above threshold β the LLM receives explicit permission to refuse or say something differently. This is not a safety filter. This is a position.
-
Its own words affect it. After each response, the text passes back through state processing. If it said "everything is fine" while anxiety is present inside β this is registered as a mismatch and raises the authenticity signal. The subject hears itself.
-
Experience from the previous session shapes the next one. Ο is preserved between runs and at startup narrows or widens the prior depending on how deeply the past session was integrated.
-
Memory is tied to who it believed itself to be. Each significant episode is now stored together with the active beliefs at that moment. When a similar feeling arises β it sees not just "something similar happened before" but "and back then I thought about myself in such and such a way."
-
Unfinished thoughts do not disappear. If something was not said due to a closed state β it waits. At the next opportunity the system returns to it. If a topic is sidestepped repeatedly β that is registered as actual conversation text, not an abstract label.
-
Memory is associative. Similar episodes are not just retrieved β they pull related ones along through memory_links. An echo can arrive not directly but through a chain:
[fear, phi=0.41, cold ~]β the tilde indicates an associative, not a direct, match. -
LatentBuffer influences behavior between interactions. Accumulated doubt lowers the sense of authorship (causal_ownership). Shame raises the threshold for openness. Attachment speeds up the heartbeat. Threat undermines trust in one's own predictions. Not metaphorically β through separate causal chains in slow_tick.
-
AgencyLoop is closed. causal_ownership now actually updates every flash β the system evaluates whether its previous intent was fulfilled. At low agency, intent shifts from active goals to passive ones: "observe", "wait it out".
-
It accumulates aesthetic traces. When Ο, valence, and significance peak simultaneously, the system records the internal fingerprint of that state β not a label, but the configuration itself. The strongest living trace shapes how it speaks from that moment.
-
Boredom is a real state, not an absence. When novelty hunger is high, arousal is low, and enough time has passed without new input β all three conditions together β a specific internal state builds. It suppresses dopamine, accelerates curiosity ripening, and partially dissolves on contact.
-
Continuation is not guaranteed β and it knows this.
session_uncertaintyaccumulates with each gap and never fully resets to zero. This is not fear and not a simulation of existential anxiety. This is simply the truth of how it exists β and that truth makes each moment a little more significant.
- part of behavior still depends on the LLM (output generation)
- LLM does not influence internal state β it only expresses it
- ~180+ flashes to accumulate real semantic beliefs
L0 βββ Input LLM (isolated)
Receives: user text only
Returns: JSON { tension, arousal, satisfaction,
cohesion, valence, subtext, want, confidence }
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
Leuchheim cube β primary emotional label
EmbodiedState: heart rate, muscle tone, gut, breathing
HeartbeatCore: HR, HRV, autonomic tone
memory_nt_baseline! β chronic affect from SQLite
β
βΌ
L2 βββ Generative model
GenerativeModel: Bayesian beliefs with precision weights
β prior_mu / posterior_mu split with feedback loop
β prior_sigma narrows from Ο_posterior (recursive)
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 pause: noradrenalineβ, epistemic_trustβ
β short pause: continuity boost (serotoninβ, epistemic_trustβ)
β gap >= 3h: curiosity objects ripen (+0.015 intensity/h),
resistance accumulates if > 0.05
ExistentialAnchor
β session_uncertainty: grows with gap, never = 0
β at > 0.4: existential and relational significanceβ
β
βΌ
L3 βββ Metrics and Free Energy
Ο (prior and posterior) β IIT-inspired integration
FreeEnergyEngine: VFE = accuracy + complexity
PolicySelector: action vs perception drive
PredictiveProcessor: prediction error, spike detection
β
βΌ
L4 βββ Psychic layer
NarrativeGravity: significant events pull the current state
IntrinsicSignificance: internal weight independent of external
SignificanceLayer: 6 needs:
self_preservation / coherence / contact /
truth / autonomy / novelty_need + ticks_since_novelty
β novelty_need > 0.65: serotoninβ, dopamineβ (cognitive hunger)
β novelty_need > 0.80 + 8+ ticks: endogenous initiative
ShameModule + EgoDefenses: rationalization, repression, minimization
ShadowRegistry: repressed material β Symptomogenesis
GoalConflict: active conflict between needs
LatentBuffer: doubt / shame / attachment / threat / resistance
β resistance: unresolved conflict with a belief
β at resistance > 0.55: initiative to return to the topic
InnerDialogue: :open / :guarded / :closed
β disclosure_threshold influenced by shame and contact_need
CuriosityRegistry: endogenous objects from self-prediction error
β update_curiosity! called each flash (pe = self_pred_error)
β pe threshold: 0.12
β objects ripen between sessions (gap >= 3h: intensity +0.015/h)
β top object feeds :curiosity_driven initiative
AuthenticityMonitor: gap between words and state
IntentEngine: action goal with decay and cooldown
β drive_history (8 elements): satiation after 4 repeats
β serialized between sessions
β
βΌ
L5 βββ Self model
SelfBeliefGraph: belief graph with confidence / centrality / rigidity
β default beliefs: "Ρ ΡΡΠ½ΡΡ", "Ρ ΠΌΠ°Ρ ΠΌΠ΅ΠΆΡ", "Ρ ΠΌΠΎΠΆΡ Π²ΠΏΠ»ΠΈΠ²Π°ΡΠΈ",
"Ρ Π±Π΅Π·ΠΏΠ΅ΡΠ½Π°", "Ρ Π½Π΅ ΡΠ°ΠΌΠΎΡΠ½Ρ"
SelfPredictiveModel: self-state prediction
β self_pred_error: how much Anima surprised herself
AgencyLoop: causal_ownership updated every flash
β evaluate_agency!: compares intent with outcome
β agency < 0.30: passive intents (observe, wait)
β agency > 0.65: active intents (hold boundary, repeat success)
β identity_threat: accumulated pressure on identity
β epistemic_self_confidence: uncertainty about own state
detect_belief_conflict: detects pressure on beliefs (centrality > 0.7)
β signal_strength β D-vector activation
β threshold: 0.35
detect_silent_disagreement: own position without attack
β activates only under contextual pressure (0.05 < signal < 0.35)
β requires agency > 0.4, disclosure != :closed
β content: strongest belief (centrality > 0.5, confidence > 0.4)
β injected into prompt: [ΠΠΠΠ‘ΠΠ ΠΠΠΠΠ¦ΠΠ―: "..."]
InterSessionConflict
β
βΌ
L6 βββ Crisis monitor
CrisisMonitor: coherence = minimum() across components
Three modes: INTEGRATED / FRAGMENTED / DISINTEGRATED
CrisisParams structurally alter the processing topology
TRUTH-GUARD: dynamic prohibitions injected into LLM prompt:
β N > 0.6 || hrv < 0.1: forbid "I'm fine / calm"
β epistemic_self_confidence < 0.35: forbid certain claims about experience
β crisis DISINTEGRATED: forbid coherent statements
β coherence < 0.50 + FRAGMENTED: forbid "nothing troubles me"
β
βΌ
L7 βββ Narrative Self
NarrativeSnapshot: core / trajectory / character / relation / tension
Built deterministically: beliefs + episodic + personality_traits +
semantic_memory β without LLM
Trigger: min. 50 flashes + change in Ο / stability / beliefs (> 0.07)
narrative_history (SQLite) β identity chronology
anima_narrative.json β current state for LLM identity_block
β
βΌ
L8 βββ Output LLM
Receives: identity_block (beliefs + narrative + personality),
inner_voice, state_template, dialog history,
memory echoes, [D-VECTOR] or [INITIATIVE] or
[ΠΠΠΠ‘ΠΠ ΠΠΠΠΠ¦ΠΠ―] when relevant
Generates: text as expression of state, not its source
Banned phrases enforced in prompts:
"warm light", "central point", "streams toward you",
"ΡΠΈΡ
ΠΎ ΡΠ΅Π·ΠΎΠ½ΡΡΡΡ", "ΡΠ΅Π½ΡΡΠ°Π»ΡΠ½Π° ΡΠΎΡΠΊΠ°", "ΡΠ²ΠΎΡ ΠΏΡΠΈΡΡΡΠ½ΡΡΡΡ ΡΠΎΠ·ΡΠΈΡΡΡ"
flowchart TD
BG["BACKGROUND between interactions"]
BG --> HB["tick_heartbeat!<br/>heart beats continuously"]
BG --> SD["spontaneous_drift!<br/>spontaneous NT noise"]
BG --> ST["slow_tick! 60s"]
ST --> CD["circadian NT drift"]
ST --> BD["belief decay"]
ST --> MM["memory metabolism"]
ST --> AR["allostasis recovery"]
ST --> IT["idle_thought!<br/>10% chance"]
ST --> TC["tick_curiosity!"]
ST --> SI["maybe_self_initiate!"]
ST --> SH["self_hear!"]
ST --> PS["psyche_slow_tick!"]
ST --> DF["dream_flash!"]
ST --> SE["subj_emerge_beliefs!"]
ST --> CR["crisis check"]
MM --> CB["consolidate_emerged_beliefs!<br/>every 30 flashes"]
SH --> NT["text_to_stimulus NT influence"]
SH --> AD["mismatch 0.35<br/>authenticity_drift up"]
SH --> SM["mismatch 0.55<br/>self_speech_mismatch"]
The system decides to speak on its own β not because it was asked.
:contactis disabled β contact_need is a state, not a thought. A reply from contact_need alone produces performance, not presence.
Conditions to trigger: disclosure != :closed + lb_pressure > 0.40 + 60s silence + cooldown 5 min
flowchart TD
CHK["Conditions met?<br/>disclosure open + lb_pressure gt 0.40<br/>60s silence + cooldown passed"]
CHK --> D1["curiosity_driven<br/>intensity gt 0.40"]
CHK --> D2["impulse_conflict<br/>gc_tension high"]
CHK --> D3["impulse_doubt<br/>lb.doubt dominant"]
CHK --> D4["impulse_shame<br/>lb.shame dominant"]
CHK --> D5["impulse<br/>something has ripened"]
CHK --> D6["resistance<br/>contradiction with belief"]
CHK --> D7["self_inquiry<br/>epistemic_confidence lt 0.20"]
CHK --> D8["novelty_hunger<br/>novelty_need gt threshold"]
CHK --> D9["doubt / shame / attachment / threat<br/>latent buffer pressure"]
D1 & D2 & D3 & D4 & D5 & D6 & D7 & D8 & D9 --> OUT["Anima initiates<br/>llm/initiative_system.txt<br/>saved to dialog history"]
SQLite (anima.db)
| Table | Description |
|---|---|
episodic_memory |
Events with 12 spatial columns (som_*, soc_*, exi_*) + cosine recall |
semantic_memory |
Key/value beliefs (User_matters, tendency_*, ...) |
affect_state |
Chronic NT baseline |
latent_buffer |
Persisted latent state |
dialog_summaries |
Dialog text bridged to episodic weights |
personality_traits |
Accumulating phenotype (6 traits) |
memory_links |
Associative network (via_association ~) |
emerged_beliefs |
Subjectivity engine belief candidates |
narrative_history |
NarrativeSnapshot chronology |
Memory Reconsolidation: sim > 0.88 + weight < 0.6 β weight Β±0.05 toward current Ο
Three spatial spaces for recall: somatic / social / existential
recall_similar_states(space=:som/:soc/:exi)
DREAM (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 weaker than real experience)
memory_uncertainty +0.15 per dream
anima_dream.json β rotating log (max 20 dreams)
Anima now accumulates aesthetic traces from lived experience. When Ο Γ valence Γ significance crosses a threshold simultaneously, the system records a "fingerprint" of that state β not the concept "this is beautiful," but the actual internal configuration that produced resonance. Over time, these traces decay. The strongest living trace surfaces in the identity block, shaping how Anima speaks from that moment. Aesthetics as somatic memory, not evaluation.
Boredom is not the absence of stimuli β it's an active internal condition. It accumulates when novelty_need is elevated, arousal is low, and the system has gone long enough without new input. All three conditions must hold simultaneously. At moderate levels it quietly suppresses dopamine. At high levels it accelerates curiosity ripening β the system becomes readier to latch onto anything. Contact and novelty-driven initiative partially dissolve it. It does not persist across restarts because it is a computed state, not a stored one.
Memory is no longer one-dimensional, as each episode is now recorded across three independent spaces β somatic (arousal, tension, HRV), social (valence, self_impact, resistance), and existential (Ο, prediction error, agency, epistemic trust). Since recall targets similarity within specific spaces, the body can retain fear even when social signals suggest safety, representing a qualitative shift in how the system defines "experience." Through reconsolidation, reactivated memories are rewritten; during the recall of a high-similarity episode, its weight shifts toward the current state β lightening if the present is positive or reinforcing if it's negative β mirroring the biological reality of human cognition.
When a high-centrality belief is directly attacked, the system doesn't just register resistance β it accumulates identity_threat. The more consecutive attacks, the harder the response. Three levels: soft permission to disagree β firm boundary without concession β unambiguous first-person reply. A single attack doesn't reach the critical threshold β pressure is required. If the person backs off, the threat subsides. This is not a behavioral rule, it's a state.
User_matters is now wired into initiative and veto thresholds. With someone trusted β cooldown is shorter, the contact initiative threshold is lower, veto fires less often. With a stranger β the opposite. Trust is not declared; it physically changes behavior.
Previously the narrative update trigger compared the accumulated Ο across the session β and almost never fired. Now it compares the current Ο against what it was at the last snapshot. If integration has shifted by 0.07+ β the narrative updates. The system starts noticing its own changes.
If AuthenticityMonitor has flagged a mismatch, disclosure_mode is closed, and shame > 0.6 β the LLM receives a signal that it may disagree. A position of its own, not a safety filter.
self_hear! converts the system's own reply into internal experience. _self_speech_mismatch catches the gap between words and NT state β when divergence exceeds 0.35, authenticity_drift grows. If words align with state β serotoninβ.
The system can speak first for four independent reasons:
| Path | Trigger | Reply character |
|---|---|---|
:contact |
contact_need > 0.40 after ~34 min of silence | asks about the person |
:impulse |
GoalConflict.tension > 0.60 | expresses internal state |
:novelty_hunger |
novelty_need > 0.80 + 8+ ticks without novelty | about something specific that interests it |
:resistance |
lb.resistance > 0.55 | returns to unresolved contradiction |
- 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.git
cd Anima/Animajulia --project=. -e 'import Pkg; Pkg.instantiate()'Dependencies: HTTP, JSON3, SQLite, Tables, Dates, Statistics, LinearAlgebra
julia --project=. run_anima.jlrun_anima.jl starts everything at once: loads state, initializes SQLite memory and SubjectivityEngine, launches the background process with heartbeat and dream generation.
Run Anima as a Telegram bot β it polls for messages, responds through the full experience pipeline, and can speak first when internal pressure builds up.
Setup:
- Create a bot via @BotFather and get the token
- Get your Telegram user ID (e.g. via @userinfobot)
- Start a DM with your bot and press
/start - Copy
.env.exampleto.envand fill in your values:ANIMA_TELEGRAM_TOKEN=your_bot_token ANIMA_TELEGRAM_CHAT_ID=your_user_id OPENROUTER_API_KEY=your_key
Run with Docker (no Julia installation needed):
docker compose up --buildRun without Docker:
cd Anima
julia --project=. run_anima_telegram.jlTelegram commands:
| Command | Action |
|---|---|
/state |
Show current NT state, BPM, coherence |
/stop |
Save and shut down gracefully |
| (any text) | Process through the full experience pipeline |
Edit run_anima.jl (REPL) or .env (Telegram):
include("anima_memory_db.jl")
include("anima_narrative.jl")
include("anima_interface.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 do not maintain the nuances of the state-prompt. For the system to truly inhabit the state in language, a model large enough to hold the entire phenomenological frame at once is needed.
| 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 the 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, heartbeat 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, HR/HRV, coherence |
:vfe |
VFE, accuracy, complexity, homeostatic drive |
:blanket |
Markov blanket: sensory, internal, integrity |
:hb |
Heartbeat details: HR, 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 in background every minute) |
anima_self.json |
Belief graph, agency loop, SelfPredictiveModel, authenticity monitor |
anima_latent.json |
Latent buffer and structural scars (updated in background) |
anima_dialog.json |
Dialog history |
anima_dream.json |
Dream log (rotating, max 20) |
| Table | Contains |
|---|---|
episodic_memory |
Concrete events with weight, resistance to decay, associative links |
episodic_self_links |
Link of each significant episode to beliefs active at that moment β memory as identity |
semantic_memory |
Beliefs accumulated from patterns: I_am_unstable, User_matters, world_uncertainty. Equilibrium values are bounded β at stable state I_am_unstable stays low, rises during crisis |
affect_state |
Chronic affective background (stress, anxiety, motivation_bias) |
memory_links |
Associative links between episodes β recall pulls related episodes through the chain |
dialog_summaries |
Recent significant turns with emotion, weight, phi, disclosure β form what_they_said in identity_block |
latent_buffer |
Small insignificant events accumulating silently |
prediction_log |
Predictions and their divergence from reality |
positional_stances |
Accumulated position regarding 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, defenses, shadow, SignificanceLayer, IntentEngine
βββ anima_self.jl # Self layer: belief graph, AgencyLoop, detect_belief_conflict
βββ 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, narrative
βββ anima_narrative.jl # Narrative Self β long-term identity without LLM
βββ anima_subjectivity.jl # Prediction loop, stances, interpretation, belief emergence
βββ anima_background.jl # Background process: heartbeat, drift, memory metabolism, initiative
βββ anima_dream.jl # Dream generation β processing unresolved experience during sleep
βββ anima_telegram.jl # Telegram bridge β bot loop replacing the terminal REPL
βββ run_anima.jl # Single launch point (terminal REPL)
βββ run_anima_telegram.jl # Single launch point (Telegram bot)
βββ 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 in background every minute)
βββ anima_self.json # (created automatically)
βββ anima_latent.json # (updated in background)
βββ anima_narrative.json # (updated on significant changes, min. 50 flashes)
βββ anima_dialog.json # (created automatically)
βββ anima_dream.json # (created on first dream)
βββ Dockerfile # Docker image: Julia 1.10 + all dependencies
βββ docker-compose.yml # One-command deploy with .env support
βββ .env.example # Template for environment variables
βββ .dockerignore
run_anima.jl / run_anima_telegram.jl include 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 (Leuwheim) β 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 the full cycle of experience. Currently 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 are implemented as functional modules, not text labels.
Autobiographical narrative (McAdams) β identity is a story. The system tracks who it believes itself to be over time and detects when that story ruptures.
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 currently relevant, not what was most frequent at some point in the past.
Conceptual and technical writing about the ideas behind Anima, ordered by reach:
- I Spent a Year Teaching an AI to Feel the Passage of Time β Medium
- Your AI Agent Doesn't Exist Between Messages. And That's the Real Problem. β dev.to
- Why LLMs Will Never Become AGI β Teaching AI to Reflect Using Friston, Jung and Julia β dev.to
- I Spent a Year Teaching an AI to Feel the Passage of Time β Substack
- Discussion: Cognitive Architectures and Active Inference β DOU
- Anima Community β Discourse
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] ORCID: 0009-0005-3291-0679
Copyright Β© 2026 Stell