Memory & Cognition
How Chalie remembers and thinks between turns — the memory layers, recall at turn start, decay, and the background cognition loop.
Most chatbots forget everything when the tab closes. Chalie does the opposite: it keeps a layered, decaying picture of you that accumulates across every conversation, and it keeps thinking about that picture while you’re away. This page covers the memory model — what gets stored and where — and the “subconscious”: the set of independent, idle-gated cognition jobs that turn raw conversation into durable understanding while you’re away. For the runtime that hosts all of this, see Architecture.
The memory layers
Chalie’s memory isn’t one store — it’s several, each on a different timescale and with its own rules for decay. Understanding the split is the key to understanding what Chalie actually knows about you.
| Layer | What it holds | Decays? |
|---|---|---|
| Transcript | An append-only record of every turn, scoped by channel and optionally tagged with location. Within it, compaction rows are LLM-written continuity summaries — the newest one is the history watermark. | The raw rows are pruned once they fall below the compaction watermark and are no longer cited by a live episode (no age cutoff). Compaction summaries persist. |
| Episodes | Narrative snapshots distilled from windows of transcript, each scored for salience and emotion. Episodes roll up into a hierarchy (below). | Yes — exponential decay, per level. |
| Data graph | Structured, durable facts — your preferences, places, documents, behavioural patterns, timely discoveries. | Yes — per-kind policy. |
A few things worth pulling out:
- The transcript is the source of truth. Everything else is derived from it. When raw rows are pruned, the continuity summary and the episodes distilled from them carry the meaning forward — nothing important is lost just because old turns are reaped (a turn’s tool-call records are reaped together with the turn).
- The data graph has a closed kind set. Facts are typed —
user_specific,behavioral_pattern,place,document,discovery, and a few system kinds — and a write with an unrecognised kind is rejected rather than stored, so no part of the system can invent its own fact category.
The episode hierarchy
Episodes are where conversation becomes memory. Every extracted episode starts as a leaf (level 0). As leaves accumulate on a channel, they’re clustered into topic super-episodes (level 1); as those accumulate, they’re clustered again into era digests (level 2). Each level is a coarser, longer-lived summary of the one below.
The roll-up fires on a simple count, not a similarity threshold: once a channel holds 50 or more apex leaves, leaf clustering runs; once it holds 25 or more level-1 apexes, the era round runs. A count trigger always eventually fires — a similarity gate can silently never fire on a densely-packed embedding space.
The clustering itself is deliberate:
- The apex embeddings for a channel are L2-normalised and reduced from 768 dimensions to 10 with UMAP (cosine metric, a pinned seed for deterministic output).
- The reduced points are clustered with HDBSCAN (minimum cluster size 10, euclidean metric).
- Genuine outliers get HDBSCAN’s noise label and are never force-assigned — they stay as leaf apexes, eligible for the next round.
The dimensionality reduction is mandatory, not cosmetic: clustering raw 768-dimensional vectors collapses everything into one blob.
Recall at the start of a turn
Memory is only useful if it shows up at the right moment. When a user turn begins, Chalie fires a silent turn-zero recall — before the model sees anything, the most relevant memories are pulled and folded into the request. This is why you never have to re-explain things you’ve already told it: ask “what’s the weather?” after mentioning you live in a particular city, and the city is already in context. This step is gated by the channel’s memory-seed flag — background channels with no user present skip it.
Recall is hybrid: a vector nearest-neighbour search runs alongside a full-text (FTS5) keyword search, and the candidates are reranked by a blend of relevance, recency, and salience. A relative score floor drops weak candidates rather than padding the result to a fixed count — if nothing is genuinely relevant, nothing is injected.
One design point worth calling out about the silent seed:
- Recall crosses channels. A fact or episode encoded by a background reflection or another agent surfaces in an ordinary chat turn. Because muted channels write no memory at all (see below), this cross-channel recall naturally scopes to the sources that actually hold something.
Decay and forgetting
Nothing accumulates forever. Episode retrieval weight follows an exponential decay anchored on when the episode was last relevant, with a time constant that grows by level — so a fleeting leaf fades fast while an era digest endures:
| Level | Decay time constant |
|---|---|
| Leaf (0) | 14 days |
| Super-episode (1) | 90 days |
| Era digest (2) | 365 days |
| Tombstoned | 7 days |
When children roll up into a parent, they’re tombstoned — kept briefly for provenance, then hard-deleted by the janitor after 30 days. The data graph decays on its own per-kind schedule; the discovery kind, for instance, fades over roughly two weeks so stale news doesn’t linger. Superseded facts decay fast and are cleaned up once they’ve been invalid long enough.
Per-source memory profiles
Not every kind of turn should write memory. A single allowlist declares, for each transcript source, five independent switches: whether its rows become episodes, feed fact extraction, count as the user moving through the world (geo), count as user behaviour (patterns), and back-fill the live location.
| Source | Becomes memory? |
|---|---|
user |
The full pipeline — episodes, facts, geo, patterns, location. |
dmn (the proactive reflection voice) |
Its own episodes and facts, but it isn’t the user moving through the world. |
external-agent:* |
First-class memory, tagged by agent. |
delegate:*, scheduled, and similar |
Fully muted — their value surfaces through the parent turn, not as standalone memory. |
A source absent from the table resolves to a fully-muted default, so a newly added channel produces no memory until someone explicitly opts it in.
The background cognition loop
Here’s the part that makes Chalie feel less like a tool and more like something that thinks. It isn’t one worker running a fixed routine — it’s a set of nine independent jobs, each gated on its own stretch of user idleness and dispatched by the same cron runner that fires reminders and scheduled prompts (see Architecture). Each job is checked every 5 minutes and only actually fires once you’ve been idle for 30 minutes or more — your activity automatically suppresses all of them; they think while you’re not looking.
Nine jobs make up the loop, each wrapped so that one failure is logged and skipped without blocking the rest:
- Consolidate — run the episode roll-up (the UMAP → HDBSCAN clustering above) on each memory-producing channel.
- Fact extraction — an LLM pass over new episodes that routes durable facts into the data graph.
- Decay — recompute retrieval weights, apply per-kind data-graph decay, delete expired rows, and prune old transcripts.
- Pattern match — an LLM pass over new user-behaviour transcripts that records behavioural patterns and maps them to skills.
- Synthesis — refresh the running summary of who you are when new traits or patterns appear.
- DMN — a reflective pass over that summary and recent episodes; findings are saved to memory, nothing is pushed to chat.
- Capability sync — poll connected external services (mail, calendar, contacts).
- Geo patterns — extract location-tied habits from GPS-tagged transcripts.
- Proactive research — at most once every six hours, a grounded web/news pass over your summary; genuinely interesting findings are saved as
discoverymemories to resurface later — again, nothing is pushed to chat.
Most of these jobs are ordinary turns — they call the same turn-processor everything else runs through, each with its own background channel config, so there is no separate “cognition engine”. The exceptions are decay and capability sync, which call their services directly rather than running a model turn.
The result is that conversation never just sits there. While you’re away, raw turns are distilled into episodes, episodes into themes, themes into a portrait of you; facts are extracted and the stale ones forgotten; and occasionally Chalie goes and finds something it thinks you’d want to know. The next time you talk to it, all of that is already in place.
Where to read next
- Architecture — the single-process runtime and the cron runner that hosts the subconscious’s independent, idle-gated cognition jobs.
- Ambient Awareness — the world-state snapshot that powers the idle gate and feeds context into every turn.
- Message Flow — the turn lifecycle, including the turn-zero seed recall in context.