SIBYL LABSdocs

How it works

Most memory products store everything on someone else's servers, treat every fact the same way, and quietly forget the important things. Sibyl fixes all three by organizing memory into five tiers, each recalled the way it should be.

The five tiers

Memory is not one bucket. Each tier has a clear intent and its own part of the API.

IntentTierAPI
What you're working on right nowHOT stateset_state(key, body) / get_state(key)
Things the agent knows aboutWARM entitiesset_entity(kind, name, body) / get_entity
What happened, in time orderCOLD journalwrite_event(...) / read_events(...)
Documents you look up by nameREFERENCEset_reference(key, body) / get_reference
Frozen things, kept out of the wayARCHIVEarchive_entity(kind, name)
Search across everythingFTS5search_entities(query)

The SDK in five lines

The same engine that powers the plugin. Everything is local; nothing round-trips to a server.

from sibyl_memory_client import MemoryClient

memory = MemoryClient.local("~/.sibyl-memory/memory.db")

# Remember a fact (entity)
memory.set_entity("project", "atlas", {"status": "active", "owner": "jane"})

# Recall it
print(memory.get_entity("project", "atlas"))

# Record what happened (journal)
memory.write_event(acted=["deployed atlas v1.2 to staging"])

# Search across everything
results = memory.search_entities("atlas")

Single source of truth, enforced

Each entity is unique per (category, name) inside a tenant. That is not a convention the application politely follows; it is a UNIQUE (tenant_id, category, name) constraint at the schema level. Two rows describing the same thing cannot exist. Drift is impossible by construction, which is a large part of why retrieval stays clean as the store grows.

Search without embeddings

Retrieval is SQLite FTS5 full-text search across the entity, state, reference, and journal tiers. No vector index, no embedding model to host, no embedding fees, no similarity drift. The answer your agent needs is found by structure and text, and the whole thing runs on a single box.

Why this matters at scale

In independent beta testing on a 191k-record corpus, retrieval stayed at 100% while reading roughly two rows and ~228 tokens per query, against engines reading 50× the context to answer worse. See Benchmarks.

Forgetting vs deleting

archive_entity(kind, name) is recoverable: it moves the entity into the archive table, out of the active set but still on disk. delete_entity(kind, name) is a permanent hard delete that removes the row outright. Use archive to declutter, delete to truly forget.

Multi-tenant by design

One machine can hold separate, fully isolated memory for separate identities. Every read and write is scoped by tenant_id; one identity never sees another's rows. The same property is what lets Sibyl Labs host the schema as a managed service without the tiers leaking across customers.