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:

KindAnswersLifecycle
knowledgewhat is true nowupsert by key, forever
incidentswhat happenedopen → resolved, archived on close
taskswhat is in flightopen → 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:

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:

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:

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

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.