Memory
July 26, 2026 ยท View on GitHub
Memory is the part that compounds. Most agents forget you the moment the context window fills โ 131k tokens goes fast. Iva files everything into a plain-markdown vault, reorganizes it while you sleep, and pulls back only what each question needs. You talk, it files.

The memory tree
Iva means willow, and the memory is shaped like one:
| Layer | What lives there | Path |
|---|---|---|
| ๐ Leaves | the word-for-word transcript of each day, Iva's replies included | daily/YYYY-MM-DD.md |
| ๐ฟ Branches | summaries folded upward: day โ week โ month โ year | summaries/daily/, weekly/, monthly/, yearly/ |
| ๐ชต Trunk | CORE.md (โค1200 chars, in every prompt) + typed cards: contacts, projects, decisions, ideas, notes | CORE.md, cards/ |
CORE.md rides in every system prompt; everything else comes in per question through ranked search. A weekly summary costs about 1/35th of its seven raw days, so recall stays cheap as the vault grows.
Nightly rollup
One script, four timers, server-local time. scripts/memory/rollup.ts drives the running agent through eve/client:
| Timer | When | Reads | Writes |
|---|---|---|---|
| daily | 04:00 | yesterday's raw transcript | cards, daily summary, CORE.md |
| weekly | Sun 04:15 | 7 daily summaries | weekly summary |
| monthly | 1st, 04:20 | the month's weeklies | monthly summary |
| yearly | Jan 1, 04:25 | the year's monthlies | yearly summary |
Daily and weekly runs post a report to Telegram; monthly and yearly run silent.
The daily pass extracts entities through write_card โ a tool whose type and status enums come from the vault's schema.json, so the model cannot invent card types. Every fact gets one operation:
- โ ADD โ a new card, or a new line on an existing one.
- ๐ SUPERSEDE โ the card is rewritten to the new truth; the old value moves to an append-only
## Historyas a dated line (- 2026-03โ06: TDI Group). - โญ๏ธ NOOP โ already known, nothing written.
Facts carry a confidence: tag โ EXTRACTED (you said it) or INFERRED (Iva deduced it) โ so later answers assert the first and hedge the second. Decisions are the payoff: a decision card holds what you chose, when and why, and its History records every reversal with dates. You always see what is true now, plus the trail of how it got there.
The same pass resolves conflicts flagged in .graph/supersede-candidates.json and rewrites CORE.md: durable facts, standing preferences, at most 3 active goals โ plus dated behavioral lessons from exchanges you corrected, so a mistake made twice doesn't become a habit.
Search
memory_search runs on Node 24's built-in node:sqlite: BM25 over an FTS5 full-text index. Zero external dependencies โ no vector database, no search server, nothing extra on a $5 VPS. Hits are reranked by link distance in .graph/vault-graph.json โ cards that reference each other surface together โ and weighted by IDF coverage, so ranking stays language-agnostic: Russian, Uzbek and English all work.
For fuzzy or cross-language semantics, switch on hybrid mode (MEMORY_SEARCH_MODE=hybrid plus one embedding key โ every variable in configuration.md). Dense results are fused with BM25 via reciprocal rank fusion; the nightly doctor rebuilds the embedding sidecar.
Doctor
At 05:00 scripts/memory/doctor.ts runs mechanical maintenance โ no LLM, all deterministic โ executing the autograph scripts from scripts/autograph/ via uv:
enforceโ schema backstop: coerces type aliases, fixes invalid statuses, backfills system fields on cards written outsidewrite_cardgraph.healthโ rebuilds the link graph, appends a 0โ100 health score to historydecayโ updates relevance tiers so stale cards sinkmoc.generateโ regenerates the MOC topic indexessupersede,dedup,link_cleanupโ dry-run scans; findings queue for the next rollup, never auto-applied
Then it commits and pushes the vault. No remote yet? It creates a private iva-vault GitHub repo through gh. It pings you on Telegram only when a human is needed: a failed maintenance step, a health-score drop, CORE.md past its 1200-char cap, or a failed push (including when there's no remote and gh isn't logged in).
Vault layout
The vault is initialized from vault-template/ as its own private git repo, separate from the Iva checkout:
vault/
โโโ CORE.md # always-on core
โโโ MOC.md # topic index, regenerated nightly
โโโ cards/ # contacts/ projects/ decisions/ ideas/ notes/
โโโ daily/ # raw transcripts, one per day
โโโ summaries/daily/ # day summaries
โโโ weekly/ monthly/ yearly/
โโโ attachments/ # originals, by date
โโโ schema.json # the vault schema โ types, domains, decay
โโโ .graph/ # machine-owned graph + scan results
The vault is pure data: the maintenance code and the processing prompts live in the Iva repo (scripts/autograph/, scripts/memory/instructions/), so an update ships them to every install at once. Vaults created before 0.3.3 also carry a legacy .claude/ folder โ dead weight, no longer read, safe to keep or delete.
Everything is plain markdown. Cards, summaries and CORE.md are safe to edit by hand โ enforce re-canonicalizes the frontmatter the next night. Leave MOC.md and .graph/ alone (both are regenerated) and treat daily/ as an append-only log. To browse, open the vault folder in Obsidian: wikilinks, backlinks and the graph view work as-is.
Background & prior art
Memory is the part I've worked on longest: first agent-second-brain, a Telegram-to-Obsidian pipeline; then autograph, the typed-graph schema engine Iva now ships and runs over the vault; Iva gathers both. The core idea โ keep the verbatim record, compress upward, never lose the trail โ follows the LCM: Lossless Context Management paper (Ehrlich & Blackman, 2026), with the card graph, SUPERSEDE semantics and doctor loop on top.