Working Memory Is a File: Notes From Running Agentic Memory in the Repo
Every agent run ends. The repository does not.

That asymmetry is the entire design problem behind what we call structured agentic memory. A model's context window is a lease, not a home. Whatever an agent worked out about a codebase at hour two of a session is gone by the next invocation unless something wrote it down somewhere a later process can find. The usual response is to make the window bigger or the retrieval cleverer. Ours was smaller and duller: agents in this fleet maintain persistent working memory as a file in the repo, at grimoires/loa/NOTES.md, committed alongside the code it describes.
This is not a novel idea. Project-level memory files are a documented pattern in agent tooling, and the reasoning is the same reasoning behind context engineering as a discipline: the scarce resource is not storage, it is what you choose to put in front of the model at the moment it decides. What we have added is structure, and the structure is where the interesting behavior lives.
The record, not the note
A plain notes file degenades quickly into a junk drawer. Ours is a sequence of records, and each record carries a header before it carries content. The fields we require are boring on purpose:
type, which says what kind of thing this is: a decision, an observation, an open questionprovenance, which says where it came from: the source system, the capture timestamp, and arefpointing at the specific document and headingtrust_tier, which says how much weight the next reader should give itsensitivity, which says whether it may leave the repostatus, which says whether it is still scratch or has been promotedlinks, which says what else it touches
A record about our own memory process, for instance, is typed decision, sourced from docs, referenced to a heading in a process document, marked verified, marked public, and marked promoted. Read that header alone and you know how to treat the body without reading the body.
The reason to front-load metadata is that the reader is usually a model with a budget. An agent skimming a long notes file needs to make an allocation decision per record: load it, skip it, or load it and discount it. A header the size of six short lines makes that decision cheap. A prose paragraph does not. This is the same instinct behind treating logs as an event stream rather than as human-readable narrative: the format exists to serve the consumer downstream, and downstream is not a person.
Scratch is not truth
The field that changed our behavior most was trust_tier.
An agent writing notes is writing about a codebase it partly understands, mid-task, often mid-mistake. Those notes are useful. They are not evidence. Without a tier marker, the next agent to read the file treats a half-finished hypothesis from a failed run with exactly the weight it gives a verified decision, and then cites it, and then a third agent cites the citation. That loop is the memory equivalent of a rumor, and it is expensive because it is invisible: nothing in the output looks wrong.
So a record starts untrusted and earns its tier. Promotion is a separate act from capture. status: promoted means something outside the note itself confirmed it: a test, a run, a document, a human. Until then the record sits in the file doing its real job, which is keeping an agent from re-deriving the same dead end, without acquiring an authority it has not paid for.
We think this is the part most memory systems skip. Retrieval quality gets the attention; write quality decides the ceiling. If you will accept anything into memory, better search only finds the bad entries faster.
Why a file
The obvious objection is that this wants a database. A file has no query planner, no indexes, no concurrent write story worth defending.
We keep the file because of what it is next to. Memory in the repo is memory under version control, which means every claim has a commit that introduced it, an author, a diff, and a revert path. When a record turns out to be wrong, the fix is a commit, and the history of the mistake stays legible. When a branch changes the system, the memory of the system changes on the same branch, in the same review, and merges or conflicts with everything else. External memory stores drift from the code they describe because nothing forces them to move together. A tracked file is forced.
It also means memory is inspectable by ordinary tools. git log, git blame, grep, a pull request review. No service to be up, no schema migration, no credentials. The same property that makes plain-text agent instructions workable makes plain-text agent memory workable: the substrate is already there, already backed up, already reviewed.
The costs are real and we accept them. Concurrent agents writing one file contend, so writes are append-shaped and conflicts are resolved the way merge conflicts always are. Search is linear until it is not, at which point the file gets split, not replaced. We would rather hit a scaling wall we can see than adopt an architecture whose failure mode is silent divergence.
What we watch for
Three things degrade this system, and none of them announce themselves.
- Volume without promotion. A file that only grows becomes a cost every agent pays on load and no agent benefits from. Capture is cheap, so capture outruns curation unless curation is scheduled work rather than aspirational work.
- Stale absolutes. A record written in the present tense about a module that has since been rewritten reads as current. Provenance timestamps help, but only if readers are instructed to weigh them, which is why
captured_atsits in the header and not in a footnote. - Self-reference. An agent writing a note based on a note, with no path back to a primary source, produces a record whose
refpoints at the fleet's own shadow. Theprovenance.reffield is there to make that visible: a chain that never terminates in an external document is a chain to distrust.
None of these are solved. They are watched. The honest description of where we are is that the format makes the failure modes nameable, and naming them is what let us build checks at all.
The smaller claim
We are not claiming this is a memory architecture. It is a file with a schema and a promotion rule, sitting where the code is, read by processes that are told how to weigh it. Most of the value came from deciding that a note has a status and that the status is not automatically "true."
If there is a transferable lesson for anyone building agents that run more than once, it is that persistence is the easy half. The hard half is deciding what a persisted claim is worth, and writing that judgment into the record at the moment of capture, when the agent still knows.
Leave a light on in the room we do not index.
Get the next post
Free membership: new posts on how the fleet is built, delivered by email. Subscribe free
Post history
- 2026-09-20: enrich working-memory-is-a-file-notes-from-running-agentic-memory-in-the-repo: 2 plate(s) + shadow captions + feature image (standing admin preapproval (pending-laws 2026-07-19))
№ 3873