How memory works
Sibyl Memory Plugin splits everything an agent might want to remember into five clear kinds. Each kind is stored differently and recalled differently. This is the single biggest reason our memory beats "dump everything in one bucket" systems.
The intuition: a desk, a notebook, and a filing cabinet
Imagine how you'd organize information at a desk, sensibly:
- The sticky note on your monitor. What you're focused on right now. You glance at it constantly.
- Your address book. Names, projects, and decisions you reference by name. One canonical entry per thing.
- Your daily journal. What happened today, in order. You flip through it when you need to remember when.
- Your reference shelf. Runbooks, recipes, rules of thumb. You look them up by topic.
- The cardboard box in the closet. Stuff you're not using but might need someday.
Now imagine someone took all of that and threw it in a blender, then asked you to find anything in it by "vibes-based similarity." That's what most agent-memory systems do today. Sibyl Memory Plugin keeps the five categories separate and asks the agent to retrieve each one the way it would actually want to.
The five kinds, in detail
1. State: What you're working on right now
Short, structured documents the agent loads on every turn. Examples: "my current priorities are X, Y, Z," "the user is in the middle of debugging the deployment script," "voice rules for tonight's broadcast."
State is small (a handful of key-value documents) and changes often. The agent reads it at the top of every interaction.
Stored in: state_documents · API call: memory.set_state(key, body) / memory.get_state(key)
2. Entities: The things the agent knows about
People, projects, decisions, products. One canonical record per thing. Examples: "project: atlas, status: active, owner: jane," "person: jane, role: ops lead, last interaction: yesterday," "decision: error budget threshold = 2%."
When the agent learns something new about an entity, it updates the existing record rather than creating a new one. This keeps the agent's worldview clean: one Atlas, not seventeen variations.
Stored in: entities · API call: memory.set_entity(kind, name, body) / memory.get_entity(kind, name)
3. Journal: What happened, in order
Append-only log of every action, decision, and outcome. Examples: "2026-05-15 10:23 deployed atlas v1.2 to staging," "2026-05-14 16:42 pair-debugged with jane on the queue worker," "2026-05-13 09:00 daily standup."
The journal is the only kind of memory that's strictly time-ordered. You read it when you need to remember "yesterday," "last week," "this morning." You don't update journal entries. Once they're written, they're history.
Stored in: journal_events · API call: memory.write_event(evaluated, acted, forward, extra) / memory.read_events(limit, since, until)
4. Reference: Things you look up by name
Static lookup material: runbooks, rules, conventions, voice guides. Examples: "rollback-runbook," "voice-rules," "on-call-escalation."
Reference docs change occasionally. The agent looks them up by their name, not by similarity to a question. When the agent asks "do I have a rollback runbook," it gets either the document or nothing. No fuzzy match.
Stored in: reference_documents · API call: memory.set_reference(key, body) / memory.get_reference(key)
5. Archive: Frozen things, kept but out of the way
Entities that are no longer active but might be useful to look up later. Examples: "the prototype we built but abandoned in March," "the partner who used to be on the roster but isn't now."
Archiving an entity moves it out of the day-to-day worldview but keeps it findable. The agent doesn't accidentally confuse archived projects with active ones, and the working set stays clean.
Stored in: archived_entities · API call: memory.archive_entity(kind, name, reason)
How the agent uses them together
When you say "how's Atlas going," the agent doesn't just guess. It does something like:
- Look up entity
project/atlas→ finds the canonical record (status: active, owner: jane). - Pull the last few journal entries mentioning Atlas → recent deploys, what changed, who shipped it.
- Check state → is Atlas in the current priorities?
- Look up any reference about Atlas if it exists (a project runbook, a launch checklist).
- Stitch the answer together with sources.
A vector-only system would dump all of that into one bucket and try to retrieve "things similar to 'how's Atlas going'". Which gets you a confused soup. Splitting by kind lets the agent retrieve each one with the right query.
Search across kinds
For times when you don't know what kind of thing you're looking for, Sibyl Memory Plugin has a full-text search across entities. Search runs locally and finds anywhere the text appears. Names, kinds, bodies. It's the fallback for when structured recall isn't enough.
API call: memory.search_entities(query)
Multiple identities on one machine
The same Sibyl Memory Plugin install can hold separate memory for different identities. The agent might keep one set of memory for your day job, another for your side project, a third for a team channel. Each is isolated. Facts in one don't leak into another.
This is the tenant idea. Most users only need one tenant; advanced users (and team plans) use several. See the API reference (coming soon) for how to set tenants explicitly.
What this design buys you
- Faster recall. The agent asks for what it needs by name, not by similarity. Most lookups are sub-millisecond on local hardware.
- Fewer hallucinations. The agent isn't guessing which fact is current. There's one canonical record per entity. Updates replace; they don't add.
- Smaller storage footprint. Structured rows compress about 50× better than embedding vectors. Your whole memory fits in a few megabytes for months of real use.
- Better benchmarks. On LongMemEval Oracle. The hardest public test of long-term agent recall. This design scores #2 globally when paired with Claude Opus 4.6. Full report →
Under the hood (for the curious)
The local database is SQLite with full-text search (FTS5) on top of the entity bodies. There are ten tables, one
per kind of memory plus relationships, audit, and bookkeeping. The whole schema applies idempotently on first
run and migrates automatically between versions. You can open ~/.sibyl-memory/memory.db in any
SQLite browser to inspect it directly. The full schema lives in the
package on PyPI.