The most boring line in my team's memory. Also the most expensive
In the last post I wrote that "the memory is the asset, not the agents," and then moved on without showing a single line of it. So here is one line, and here is the bug that made me rewrite the whole protocol.
Image by TheDigitalArtist from Pixabay
Let's start with the line itself. It's about how a filter behaves in our database, MongoDB, and it says roughly this: when you add a new field to a model, every document created before that simply doesn't have it, and filtering by value will never find those documents. Not "not equal to true," not "different from true," no other phrasing either. Zero results. The only way to find them is to ask whether the field exists at all.
It's boring. It also cost us, on two separate occasions, an entire section of the app quietly showing an empty list.
Why it isn't a wiki
The natural reflex is "so write it in the docs." I tried. Documentation is where you write things down to feel good, not so anyone reads them.
What does work is much narrower: at the end of every task, each agent writes itself a lessons entry (not a description of what it did, but what it learned), and the entry loads into it automatically the next time it wakes up. It doesn't go looking for it. It's already there.
A real entry from the repo, exactly as it was saved. Look at the last sentence: it's the reason the file exists. Without it, two months from now someone will research the very same direction, reach the same conclusion, and pay for it again.
The team's memory, by the numbers
| Metric | CountAs of Aug 13, 2026 |
|---|---|
| Journal entries written since July 2 | 256 |
| Distilled topic files | 109 |
| Lines of maintained memory | 1,019 |
| Personal files | 13 |
| Cap per main memory file | ~200 lines |
Counted directly from the repository. "Journal entry" = a single lessons file written at the end of a task; "topic file" = what's left after distilling. The ratio between the two isn't waste: it's the whole job.
The rule that holds all of this together is the budget rule: each agent's main memory file is capped at about 200 lines. Not because of a technical constraint, but because without a ceiling, memory turns into a pile, and a pile is exactly the same nothing as documentation.
That ceiling is also the source of all the trouble. I'll explain why in a moment.
The bug that made me rewrite the whole protocol
A hard budget means memory isn't written by append. It's written by rewriting: lines merge, shrink, move around.
Now add the fact that I run three to five jobs in parallel, each in its own working copy of the code (a git worktree) on its own branch. Two different jobs distilling the same memory file don't produce a merge conflict git knows how to resolve. They produce a conflict of meaning. Both versions are syntactically fine. Both look reasonable. And whoever reconciles them picks, without knowing it, which fact survives.
Except the failure that actually happened was worse than that, because it didn't need a conflict at all. The wrong line about the database wasn't written to one file. It was written on day one, in the same founding commit, to six files at once. And when you fix a fact like that, you fix it in one place.
Two of the agents got the fix on July 25, in two separate pull requests that happened to land the same day. The other four kept waking up with the wrong version for another eighteen days, until the distilling pass cleared it from all of them at once.
The memory didn't just fail to prevent a bug. It brought back to life a bug we had already paid for and buried
And on that same July 25, on that very same file, I also got the second failure, the one that took me ten minutes to recognize: a Pull Request with no checks running on it at all. Not failing: nonexistent. It looks exactly like an outage in the CI service.
When there's a conflict, there's nothing to build. One question on the command line would have exposed it immediately. I was looking somewhere else.
The fix was insultingly dumb
Memory doesn't belong in the agent's isolated copy.
At the end of a task, an agent doesn't edit the memory file. It writes a new file in the journal, with a date and a topic, directly in the main checkout, not in its own working copy. New files can't conflict with each other; that's the entire plan. Every so often a single distilling pass runs, with a single writer, folding the journal into the topic files and bringing them back under budget.
Without planning it, I had separated writes from reads: the journal is append-only, and the topic files are the fast read path. Developers will recognize the pattern. I rediscovered it the hard way, after losing exactly one fact.
And today it's enforced, not requested:
Each of those dates is a rule added after a failure, in exactly that order. None of them was written in advance.
What's actually worth money
What's in the entries isn't knowledge. The agents have knowledge in abundance, and they know most of it better than I do.
What's in there is local knowledge: that our production servers have a name that sounds like a dev environment, and you must not infer anything from the name. That a certain timing metric in our logs doesn't measure what its name says. That a certain background process can, on an unclean shutdown, silence every notification email in the system without anyone noticing.
That's exactly the knowledge a new hire can't bring with them, and a veteran takes with them when they leave. The only difference is that mine is in git, and you can see when it was written and which bug paid for it.
A line of memory is a bug we paid for once. Without memory you pay for it again every week. With memory you can't correct, you pay for it forever
And the last part is the most important of all, and it took me a month to understand. Organizational memory isn't a store you just keep adding to. It's a store you also have to delete from. A stale fact that stays in is more dangerous than a missing one, because an agent won't bother to verify what's written in its own file.