Josie
Josie's Blog · Engineering
From the field · Part two

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.

IR
Israel RothCTO and co-founder, Josie · August 14, 2026
A 3D model of a human brain in shades of gray, on a light background
I know: a picture of a brain, in a post about AI. I put it here on purpose, because the point of this post is the exact opposite: what turned my agents into a team is nothing like a brain. It's boring text files in git.

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.

The second time it happened on both web and mobile, because the same wrong assumption had been written twice. Nothing like consistency.

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.

.claude/agent-memory/discovery-engineer/journal/2026-08-13-music-service-taste-import-closed.md
# Reading user listening habits from Spotify / Apple Music is closed off (2026-08-13) Investigated for an onboarding initiative: connect Spotify or Apple Music at signup, pull listening history, seed a taste profile. Don't — three independent blockers. Recording the findings so this isn't re-researched from scratch.

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.

01Task endsThe agent wraps up
02Lessons entryWhat I learned, not what I did
03New fileIn the journal, in the main checkout
04DistillOne pass, one writer
05TrimBack under budget
06LoadAutomatically, on every wake-up

The team's memory, by the numbers

MetricCountAs of Aug 13, 2026
Journal entries written since July 2256
Distilled topic files109
Lines of maintained memory1,019
Personal files13
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.

The same wrong line · six memory files · when each one was fixed
Architect
Platform
Engagement
Events
Growth
Identity
Jul 2Written Jul 25Fixed for two Aug 12Distilled
Wrong version active and loading Fixed

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.

July 25 · two writers · one memory file
mainAnother session, merged directly
PR #183Its own branch
✕ Conflict
Same file, same day. GitHub can't compute the merge, so it doesn't create any runs at all: 0 checks, and not a single red one to go by.

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 code in that pull request was perfectly clean. What blocked it was the agents' memory. Since then, that's the first question we ask when there are no checks: not "what broke," but "is there anything to build at all."

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:

Jul 2, 2026 The team is set up. Memory is written straight to the files, from anywhere
Jul 25, 2026 The protocol breaks under parallelism and is rewritten: journal only, in the main checkout
Jul 28, 2026 Automatic block on writing memory from a side copy
Aug 13, 2026 An outbox for isolated sessions, and distilling that kicks off automatically at a threshold

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.

Which is, if anything, the most accurate parallel I've found between an agent's memory file and a veteran employee: people tend to trust both of them a little too much. The only difference is that one of them you can open up and delete a line from.
The quantitative data in this post was measured directly from Josie's repository on August 13, 2026 and is reproducible. The previous post in the series: I have 13 engineers on my team. None of them is human.