Most memory systems overwrite the past and flatten every question into one search. atomir is atomic on both ends — atomic facts in, atomic sub-questions out — and keeps a timeline when you need to know when it changed.
How it works
Memory that's atomic where it counts: atomic facts when you write, atomic sub-questions when you read — with an opt-in timeline for when things change.
Each message is distilled into atomic facts and reconciled against what's already known — a change updates the existing fact instead of piling up a near-duplicate.
A question is decomposed into the smaller ones it depends on; atomir retrieves for each and composes the answer from what it finds. Dense and keyword search run together, so a fact that hinges on a rare name or title isn't buried under fuzzy matches.
Turn on the timeline layer and a change becomes a dated line on a per-relationship page — so “when did this change?” has something to read instead of an overwrite. One layer, off by default.
Every fact points back to the message it came from, so forgetting an entity removes its facts, any events, and the original text.
Why the timeline layer exists
When a fact store learns something changed, it updates the fact. That's the sensible thing to do, and it quietly deletes your history. No amount of better retrieval brings it back, because retrieval isn't the part that failed — so for “when” questions, atomir keeps the change as an event instead of an overwrite.
mem.add("u", "I work at Beta") mem.add("u", "I moved to Acme") mem.answer("u", "When did I switch jobs?") → fact store: "You work at Acme." # answers a different question → atomir: "In 2025 — Beta before that, since 2023."
Quickstart
Runs with no keys for local testing. The timeline layer is opt-in and experimental.
from atomir.assembly import build_memory_service mem = build_memory_service() mem.add("u1", "I left Beta and joined Acme") mem.answer("u1", "when did I switch jobs?") mem.timeline("u1", branch="works_at")Read the docs →
Runs on your stack
Swap any piece from config. Tested end to end on more than one vendor, deliberately.
Benchmarks — in progress
I have results from my own scenarios and I don't trust them enough to print — it's easy to build an evaluation that agrees with you. I'm running the public benchmarks on the existing harness, with current systems as baselines on the same models, and publishing whatever comes out.
Follow the research →Where it doesn't fit
Questions that hop between people's timelines — “does anyone I know work at Acme?” — want a graph, and atomir isn't one. That's deliberate: the point is getting structured memory without running a graph database.
The JSON store is for development, not scale. The timeline layer is opt-in and marked experimental. With it off, atomir behaves exactly as its atomic-fact core always has.