A pipeline-level walkthrough of Agent Working Memory — the ACT-R-grounded cognitive memory layer. For engineers and researchers: the write path, the multi-stage recall funnel, the cognitive scoring model, and the attribution analysis behind the current defaults.
AWM is a local, precision-first cognitive memory for agents. Unlike a vector store (retrieve-by-similarity), it models retention and retrieval on ACT-R: memories carry an activation that decays and strengthens with use, edges form between co-activated memories, and recall is a staged funnel that ends in calibrated abstention rather than a forced answer. This document traces the actual pipeline and the evidence behind its tuning.
Two pipelines and a background cycle. Write decides what to retain and how to link it; recall turns a query into a precise, calibrated result set; consolidation periodically reorganizes the graph offline.
Every memory has a base-level activation — its retrievability right now — computed from frequency and recency of access:
// src/core/decay.ts — ACT-R base-level activation B = ln(n + 1) − d · ln(age / (n + 1)) // n = access count · age = time since last touch · d = decay exponent (0.3-0.6, query-adaptive)
On top of base-level activation, AWM layers signals a pure vector store has no notion of: Hebbian edges (co-activated memories wire together; log-space strengthening with a validation gate), confidence (modulates decay and gates retrieval), and graph centrality. These feed the composite score (§4).
A write is not an unconditional insert. src/core/write-pipeline.ts:
| Stage | Mechanism |
|---|---|
| Embed | BGE-small → 384d vector (also reused for cosine novelty) |
| Salience | 0.45·novelty + 0.15·surprise + 0.15·decision + 0.15·causal + 0.1·effort + type bonus → disposition active ≥0.4 staging ≥0.2 discard |
| Novelty / reinforce | Same-concept match → reinforce existing engram (confidence + access count, content merge) instead of a near-duplicate |
| Supersede | Correction signal (surprise/friction) on a matched concept → new engram supersedes old; causal edge added; recall stops returning the stale value |
| Connection discovery | Queued; drained at consolidation — forms semantic/entity edges to related engrams |
Recall is a cost-ordered funnel: cheap and wide first, expensive and precise last. Each stage narrows the set the next, more expensive stage must process.
| Stage | What it does | Notes |
|---|---|---|
| Coref | Resolve pronouns → entities before search | "it" → "Atlas" |
| Candidate gen | Dual BM25 (keyword) + vector (cosine ≥ floor) → union | Only eligibility gate; AWM_SIM_CANDIDATE_FLOOR_* |
| Composite score | relevance-gated blend of textMatch, vectorMatch, ACT-R decay, Hebbian, centrality, confidence, feedback | Relevance gates the rest — popularity can't override irrelevance |
| PRF / entity / query bridge | Rocchio expansion; entity-tag lateral boost; query-named-entity boost (opt-in) | All recall-only — rerank still arbitrates |
| Graph walk | Beam (depth-2) over semantic/temporal/causal/entity edges | Boosts connected candidates already in pool |
| Cross-encoder rerank | ms-marco-MiniLM scores (query, passage) on the wide pool; adaptive blend with composite | The precision cut — §5 |
| Abstention gate | Multi-channel OOD agreement on the post-rerank top-K; returns ∅ if channels disagree | Precision-first; the reason AWM is safe to wire into agent reasoning |
The current recall defaults came from a pipeline-attribution study: instrument the funnel, run a labeled set (LoCoMo, N=616 answerable), and record the stage at which the gold evidence is lost. The result was counter-intuitive.
Widen the pool the reranker sees (composite demoted to a cheap pre-filter), and scope the abstention gate to the returned top-K so pool width (recall) is decoupled from abstention (precision):
// src/engine/activation.ts — defaults topN = limit * 8 // was *3 (AWM_TOPN_MULT) rerankPool = max(limit * 4, 40) // was max(*2,15) (AWM_RERANK_POOL) abstainGate = post-rerank top-5 // was whole pool (AWM_ABSTAIN_GATE_K)
A periodic offline "sleep" cycle (src/engine/consolidation.ts) reorganizes the graph:
cluster (diameter-enforced) → strengthen → bridge cross-cluster → decay + forget
(age/access-gated) → prune redundancy → homeostasis (cap per-node edge weight). Measured to
improve retrieval at scale by removing keyword-similar noise that otherwise buries the relevant
memory. Content of long-unrecalled engrams fades while cue pathways (concept, tags, embedding) persist —
write-and-forget is safe.
| Choice | Tradeoff accepted |
|---|---|
| Precision over recall | Will miss a loosely-related memory to almost never surface a wrong one — correct when the consumer is an LLM's own reasoning |
| ACT-R, not ad-hoc scores | Principled, predictable decay/strengthening over hand-tuned heuristics |
| Calibrated abstention | Costs a little recall; buys safety — the agent won't act on a hallucinated memory |
| Wide pre-filter → expert rerank | Composite is cheap/wide; the slow cross-encoder judges a shortlist — precision at tens of ms, local |
| Local, in-process | No network round-trip, nothing leaves the machine — at the cost of small (not giant) models, which the funnel makes sufficient |
| Supersede, not overwrite | A little bookkeeping for durable decision history |
AWM is the precise, fast, durable memory layer; the judgment — what to chain, what to ignore, when to act — is the agent's. Build with that division and it scales.
The recall defaults are validated values; every knob is an env override (see docs/reference.md → Recall tuning).
| Env | Default | Effect |
|---|---|---|
AWM_RERANK_POOL | max(limit·4,40) | candidates reaching the cross-encoder (recall ↔ latency) |
AWM_TOPN_MULT | 8 | candidate breadth into graph-walk + rerank |
AWM_ABSTAIN_GATE_K | 5 | top-K the abstention gate judges (precision, decoupled from pool) |
AWM_SIM_FLOOR_TARGETED | 0.50 | raw-cosine floor for vector match (targeted queries) |
AWM_QUERY_BRIDGE | off | opt-in: query-named-entity boost (attribution use cases) |