The problem, stated precisely
Every capable model forgets you the moment the window closes. That is not a flaw anyone is going to fix for you, because context is priced per token and your history is not. The fix is architectural and it sits outside the model: a store you own, a way to search it that actually finds things, and a discipline about what goes in.
Retrieval-augmented generation solved the first half of this years ago and is widely misunderstood as the whole answer. It is not. A memory that only grows is a memory that gets worse with use, because precision falls as the pile rises. The hard part was never storage or even search. It is deciding what deserves to be remembered, and removing what no longer does.
This method is the architecture running behind this laboratory's own systems. At the time of writing that store holds over seventeen thousand memories, answers in under a hundred milliseconds, and is consulted by four different agents on every substantive question. Everything below is what it actually does, including the parts that went wrong first.
What you will have built A single-file database with hybrid keyword and semantic search, an extraction gate that keeps noise out, automatic decay and consolidation, and a tool interface any agent can call. It runs on your machine, costs nothing to operate, and survives you changing model provider.
The code is in the kit, and it runs
memory/memory.pyis this method as about three hundred lines of standard library Python: the schema, the triggers, hybrid search, fusion, the write gate, duplicate merging and decay, with seventeen tests.python3 memory.py --demoneeds nothing installed. Read the method here; take the code there.
Who this is for You can install software and read a schema. You do not need machine-learning background; nothing here trains anything. Budget a weekend for steps one through six, which is the point where it becomes useful, and a second pass later for the rest.
1. Decide what the memory is for
Do this before you write a line, because it determines the schema and the discipline, and retrofitting either is painful.
A memory serves exactly three purposes. It lets the agent recall something you said once. It stops you repeating yourself. And it lets the system get better over time by remembering what worked. Write down which of the three matters most to you; when you later have to decide whether something is worth storing, that sentence is the test.
The failure mode to name now: treating the store as a diary. A session log has no value in a week, but it will outrank a genuinely useful fact in every search you run for the rest of the year. More on this at step seven, which is the step that actually determines whether this works.
2. Choose the store — one file, no server
Use SQLite. It is a single file, needs no daemon, handles millions of rows, and is on every machine you own. A memory system you have to operate is one you will abandon.
Resist the vector database. A dedicated vector store is the right answer at tens of millions of vectors and the wrong answer at every scale you will personally reach, because it adds a service, a network hop and a second source of truth for data that belongs beside your text.
# the whole installation
python3 -c "import sqlite3; print(sqlite3.sqlite_version)"
If that prints 3.35 or above you have everything the next four steps need.
3. The schema — five columns that matter
Keep the core table narrow. Everything here earns its place.
CREATE TABLE memory (
id INTEGER PRIMARY KEY,
content TEXT NOT NULL, -- one fact, stated so it reads true alone
category TEXT NOT NULL, -- fact | decision | skill | reference
tier TEXT NOT NULL, -- semantic | procedural | episodic
importance REAL NOT NULL, -- 0..1, earned and decaying, never reflexive
tags TEXT, -- json array; project scope lives here
source TEXT, -- which agent or person wrote it
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
access_count INTEGER DEFAULT 0 -- step 8 needs this
);
One fact per row. The discipline that makes retrieval work is not in the search code, it is here. A row holding three facts matches weakly on all three and is returned confidently for none.
importance must be earned. The temptation is to write 0.9 on everything you store, and the moment you do the field stops carrying information. Reserve the top of the range for things that would change a decision.
tags carries scope. If you work across several projects, a project tag is what stops one project's patterns bleeding into another's answers. This sounds fussy until the first time an agent confidently applies the wrong codebase's conventions to your work.
A gotcha that will cost you a day
Many 2026 open models ship as hybrid reasoning checkpoints with thinking enabled by default. Handed a long system prompt, such a model can spend its entire output budget reasoning and return an empty response, with a status that merely says it stopped because it ran out of room.
If your extraction step suddenly returns nothing, this is why. Disable thinking explicitly in the request, and assert that the reasoning field came back empty rather than trusting that your flag was honoured — some client libraries drop that parameter silently.
Extraction does not need a reasoning model. It needs a fast, obedient one.