DEV Community

Filippo Pilotta
Filippo Pilotta

Posted on

I built a memory layer for AI assistants that refuses 80% of what you tell it

Every AI assistant now has some kind of memory. ChatGPT remembers that you like short answers, Claude can read a memory file, and there is a growing list of memory APIs you can plug into an agent. After using several of them for my own work I ended up building my own, and the design decision that matters most is one that sounds wrong at first: the memory should say no most of the time.

Why storing everything fails

A memory that accepts every write behaves like a notes app nobody ever cleans. In the first week it is wonderful. By the second month, recall returns four versions of the same fact, three of them stale, and the assistant picks one with full confidence. The failure is not retrieval quality. It is that nothing ever decided whether the fact was worth keeping.

Human memory does this filtering for free. We forget almost everything and keep what was surprising, useful or repeated. Software memory has to be told to do it.

What a quality gate looks like

In Cortex, the service I built, a write is a proposal, not a command. Before anything reaches storage, the proposal is compared with what the memory already knows. If it adds nothing, it is rejected, and the client is told why. On my own instance, which holds more than 11,000 memories written by a few dozen agents, about 80% of proposals are rejected as redundant. Rejected proposals do not count against quota, which matters because it removes any incentive for a client to write less.

The rejection is not exact-match deduplication. Two sentences can be worded differently and still carry the same claim, and the gate is meant to catch that case. It also lets through updates: if a proposal genuinely supersedes an older memory, it is stored with a link to what it replaces, so the history is kept.

Claims instead of blobs

The second decision follows from the first. To judge whether a proposal is new, the memory has to understand what it asserts. So stored content is broken down into typed claims: subject, predicate, object, with a confidence attached. The original text stays, but the claims are what the engine reasons about.

Once you have claims, contradictions become detectable. When a new memory conflicts with an old one, Cortex does not overwrite the old one and does not silently keep both. It records a conflict, with an open state, and surfaces it. You can resolve it, or leave it open as an honest record that two sources disagree. On my instance right now there are twelve open conflicts, and they are exactly the places where the record disagrees with itself, which is what I want to be able to see.

Claims also make citations cheap. Every recall returns the identifiers of the memories it used, so an answer can be audited back to its sources.

Consolidation

Episodic memories pile up even after filtering. A nightly job merges similar episodes into more general memories, tagged as consolidations so the client knows it is reading a summary and not a primary source. The originals are kept and reachable from the summary.

Why MCP

I did not want a memory tied to one assistant. Cortex exposes everything through the Model Context Protocol, so the same memory is available from ChatGPT, from Claude, and from any agent framework that speaks MCP. In practice this is the feature people notice first: a decision taken in one assistant is known by the other one the next morning.

Honest limits

The engine is closed source and only available hosted; the connector and the documentation are public. There is no self-hosted build today. The quality gate is a judgment call and will not suit note-taking use cases where you want everything kept. And a memory that argues with you takes some getting used to.

If you want to try it, there is a 30-day trial without a card at skynetlab-cortex.com. The comparison with Mem0, Zep, Letta and the built-in memories is on the site, written so it can be checked. I'm a solo developer in Italy, so feedback goes straight to the person who wrote the code.

Top comments (0)