Stelladocs

Context Engine

How Stella remembers — bi-temporal memory, prompt-cache-native recall, the citation loop, reflections, the tree-sitter code graph, and the domain taxonomy that ties it all together.

Stella accumulates knowledge about your workspace so each session starts smarter than a blank slate — and it does so prompt-cache-natively: durable knowledge rides the provider's prompt cache instead of being re-billed at full price every call.

Where knowledge lives

Everything is on your disk, under .stella/:

PathWhat it holds
.stella/memories/*.mdWorkspace memories — one Markdown lesson per file, written by save_memory
.stella/context.dbThe bi-temporal context store: episodes, reflection memories, domain facts
.stella/reflections.jsonlThe reflection mining log — one JSON lesson per line
.stella/codegraph.dbThe tree-sitter code-graph index
.stella/rules/*.mdRules — promoted memories and guard rules
.stella/skills/Project skills
.stella/domains.tomlThe domain taxonomy — the shared tagging vocabulary
.stella/store.dbThe citation ledger and telemetry

Bi-temporal means the context store keeps both when a fact was true and when Stella believed it: re-running stella init supersedes stale facts rather than deleting them, so "what did we believe then?" stays answerable.

Two injection points, one cache discipline

Stella feeds context to the model at exactly two places, chosen so the expensive part never changes:

  1. The baked prefix (stable). At session start, workspace memories and Tier-1 rules are concatenated into the system prompt — deterministically, byte-stable for the whole session. That stability is what lets the entire prefix ride the provider's prompt cache (~0.1× input cost on cached reads). A memory saved mid-session deliberately takes effect next session: hot-injecting it would invalidate the cache on every save.
  2. The recall block (volatile). Each turn, a single [auto-recalled context] message is refreshed in place right after the stable prefix — never accumulating. It carries what's relevant to this prompt: matching memories (similarity + domain overlap + recency), code-graph hits, past episodes, and selected skills — capped by default at 5 frames / ~1,200 tokens. Nothing relevant? No block at all.

Recall fans out through the Open Context Protocol (OCP) host to in-process providers — the workspace memory store and the code graph — fused by score under one token budget.

The context loopmemories · rules.stella/memories · rulescode graphtree-sitter indexrecall block5 frames · ~1,200 tokensthe model turncached prefix + recallcite_memory · reflections · episodes — memory that earns its place

Invalidation doesn't happen — and why that matters

Most agents treat memory as dynamic injection: retrieve per turn, splice into the prompt. It maximizes relevance and destroys prompt-cache locality — every turn's prompt is different, the cache misses every call, and the whole system prompt re-bills at full input price, forever.

Stella is built so invalidation structurally cannot happen, at two layers:

  • The cache layer. The prefix is byte-stable by discipline — same memories, same order, same bytes, every call of the session — and the volatile recall block lives in its own message after the prefix, refreshed in place. Nothing ever rewrites the cached bytes, so the cache entry is never invalidated mid-session. That is the difference between paying ~0.1× (cache-read) and 1.0× (cache-miss) on every call — a 10× structural cost gap that compounds across a session. It is also why a freshly saved memory waits for the next session: hot-injecting it would convert every subsequent cache hit into a miss.
  • The knowledge layer. The context store is bi-temporal: new facts supersede old ones with validity windows — they never overwrite or delete them. Re-initializing a workspace doesn't invalidate what Stella believed before; it records what changed and when. History stays queryable, provenance stays intact, and a recalled fact can always say when it was true.

The practical significance: Stella's memory gets cheaper and richer as a session runs and as a workspace ages — where per-turn-injection designs get more expensive with every memory they add. Cost architecture, not a cache trick.

The Open Context Protocol

The recall seam isn't private plumbing — it is a versioned, open wire protocol: the Open Context Protocol (ocp/1.0-draft), now its own project, with Stella as its reference host.

  • Zero-dependency wire types. The protocol's types depend on nothing but a JSON codec — a context provider can be written in any language without importing a line of Stella.
  • Machine-checked conformance. "OCP conformant" isn't marketing — it's green on the public conformance suite. A conforming provider works with any OCP host, checked at CI time rather than discovered at integration time.
  • A trust architecture, not just a transport: provenance (every frame says where it came from), budget honesty (providers respect the token budget they're given), consent, citation guarantees, version stability, and temporal validity — the bi-temporal "invalidation doesn't happen" property, standardized.

The consequence for you: the context engine is extensible without forks. Your company wiki, your issue tracker, your vector store — anything that speaks OCP can feed Stella's recall block under the same budget, scoring, and citation rules as the built-in providers. The full analysis lives in the OCP advantages paper.

The citation loop: memories that earn their place

Memory in Stella is not write-only. It is a feedback loop:

  • save_memory writes a lesson (a slug plus ≤ 2,000 chars of Markdown) to .stella/memories/.
  • Recalled memories carry a stable id (nod_…). When one actually informs a turn, the model calls cite_memory with a usefulness score (1–5), a truthfulness flag, and a remark. Citations aggregate into a ledger in .stella/store.db.
  • stella memory list ranks memories by citation count, average usefulness, and truthful rate. stella memory validate flags memories whose file-path anchors no longer exist.
  • Promotion: a memory cited successfully more than 10 consecutive times (one negative citation resets the streak) becomes eligible for stella memory promote <id>, which turns it into a durable rule at .stella/rules/<slug>.md.
  • Quarantine: a memory repeatedly cited as untruthful is filtered out of every future recall block. Bad memories don't just rank lower — they disappear.

One memory's arc: from lesson to rule

Concretely, over a few sessions:

  1. Save. Mid-turn, the agent learns something durable — say, "the integration suite needs TEST_DB=memory; against a real socket it hangs" — and calls save_memory with a slug and the lesson (at most 2,000 characters of Markdown). It lands as a file in .stella/memories/ and, per the cache discipline above, takes effect from the next session.
  2. Recall. In a later session, a prompt about the integration tests matches; recall surfaces the lesson in the [auto-recalled context] block as a frame tagged with its stable id (nod_ plus 24 hex characters) — competing with everything else relevant for the default cap of 5 frames / ~1,200 tokens.
  3. Cite. The lesson actually informs the turn, so the model calls cite_memory with that nod_… id, a usefulness score (1–5), a truthfulness flag, and a one-line remark. The citation lands in the ledger in .stella/store.db.
  4. Inspect. stella memory list shows the memory climbing the ranking — citation count, average usefulness, truthful rate — and flags it once it has earned promotion.
  5. Promote. After more than 10 consecutive positive citations (one negative citation resets the streak to zero), the memory is eligible: stella memory promote <id> writes it as a durable rule at .stella/rules/<slug>.md.
  6. Graduate. From the next session on, the promoted rule rides the byte-stable prompt prefix as a Tier-1 rule — standing guidance on every call, at cached-read prices, no longer needing to win recall's 5-frame contest to be seen.

Reflections: learning from every working turn

After any turn that did real work (tool calls happened — a pure chat turn is skipped to save the call), Stella spends one cheap, deterministic model call to extract 0–3 lessons, tagged with allowed domains, written to both the context store and .stella/reflections.jsonl. Failed turns get a dedicated root-cause prompt — failure is treated as the highest-value learning signal, not something to forget.

Every working turn is also recorded as an episode — a summary, the files touched, the outcome, and its time window — so future recall can surface "the last time we touched this area."

Recurring lessons that keep showing up in the reflection log are auto-promoted into skills (a new .stella/skills/<slug>/SKILL.md), capped per session and never clobbering an existing skill.

Honest measurement: A/B control turns

Does recall actually help? Stella measures instead of assuming: at a fixed rate (about every 10th turn), recall is deterministically suppressed and the turn recorded as a control turn. Comparing outcomes with and against controls keeps the memory system accountable for real, measured lift.

The code graph

graph_query gives the agent structural answers instead of grep guesses, backed by a native tree-sitter index of your code:

  • Languages: Rust, Python, JavaScript, TypeScript, TSX, and SQL.
  • Indexed: symbol definitions and import edges.
  • Queries: definitions and references (by symbol name); imports, importers, and neighbors (by file path). The same five operations back the offline stella graph CLI.

The index builds automatically: stella init builds it eagerly, and every session also builds/refreshes it in the background — the moment it's ready, graph_query switches on mid-session. An in-process file watcher (200 ms debounce, no daemon) keeps it fresh as files change, for exactly as long as the session runs.

One honest capability gap: importers edges resolve for relative TypeScript/JavaScript and Python imports. Rust use paths are indexed unresolved — an empty importers answer for a Rust file is a limitation, not a stale index.

The domain taxonomy

stella init infers a short tagging vocabulary for your project — .stella/domains.toml — and it becomes the connective tissue of the whole engine: memories, reflections, episodes, skills, and code-graph nodes all carry domain tags, so recall can relate a lesson, a past episode, and a file to the same area of the codebase.

Version-control your agent's brain

Memories, rules, skills, and the taxonomy are plain files — commit them, and your whole team's agents share the same accumulated knowledge. The .db files are local state; see what to commit.

Stella is totally free and open source, dual-licensed MIT or Apache 2.0— your choice: MIT's three-paragraph simplicity, or Apache 2.0's explicit patent grant that enterprises prefer. Use it, fork it, embed it, ship it — no account, no phone-home, no strings. What that means →

On this page