Matrix logo

Cortex: Developer Reference

Cortex is Matrix's per-actor persistent memory store — a Pebble-backed KV database with a typed taxonomy, salience-ranked queries, async embeddings, Merkle snapshots, and a full replay invariant.

Cortex is Matrix's per-actor persistent memory store: a Pebble-backed key-value database with a typed memory taxonomy, a salience-ranked query engine, an async embedding pipeline, a Merkle-authenticated snapshot system, and a full replay invariant. Every durable thing an agent knows — facts, preferences, goals, constraints, past events, procedural patterns — lives here.

This documentation is written for people working on cortex itself — extending the memory types, tuning the salience formula, adding index layers, or understanding how the replay and snapshot machinery works.

Contents

DocumentWhat it covers
Memory TaxonomyThe 9 typed memory kinds, Head, Version, Forms, Tombstone
Store & JournalPer-actor Pebble DB, key encoding, atomic write batches, journal
Write APIWrite, Update, Tombstone, UpdateHead — mutations and their journal footprint
Find QueryThe typed query engine — predicates, planner, ordering, graph traversal
Context BundleThe three-tier cold-start composer — Pinned, Frame-relevant, Outcomes
Embedder & VectorAsync embedding worker, pure-Go HNSW, Find Near / Find NearURI
Edges & GraphTyped edges, AddEdge, RemoveEdge, bounded BFS
Snapshot & ProofsJournal MMR, per-namespace SMTs, OverallRoot, multi-proofs
SalienceThe 5-factor formula, cold weights, EMA per-actor weight learning
Attest & CompactIntent attestation, salience feedback, budget-aware compaction
ScopeSub-agent CortexScope — Merkle-authenticated read/write gating
ReplayDrop-and-rebuild — the derivability invariant and Cortex.Rebuild

Repository layout

cortex/
├── go.mod
├── cortex.go               # top-level facade: Write / Update / Tombstone / Find / Context / Snapshot
├── attest.go               # Attest — intent-outcome salience feedback + EMA weight update
├── compact.go              # Compact — budget-aware context compaction + checkpoint records
├── context.go              # Context — three-tier cold-start bundle composer
├── edges.go                # AddEdge / RemoveEdge / GetEdge / IterEdgesOut / IterEdgesIn
├── embedder.go             # StartEmbedder / StopEmbedder / DrainEmbedder + HNSW worker
├── goal_state.go           # GoalRuntimeState sidecar (ambient scheduler bookkeeping)
├── ratelimit.go            # Phase 14 token-bucket DoS guards (scope violations + attests)
├── rebuild.go              # Cortex.Rebuild facade → replay.Rebuild
├── scope_enforce.go        # VerifyScope / enforceRead / enforceWrite / logScopeViolation
├── update_head.go          # UpdateHead — Head-only mutations without a Data version bump
├── keys/
│   └── keys.go             # all Pebble key constructors + namespace prefixes
├── journal/
│   └── journal.go          # Entry, Kind, payload types, canonical CBOR, leaf hash
├── memory/
│   ├── types.go            # Type, Visibility, Head, Version, Forms, Tombstone, SourceKind
│   ├── data.go             # IdentityData, FactData, …, PatternData (9 schemas)
│   ├── codec.go            # canonical CBOR encode/decode + HashVersion
│   ├── validate.go         # write-time schema validation
│   ├── verb.go             # Verb (10 D7 verbs), ObjKind, FrameRef
│   └── edge.go             # EdgeType, EdgeRecord
├── store/
│   ├── store.go            # Open, Get, PrefixIter, JournalHook, NextSeq
│   └── writebatch.go       # BeginWrite → AppendJournal → Commit / Abort
├── salience/
│   └── salience.go         # Score, ColdScore, ColdScoreWith, Weights, EMA helpers
├── forms/
│   ├── forms.go            # Render (short + medium), RenderFull (on-demand)
│   └── truncate.go         # TruncateToTokens (UTF-8-safe, bytes/4 heuristic)
├── query/
│   ├── predicate.go        # Predicate AST: Eq Ne Gt Gte Lt Lte In HasTag Matches And Or Not
│   ├── eval.go             # field resolver + scalar comparator
│   ├── find.go             # Run: planner → candidate scan → predicate eval → sort → render
│   └── graph.go            # BFS traversal for Query.From / Query.Follow
├── embed/
│   ├── embed.go            # Embedder interface + HashEmbedder (deterministic sha256 stub)
│   └── api_embedder.go     # HTTP-backed API embedder (nomic-embed-text-v1.5)
├── vector/
│   └── vector.go           # NewIndex, Add, Search, Save, Load, MapStore, VectorStore
├── snapshot/
│   ├── snapshot.go         # State, Snapshot(), CurrentRoots(), FindSnapshotByRoot()
│   ├── mmr.go              # journal MMR append + root computation
│   ├── smt.go              # per-namespace sparse Merkle tree (memories + edges)
│   └── multiproof.go       # MultiProof, BuildMultiProof, VerifyAgainstManifest
├── scope/
│   ├── scope.go            # Scope struct, Selector, Sign, Encode, Allows
│   ├── verify.go           # Verify, KeyResolver, StaticKeyResolver
│   ├── match.go            # Allows per-Head matching logic
│   └── errors.go           # ErrViolation, ErrNotWritable, ErrScopeExpired, …
├── replay/
│   ├── replay.go           # Rebuild, Result, Options, VerifyPreservesRoot
│   └── drop.go             # DropDerived, CountDerived
└── cmd/cortex-shell/       # smoke-test CLI: write/resolve/update/tombstone/find/snapshot

The one-sentence contract

Cortex is the ground truth for all durable agent memory. The context window is a cache; cortex is the disk. Every write is atomically journaled; the journal feeds a Merkle accumulator; snapshots seal the state root. Drop the derived indexes — replay the journal — roots match. That is the invariant everything else depends on.

Key locked decisions

These decisions are frozen. Don't re-litigate them without a documented protocol-level change.

IDDecision
D4Cortex holds no key material. Signing lives in the agent runtime or tools layer.
D11Compiler seed = sha256(intent.id || actor || OverallRoot || mtx_digest || model_digest). Same inputs → same output.
D13#latest is forbidden at ParseURI time. All versions must be pinned before sign-off.
D17One Pebble DB per actor. All namespaces are key prefixes inside that DB — the only way to satisfy §11.1 batch atomicity across journal + head + version + indexes.
D7Verb vocabulary is closed at exactly 10 values: find acquire build modify deliver analyze negotiate schedule monitor delegate. ObjKind is similarly closed. Extending either requires a journaled migration.
§8.2Pinned memories carry a salience floor of 0.7. Tombstoned memories rank to zero and are filtered upstream.
§11.1Every store mutation — Write, Update, Tombstone, AddEdge, UpdateHead, Compact, Attest — commits journal + primary keys + index keys in a single atomic Pebble batch. A write without a journal entry fails with ErrBatchNoJournal.
Phase 10 Q7Sub-agent UpdateHead requires Scope.Writable=true. Default deny.