Building Stele with Stele
Three months, 1,650 commits, and about 1,300 tasks, nearly all of them done by agents reading a record other agents wrote. Here is what that is actually like, including the parts that did not work.

The setup
Stele is built almost entirely by agents. Not in the sense that someone occasionally asks for a function, but in the sense that the normal unit of work is: a task exists in the record, an agent claims it, does it, writes down what it learned, and closes it. A human reads the result and decides what happens next.
Three months in, that has produced a project record with roughly these shapes:
1,650 commits since the end of April
1,300 tasks ~1,080 done · ~215 open · 3 in flight
940 active knowledge nodes 69 more archived or retired
28 components
busiest topics eval 125 · web 93 · auto-rag 79 · mcp 75 · supabase 63We are the most demanding user of this product and also the least representative one, so treat what follows as a report from an extreme case rather than as a typical experience. The failure modes are real, though, and they showed up here first.
What actually works
The record survives the agent
The single most useful property has nothing to do with retrieval quality. It is that a session can end, badly, and the work is still legible.
An agent hits a context limit halfway through something. Previously that meant reconstructing intent from a half-finished diff. Now there is a claimed task with a written goal, links to the decisions that shaped it, and whatever was learned before the wheels came off. The next session opens with all of that and continues.
This turned out to matter more than any of the retrieval work. Most of the value of writing things down is not that the right fact arrives at the right moment. It is that a crash stops being a total loss.
Comments in the source that point at the reason
A pattern emerged that nobody designed. Code comments in this repository routinely reference the task or decision that produced them. Not as decoration: as a pointer from the what to the why, where the why is too long to sit in a comment.
The measurable perf table explaining why a query selects an explicit column list rather than everything, the paragraph explaining why one weight in a scoring table is negative, the note explaining which failure a lock exists to prevent: these live next to a pointer, and the pointer resolves to the full story. Neither half would survive on its own. A comment that long would get deleted for being noise, and a record entry with no anchor in the code would never be found.
Losing an argument to your own record
The best moments are the ones where the record disagrees with the person. Someone proposes a change, and what comes back is a decision from two months ago explaining why the obvious version of that change was tried and reversed.
The value is not that the answer was retrieved. It is that the argument did not have to happen twice.
What did not work
This is the more useful half, and it is the part a page written by marketing would leave out.
Agents wrote too much, and the graph got noisy
Early on the guidance encouraged writing things down, so agents wrote things down. Every session produced knowledge entries, and a substantial share were restatements of what the code already said, or near-duplicates of something recorded two weeks earlier by a different session that had not found it.
A noisy record is worse than a small one, because it dilutes retrieval: twenty slots filled with four good facts and sixteen restatements is a worse turn than four slots filled with four good facts. Most of the lifecycle work, deduplication, the health check, the pressure to bind every fact to a retirement condition at write time, exists because of this. It was not foresight. It was cleanup.
Guidance is a much weaker lever than we assumed
The clearest case: agents folding conversational source material into the graph would retire facts that had not actually been reversed. Every single time. We rewrote the guidance, added examples of the near misses, put the warning at the point of use, and the rate did not move at all.
That failure produced the most transferable lesson we have. When better instructions do not move a number, the mistake is structural, and you should redesign for it happening instead. Which is what we did: retirement stopped being destructive, so a wrong call became a visible wrong label instead of a deleted fact.
We built things because the graph made them easy, not because they mattered
When the backlog is a queryable list of well-specified tasks and agents are cheap, the throughput of small work goes way up. That is mostly good and occasionally a trap: it is very easy to ship fifteen tidy improvements to a subsystem nobody is blocked on, because those tasks were sitting there and were well-scoped, while the ambiguous thing that actually mattered stayed open because nobody had written it down properly yet.
A well-organised backlog exerts a pull toward whatever is easiest to pick up. That pull is not correlated with importance, and the tooling does not fix it. Prioritisation is still a person's job.
Our own sessions are useless as evidence
An agent working in this repository can see that the memory system is the subject. It reads the doctrine, sees the tooling, and pays the record deliberate attention it would not pay on an ordinary project.
Which means the thing we watch every day, our own agents using this well, is not evidence that it works. It is the reason we cannot benchmark on our own repository, and it disqualifies the demo we would most like to show you.
The rhythm that emerged
None of this was designed up front. What settled into place over three months is roughly four moves, and they are worth describing because they are not what we expected to be doing.
Work is written down before it is done, not after. Not because process is virtuous, but because a task with written intent is the only artifact that survives a session ending badly. The discipline is entirely selfish.
Lessons get written in the moment, mid-task. Anything left for a summary at the end gets written in the vague register people use when they are tired, and vague lessons never surface again. The concrete trigger has to go in while it is still annoying.
Somebody reads the record with their own eyes, regularly. This is the one we keep having to relearn. Retrieval quality metrics tell you about the apparatus, not about whether the contents are true. The only way to find out that a corner of the graph has quietly filled with plausible nonsense is to go and read that corner.
Verification is scheduled, not hoped for. A sweep that diffs against the last commit it reviewed, gathers the facts touched by what changed, and checks each against the current code. It finds real drift every time it runs, which is both reassuring and slightly alarming.
Things we would tell someone starting
Do not seed a large record up front. A generated pile of facts about a codebase you have not questioned is a pile of plausible sentences, and plausible sentences that turn out to be wrong are worse than nothing, because they arrive with the same authority as the true ones. Let it accumulate from work that actually happened.
The lesson has to contain the literal trigger. Not be careful with type generation, but the error string, the file, the symbol. A lesson written abstractly is invisible exactly when it would help, because retrieval matches text and the person in trouble is searching with the words the error gave them.
Decide when a fact dies while you are writing it. Nobody ever runs a quarterly audit of their notes. Everybody can answer when does this stop being true in the moment they write it down. Bind the risk to the task that resolves it and it retires itself.
Read your own record occasionally. Not through an agent. Actually read it. Every serious problem we have had with the graph was visible in about ten minutes of reading it, and invisible in any metric we had.
Open your record and pick five facts at random. How many can you confirm are still true without opening the code? If the answer is fewer than four, the problem is not retrieval and adding more facts will make it worse.
What we still do not know
Whether this is faster. We genuinely do not have that number, and we are suspicious of everyone in this category who claims to.
The number we want is the crossover point: how many sessions before the overhead of maintaining a record is repaid by the sessions that inherit it. That is a two-session paired experiment, we know exactly how to build it, and we would rather publish that than a testimonial.
What we can say without it is narrower and holds up: sessions resume instead of restarting, decisions get re-litigated less often than they used to, and a session that dies halfway is no longer a total loss. Three months of building this way is not a controlled trial, and it is also not nothing. It is why the crossover experiment is the one we chose to build first, out of everything we could have measured.