Skip to main content
Knowledge is stored as typed, content-addressed blocks organized into five memory modules. Each module bundles its blocks, a Merkle DAG that pins the exact composition of a version, and the indices needed to query it.

Blocks

A block is a small immutable record with a payload wrapped in an envelope. The envelope is what block_id is computed over, and it has exactly five keys:
Blocks are never mutated. Every operation that looks like a change produces a new block, a new composition, or a new snapshot. See Memory types for the five schemas.

Compositions

A Composition is an immutable set of block identities committed by a single Merkle root. Deriving one returns a new one:
Because the root is computed over sorted leaves, it is a pure function of the set of blocks: two parties that assembled the same blocks in different orders obtain the same root.
A root can be verified but not inverted, so the leaf list is stored alongside it as a composition document (composition.json). Without it a snapshot would identify a version it could not reopen.

Modules

A Module is one memory module at one version: a composition, the store its bytes live in, and its indices.
with_blocks and without_blocks derive new versions. Module exposes no write method at all — extending a brain goes through commit, which is the only write path.

Snapshots

A Snapshot is the state of a brain: one ModuleRef per installed module, plus a parent pointer that forms an auditable chain of versions.
Each ModuleRef carries the module’s root, the composition digest, the block_count, the Merkle layout identifier, and the embedding_model behind a travelling vector index when one ships with it.
A brain may hold a subset of modules. Selective installation is the point of packaging each module separately, so “not installed” is a legitimate state — and therefore an error rather than an empty module when you ask for one you do not have.
The one piece of mutable state a brain has is which snapshot is current:

The store

Blocks live in a BlockStore. Two ship with the SDK: A store must not normalize: bytes that are not canonical do not decode, and bytes that do not hash to the digest they are filed under are refused. A redacted block is tombstoned, never silently missing — a removed block must never look like a corrupted one.