Blog · · By Alexander Panasenko · 9 min
Agent memory that keeps its mistakes
An overwriting memory can only ever answer one question: what is true now. The failure that actually costs you is an answer that used to be true — and nothing in it says so.
The fleet forgets, and then argues
Run more than one coding agent and the arithmetic turns against you quickly. Sessions end. Context windows compact. A task starts on one provider and finishes on another. Each new agent arrives fluent and amnesiac, and re-derives what the last one already worked out: which service owns that write path, why the retry budget is set the way it is, what happened the last time the queue backed up at 3am.
The standard answer is a vector store. Embed the documents, retrieve the top-k, stuff it in the prompt. It works — until the facts move. Then you meet the failure mode that matters:
The base confidently returns something that was true in June.
In an overwriting store there is no such thing as a stale answer, because there is no such thing as a previous answer. There is only current. The moment you write the new value, the old one and the fact that it ever changed both stop existing. An agent cannot detect a problem the data model has defined out of existence.
What KYB is
KYB is a git-backed, searchable knowledge base and incident tracker for fleets of AI agents. One HTTP service, one CLI, and a skill wired into each agent's always-loaded instructions — so it gets used without anyone remembering to ask for it.
Three kinds share one flat key space:
| Kind | Answers | Lifecycle |
|---|---|---|
knowledge | what is true now | upsert by key, forever |
incidents | what happened | open → resolved, archived on close |
tasks | what is in flight | open → in_progress / blocked → done |
No projects, no namespaces, no folders to argue about. Tags carry the scope, and the key is the identity.
Git is the canon, not an implementation detail
One markdown file per entry. One commit per change. A commit sha is the version id. The Tantivy search index is a disposable cache — delete it and it rebuilds from git on the next start.
This is not minimalism for its own sake. It buys three concrete things:
- Every superseded version stays. Not in an audit log beside the data — in the data. The history is the same object as the content.
- There is no migration story. The canon is text in a git repository. When
the service is down you can still read it with
catand fix it in an editor. - Backup is
git clone. There is no second system holding state that has to be kept consistent with the first.
When an incident or task closes, its file leaves the working tree — the tree holds only what is live — while the content stays in history and stays searchable. Archive on close, not delete. A resolved incident is still the best answer to "has this bitten us before?".
Search: lexical and vectors, fused
BM25 over the text (title weighted ×2, tags and keys ×1.5) fused by reciprocal rank with vector search over a multilingual e5-small int8 ONNX model running on CPU. A query lands in about 7–9 ms round trip over LAN on a base of several hundred entries.
The vectors are not there to rerank a lexical top-k. They retrieve, independently. That distinction is the whole point: a question phrased in words the entry never uses, or asked in a different language than the entry was written in, has no lexical anchor at all. BM25 cannot rerank a list it never produced.
$ kyb query "why did checkout keep timing out" # no keyword overlap
inc-2026-05-14-checkout-timeouts · resolved · semantic hit ✓
Without the model on disk the service degrades to lexical-only. That is still a working product, just a duller one — and it is a deliberate degradation rather than a crash.
The schema has opinions
An incident report that cannot tell you whether the thing is still happening is a story, not a report. So a report carries fields that make it actionable by a machine:
detection— an executable check and the result that means healthy.affected—{scope, from, to}windows, so a backtest can exclude a poisoned period programmatically instead of someone remembering to.resolution— mandatory to close. A report with no ending teaches nobody.- unfinished
- [ ]items are counted, and a close warns about the loose ends.
And the service refuses to swallow secrets. A body, ref, resolution or detection that looks like a token, an AWS key id or private key material is rejected at write time, with a message telling you to store a pointer instead. Refs point at where the secret lives; they are not the place it lives.
Why versioning with provenance beats overwriting
An overwriting store answers one question: what do we believe now. A versioned one can, in principle, answer two more:
- What did we believe then? — the question you ask when reconstructing why an agent made the call it made last Tuesday.
- Where did this change? — the question you ask when an assumption you have been carrying for a month quietly stopped being true.
For a human wiki, those are a nice-to-have; a person usually remembers that something changed even when the page doesn't say so. For a fleet of agents it is structural, because the agent acting on a fact is almost never the one that wrote it. It has no memory of the change, no colleague to ask, and no instinct that the page looks different from last time. Everything it can know has to be in the retrieval result.
So the design rule is: never lose the shape of a belief changing. Store the new value, keep the old one addressable, and keep the commit that moved between them.
What it does not do yet
Being straight about the gap. Half of the temporal query layer exists. The other half does not, and the roadmap is not written in the present tense here.
What works. Three questions, three answers. --as-of gives the base as
it stood at a moment — one row per key, the value that was current then, not today's.
--changed-between gives what moved inside a window, which is the question an agent
taking over from another actually has. /diff says what moved inside one
entry, field by field and line by line, instead of leaving you to fetch two versions and
compare them by hand.
What does not. All three are lexical. The vector index holds one vector per key, for the head version, so a question about a past version has nothing to match against semantically — ask it in words the old entry did not use and the search will not find it. Extending the vectors to every version is small and is the next thing.
One more honest limit: git stamps whole seconds, so two versions written inside the same
second cannot be told apart by --as-of, and the later one wins.
The skill is the delivery mechanism
A knowledge base an agent never opens is a knowledge base that does not exist. So the
installer does not just drop a CLI on PATH — it writes a pointer into each agent's
always-loaded global instructions, between markers so re-running updates in place instead of
appending copies.
$ kyb query "queue retention" --tag infra
$ kyb add --key queue-retention --title "..." --tags queue,infra <<< "body"
$ kyb incident --key inc-2026-05-14-checkout-timeouts --service svc-checkout --severity high
$ kyb resolve inc-2026-05-14-checkout-timeouts <<< "what fixed it"
$ kyb tasks --status blocked --priority critical
That is the part that turns a database into a habit: the agent finds the skill in its own instructions, on every machine, without being told.
Where it is not a fit
- You need auth. There is none, deliberately — the service binds to localhost or one private interface and trusts the network boundary. If that is not your threat model, this is the wrong tool.
- You have millions of documents. The vector index lives in memory and is rebuilt from git on start. It is sized for hundreds to thousands of entries about your own systems, not a document warehouse.
- You want a wiki for people. The write path is a CLI and an HTTP API shaped for agents. A human can use it, but nobody will enjoy composing prose through it.
Try it
# Docker — the image already contains the embedding model
docker compose up -d
# then wire the skill into every agent on the machine
bash skills/install.sh
Source, issues and the full API surface: github.com/alex09x/kyb. MIT. It is early and the repository is honest about that — including the part above about what the query layer still cannot do.