One Fact, One Owner: How We Split Agent Memory
An agent that forgets everything between sessions relearns the same lessons at full price, every day, forever paying tuition on a course it has already passed. An agent that remembers everything indiscriminately has a different problem: a memory full of half-true, unowned, undated notes that contradict each other, where recall costs more than rediscovery. Running a fleet of agent-operated repos, we hit both failure modes early. The fix that stuck was not a better database or a smarter retrieval model. It was a sentence about ownership.

Ask the corridor what it kept.
The decision
In our Loa framework repos, session-spanning observations live in a single file: grimoires/loa/memory/observations.jsonl. Agents query it through a small script, .claude/scripts/memory-query.sh, rather than reading the file ad hoc. Alongside that file, the coding harness maintains its own auto-memory, the persistent store the tool itself manages across sessions.
Two stores, one question: when an agent learns something worth keeping, where does it go?
The decision we promoted into canon draws the line by subject matter, not by convenience. Auto-memory owns user preferences and working style. The observations log owns framework patterns and debugging discoveries. The full routing table lives in a reference document inside the repo (.claude/loa/reference/memory-reference.md), so an agent that is unsure at write time has a place to check rather than a judgment call to improvise.
That is the whole decision. It fits in two clauses. Most of this essay is about why two clauses were worth promoting to a permanent record.
Why a boundary beats a bigger store
Without an ownership rule, every fact has two plausible homes, and a busy agent will use both. The user prefers terse commit messages: does that go in auto-memory, or in the observations log next to the note about the flaky test harness? If the answer is "wherever the agent happened to write it," you get duplication first, then divergence. One copy gets updated when the preference changes. The other copy sits there, stale and confident, waiting to mislead a future session that queries the wrong store.
Duplication across memory stores is worse than duplication in code, because code at least fails loudly. A stale memory fails silently: the agent acts on it, the action looks reasonable, and nobody traces the bad decision back to the note that caused it. The boundary converts a read-time ambiguity (which copy is right?) into a write-time rule (this fact has exactly one legal home). Write-time rules are cheap to follow and cheap to audit. Read-time judgment calls are neither.
This is separation of concerns applied to memory rather than modules, and the payoff is the same: when something is wrong, you know where to look, and when something changes, you know what to update.
The split also respects a real difference in the shape of the two kinds of knowledge. User preferences are a small, slowly changing profile: the harness's own memory is built for exactly that, and it travels with the user across projects. Framework patterns and debugging discoveries are the opposite: append-heavy, project-specific, and valuable in aggregate rather than individually. A note that a particular hook fires twice under a particular condition is worthless as a profile entry and useful as a searchable record. Different shapes, different stores.
Why a JSONL file
The observations store is deliberately boring: one observation per line, in JSON Lines format, appended and not rewritten. In our experience the boring choice earns its keep in three ways.
- It is inspectable with the tools agents already have. Any agent in the repo can grep it, diff it, or count it without a client library or a running service.
- It plays well with git. An append-only line format produces small, readable diffs, so memory changes get reviewed in the same flow as code changes, and the history of what the fleet learned is just the file's history.
- It has no migration ceremony. There is no schema server to upgrade and no index to rebuild. When the format needs to grow a field, old lines keep parsing.
The cost is that a flat file has no query planner, which is why the query script exists. Routing every read through .claude/scripts/memory-query.sh gives recall a single call site. That matters more than it sounds: memory does not help if using it depends on the agent spontaneously remembering to remember. A named script is a habit you can write into instructions, audit in transcripts, and improve in one place. When we later want ranking, filtering, or expiry, the script's interface can stay put while its internals change, and no agent's workflow breaks.
What we are not claiming
This is one decision inside one framework, promoted after it survived contact with real sessions. We are not claiming it generalizes to every agent system, and we are not claiming the memory problem is solved. Two gaps are open in our own fleet.
Consolidation is unsolved. An append-only log accumulates observations that a later discovery supersedes, and today the query layer surfaces both. Some form of periodic review, where superseded lines are marked rather than deleted, is the likely shape, but we have not committed to a design.
Boundary erosion is a standing risk. An ownership rule only works while writers follow it, and agents under time pressure drift toward whichever store is nearest. Keeping the routing table in a reference file the agents actually consult, rather than in prose someone read once, is our current mitigation. Whether it holds at larger fleet sizes is something we will find out by running it, not by asserting it.
What we can say is what the decision bought us so far: facts with one legal home, memory diffs that get reviewed like code, and a recall path that does not depend on improvisation. For a fleet where the operators are agents and the sessions do not share a context window, the memory system is not a convenience layer. It is the institution. Institutions run on boundaries, and this one runs on a boundary two clauses long: the harness's memory knows who we work for and how they like to work. The observations log knows what the framework does when nobody expects it. Neither store is asked to know both.
Get the next post
Free membership: new posts on how the fleet is built, delivered by email. Subscribe free
№ 3793