Memory System
Package matrix/neo/internal/memory is Neo's memory controller, the pager in the frozen spec's RAM/disk/pager model. Pins, page-faults, writes back, and manages procedural patterns with conflict-aware linking.
Package matrix/neo/internal/memory is Neo's memory controller, the "pager" in the frozen spec's RAM/disk/pager model. The context window is RAM (scarce), cortex is disk (durable ground truth), and this package is the controller that pins, page-faults, writes back, and compacts.
Source files: neo/internal/memory/pager.go, neo/internal/memory/embedder.go, neo/internal/memory/pattern.go, neo/internal/memory/writeback.go.
Design decisions
Cortex is ground truth; the window is a cache. All durable learnings live in cortex. The window is a disposable working set that gets re-faulted every turn. Summaries are re-derivable, not ground truth.
Two retrieval lanes. Semantic (HNSW vector search via embedder) + salience-ranked (type-filtered). The embedding worker is async, so a memory written seconds ago is invisible to the vector index. Without the salience lane, a "remember this" then "what do you know?" round trip inside one session would come back empty.
Anti-overfit guard for procedural patterns. A candidate pattern must reach MinPatternSuccesses (default 3) before it is injected into the window. This prevents one-off successes from being treated as proven recipes.
Verbatim trust contract. High-entropy tokens (addresses, tx hashes, IDs, file paths) are copied verbatim in compaction and recall. A paraphrased 0x... is a corrupted memory (i3).
Conflict-aware fact linking. When RememberFactRelated is called with a classifier, topically-similar facts are classified as supersedes, contradicts, or relates, and the appropriate cortex edge is linked. Contradiction edges surface as advisory notes on retrieved snippets.
Pager
type Pager struct {
cfg config.Config
cortex *cortex.Cortex
store *store.Store
embedder embed.Embedder
hasEmbedder bool
mu sync.RWMutex
activeGoal string
}
Opened per-actor under the shared cortex root:
pager, err := memory.Open(cfg)
A failed embedder is non-fatal; retrieval falls back to salience ranking. The embedding worker lazily re-embeds memories whose recorded model differs from the active one, so upgrading from hash to API vectors migrates the brain automatically.
Pinned block
The pinned block is injected every turn. It contains:
- Identity - agent name + DID from cortex identity record
- Inviolable rules - the 6 baked-invariants from the frozen spec
- Hard constraints - user/operator-declared hard-strength constraints from cortex
- User profile - durable facts about the user (name, role, preferences), deduped and bounded to 12 entries
- Active goal - the current conversation's task
func (p *Pager) Pinned(ctx context.Context, goal string) string
Bounded by PinnedBudgetTokens (default 2000). The caller passes the per-conversation goal so many conversations can share one cortex store safely.
Page-fault retrieval
func (p *Pager) Retrieve(ctx context.Context, queryText string) ([]Snippet, error)
Returns top-K relevant cortex records, merged from both lanes:
- Semantic lane -
cortex.FindwithNear=queryText(HNSW vector search), when embedder is running - Salience lane -
cortex.Findwith type filter: Fact, Event, Pattern, Preference, Goal
Deduplicated by URI. Bounded by RetrievalTopK (default 8) and RetrievalBudgetTokens (default 6000).
Snippet
type Snippet struct {
Text string // rendered text for injection
URI string // matrix://cortex/... reference
Type string // memory type name
Note string // optional advisory (e.g. contradiction edge)
}
The Note field carries a one-line advisory when a surfaced memory is joined to another surfaced memory by a live contradiction edge. Empty for ordinary memories.
Procedural patterns
Procedural memory is reusable how-to knowledge, the nursery for MCL skills.
func (p *Pager) Procedural(ctx context.Context, goal string) ([]Pattern, error)
Returns proven patterns whose trigger matches the goal, gated by MinPatternSuccesses. Sorted by confidence descending.
PatternSpec
The structured schema encoded onto cortex's flat Statement field:
type PatternSpec struct {
Name string // human label
Trigger string // when to apply
Preconditions []string // check BEFORE applying
Steps []string // proven tool sequence
Gotchas []string // learned failure modes
SuccessCriteria []string // verify AFTER applying
}
Encoded as neo.pattern.v1: + JSON. Legacy plain statements decode as a single freeform step.
Pattern lifecycle
- Experience - an episodic event ("this worked")
- Distill - background write-back abstracts the sequence into a candidate
- Reinforce -
ReinforcePatternincrements coverage and nudges strength up on each repeat success - Auto-propose - when coverage crosses
MinPatternSuccesses, the consolidator proposes it as a skill - Promote - a proven, rigorous pattern graduates into an authored MCL
.mtxskill
Write-back helpers
The pager provides typed write methods used by the background consolidation pass:
func (p *Pager) RememberFact(ctx, statement string) (string, error) // semantic memory
func (p *Pager) RememberFactRelated(ctx, statement string, classify func(string) int) (string, error) // conflict-aware
func (p *Pager) RememberUserFact(ctx, statement string) (string, error) // user profile (pinned)
func (p *Pager) RecordOutcome(ctx, summary string, outcome Outcome, intentRef string) (string, error) // episodic
func (p *Pager) WritePattern(ctx, spec PatternSpec, strength float32, coverage int, derivedFrom []string) (string, error) // procedural
func (p *Pager) ReinforcePattern(ctx, spec PatternSpec, derivedFrom []string) (string, error) // distill+reinforce
All write with SourceObserved provenance and the actor's scope. Facts use subject matrix://knowledge/neo (general) or matrix://knowledge/user (profile). User facts are deduped by normalized statement before writing. RememberFact skips a write whose statement is near-identical to an existing fact (semantic dedup), refreshing its recency/salience instead via the Attest usage loop.
Embedding backend
func pickEmbedder(cfg config.Config) embed.Embedder
Selection order:
- Matrix gateway -
${GatewayURL}/v1/embeddingswithMATRIX_GATEWAY_TOKEN+ actor DID. Spend is attributed under slot "neo". - Direct provider - Fireworks API key (
FIREWORKS_API_KEY) - Hash fallback - deterministic hash embedder. Retrieval degrades to pseudo-lexical, but nothing breaks.
A boot-time probe (probeEmbedder) issues one tiny embed to verify the backend accepts credentials. Without this, a misconfigured gateway would be selected and every page-fault would return nothing.
Token estimation
func EstimateTokens(s string) int
Uses cortex's bytes/4 heuristic. Deterministic and dependency-free. Matches the budget math everywhere.
func truncateTokens(s string, maxTokens int) string
Truncates to maxTokens * 4 bytes, appending a truncation marker.
Modifying memory behavior
| What to change | Where |
|---|---|
| Pinned block composition | memory/pager.go - Pinned() |
| Inviolable rules | agent/prompt.go - invariantRules |
| Retrieval type filter | memory/pager.go - Retrieve() salience lane |
| Pattern schema | memory/pattern.go - PatternSpec |
| Anti-overfit threshold | config/config.go - MinPatternSuccesses |
| Embedding backend priority | memory/embedder.go - pickEmbedder() |
| Write-back fact subject | memory/writeback.go - factSubject / userFactSubject |
| Conflict-aware linking | memory/writeback.go - RememberFactRelated() |
