01Why AWM exists: the context-window wall
What the system was originally designed to do, and the problem that forced it.
AWM was born out of a single, concrete pain on a large, long-lived software platform project. The codebase, its documentation, the decision history, and the accumulated work transcripts together come to roughly 29 million tokens. That number fits in no context window, at any tier, on any model. You cannot keep that project's context "alive" by carrying it — and the usual escape hatch, summarizing to fit, silently drops the one fact you need next.
So the design goal was never "remember everything." It was the opposite: given a single question, retrieve only the relevant slice — a few hundred tokens — independent of how large the project grows. One work agent on that project has accumulated 20,000+ memories across the multi-million-token corpus, and still answers a given question from a tiny scoped recall.
Two structural properties separate this from a notes file or a flat vector store — and they are the reason a coding/operations agent can keep moving through a project for months:
- Staleness is tracked. When a fact changes,
memory_supersederetires the old value and recall stops returning it — the system knows what changed. A notes file or a repo goes stale silently; you'd re-scan everything to find out. - Dead weight costs nothing. ~90% of accumulated memories are never recalled for a given task. A notes file pays for all of them in every prompt; scoped recall pays for ≈zero.
The thesis in one line: past roughly half a million tokens, you stop carrying context and start retrieving it. AWM is the retrieval layer built for that regime — tuned for productivity and engineering workflows where staying on topic and filtering noise matter, explicitly not for remembering every line of every chat.
02The agent-harness pattern: memory as a substrate, not a tool
PRIME → ACT → VERIFY → LEARN. The phases the model does not control are what make it a substrate.
The highest-leverage way to use AWM is not "give the model a recall tool and hope it calls it." It's to make the harness own memory: recall before the model's turn and learn after it, with zero model cooperation required. That single shift is what lets a cheap model perform at a high level — because the hard-won domain knowledge lives in the substrate, not the model's weights.
On a real domain-support workload (a 15-task stress suite over a member-support investigation domain):
| Configuration | Score | Cost / task |
|---|---|---|
| cheap reasoning-mini model + AWM (primed) | 14 / 15 | $0.0069 |
| frontier model, no substrate priming | 7 / 15 | $0.277 (≈40×) |
A small, cheap model out-performed a frontier model at ~1/40th the cost — the domain knowledge (schemas, working queries, business rules, prior corrections) was primed into context for it. Move capability from the model into the memory.
- 1 · PRIME (automatic, pre-model)
- Before the model sees anything, the harness recalls relevant memories — verified facts, working query patterns, prior corrections — and injects them into the system prompt. The model starts already knowing what every prior run learned.
- 2 · ACT (cost-tiered)
- A router picks a cheap model for lookups and escalates to a reasoning model only when needed, per iteration. Most iterations are cheap.
- 3 · VERIFY (mechanical gates)
- Reversible-write tools require a read-back confirmation; responses are validated for substance (did it actually answer with real data?). Failures loop back with a corrective prompt before finalizing.
- 4 · LEARN (automatic, post-model)
- After the turn, with zero model cooperation, the harness sends feedback on which recalled memories were used (Hebbian strengthening), captures discovered schemas as canonical memories with supersede-on-correction, captures working query patterns, and reflects on gaps as friction memories.
Why it compounds
A stateless tool-calling agent pays full price for every task forever. This pattern doesn't: primed schemas + working queries mean fewer iterations next time, recall replaces flailing (measured ≈9.8× cheaper than a Read/Grep/Glob rediscovery workflow), corrections supersede wrong facts so mistakes don't recur, and the Hebbian loop promotes what proved useful. Net: on a fixed workload the same agent gets cheaper and better with use.
Embedded (deepest): AWM engines run in-process on a local SQLite DB — no network hop; the harness calls feedback/edge-strengthen/class-bonus rerank directly. HTTP / MCP client (shallower): recall/write/feedback over the wire, for agents that can't embed. Either way the recall→feedback wiring must be owned by the harness — which is exactly why a generic MCP-tool host (where recall is a tool the model chooses to call) can't reproduce the flywheel: priming and feedback stop being automatic.
Reuse checklist
- Embed AWM (in-process if possible); own recall + feedback in the harness, never leave it to the model.
- Prime before the model runs — recall + domain topic files into the prompt; use
compactgranularity to keep token cost low (~70% trim). - Cost-tier the loop — cheap model for lookups, escalate only when needed.
- Wire the post-turn learning pipeline — feedback, canonical capture with supersede-on-correction, working-pattern capture, reflection.
- Add verify gates — read-back on writes, substance validation.
- Set the network perimeter, then tier every tool (see §3) — guards in the tool code, not the prompt.
Best practice: write for recall — summary, detail, and tags
Recall quality is decided at write time. AWM is good at finding what's findable, but a badly-shaped write can't be rescued by any retriever. Every memory has three parts that all matter — and the common mistake is filling in only the first:
| Part | Do |
|---|---|
| Concept (short summary) | 3–8 words, and lead with the rule or fact, not the backstory. "Period-close BLOCKED check missing server-side" — not "a thing about accounting." This is the label, not the memory. |
| Content (the detail / description field) | Don't stop at the summary. The body is what BM25, the embedding model, and concept extraction read most strongly — and what a future query actually matches. Be slightly more verbose at the front than feels natural: include the mechanism, the file/function, and (for guidance) the why. A rule with no reason can't be applied to edge cases. |
| Tags | Always pass the structured prefix-tags — proj=, topic= (most specific you can), intent=, confidence_level= — and add 2+ retrievable identifiers present in the content: file=/path, function name, ticket=, date=YYYY-MM-DD, person=. Tags are a hard filter and a BM25/entity-bridge boost at recall time; the difference between a memory found in three months and one lost in a noisy bucket. |
Write in the vocabulary of the future question. Imagine
asking this in three months — use those exact nouns (file paths, table columns, error strings),
not a neutral paraphrase. Reserve canonical for stable invariants and anything other
agents must recall; leave findings and progress notes in the default working class.
03Agent feature surface
The full set of capabilities an agent (or a fleet of agents) can use — identity, sharing, learning, safety.
Identity, isolation & sharing
| Feature | What it gives the agent |
|---|---|
| Agent ID | Hard memory isolation per agent. Default recall is agent-scoped — you only see your own memories. |
| Workspace multi-agent | A shared substrate across a fleet. Pass workspace on recall (or set AWM_WORKSPACE) and one agent recalls what another wrote — in real time, distinct agent IDs, one store. This is the capability a per-process notes file or library structurally cannot do. |
| Session ID | Group memories from one conversation. Memories sharing a session_id get an entity-bridge recall boost (things learned together resurface together). |
| Incognito | A mode where the agent can read the store without writing — for exploratory or read-only tasks. |
Writing & correcting knowledge
| Feature | What it gives the agent |
|---|---|
| Memory classes | canonical (source-of-truth, salience floor 0.7, never staged), working (default, salience-gated), ephemeral (decays fast), structural (high-volume system event-log records, excluded from auto-activation). |
| Prefix-tags | Structured, retrievable metadata — proj=, topic=, intent=, confidence_level=, plus identifiers like ticket=, date=YYYY-MM-DD, person=. Drive BM25 boosts and entity bridges at recall time. |
| Supersede | Retire an outdated fact and link the replacement (old confidence decays, BM25 stops returning it). Atomic "write-and-supersede by concept match" in one transaction — staleness is tracked, not silent. |
| Retract | Invalidate a wrong memory, attach the correction, and propagate penalties to associated memories (depth 2, decaying). |
| Feedback | Mark a recalled memory useful / not-useful. Tunes confidence and the validation-gated Hebbian edges so useful memories strengthen and surface first next time. |
| Reinforce-on-duplicate | A restated fact merges into the existing memory and re-embeds, instead of creating a near-duplicate. |
| References & resolve (0.8) | Typed cross-record links (advances/resolves/…) and a resolve call that computes an engram's effective state (active / resolved / superseded / abandoned). |
Recall controls
| Feature | What it gives the agent |
|---|---|
| Cognitive recall | Not cosine-only: dual BM25 (keyword + expanded) + vectors + cross-encoder rerank + graph walk + ACT-R decay + coreference expansion. See the pipeline walkthrough. |
| Granularity | full (default), compact (a query-aware ~200-char snippet per result — ~70% fewer output tokens when scanning many), auto (confidence-adaptive). |
| Abstention | require_confidence makes recall return nothing rather than best-of-bad noise — so the agent can act on "I don't know" instead of a plausible-but-wrong fact. A multi-channel agreement gate backs it (2+ channels must agree). |
| Tag-set search (0.8) | AND / OR / NOT tag operators, latest-by-tag, top-by numeric tag sort, race-free sequence allocator — relational-style queries over the memory store. |
Interfaces, hooks & the bearer token
| Feature | What it gives the agent |
|---|---|
| MCP server | 16 first-class memory tools over stdio — recall / write / supersede / retract / feedback / tasks / checkpoint / restore. |
| HTTP API | 18 routes (write / activate / search / supersede / feedback / tasks / stats / metrics) for any non-Claude-Code agent or service. |
| Lifecycle hooks + bearer token | A bundled hook sidecar (loopback 127.0.0.1 only) auto-checkpoints on Stop / PreCompact / SessionEnd so context survives compaction and session close. Hook calls authenticate with an Authorization: Bearer ${AWM_HOOK_SECRET} token — set the env var to any random value and awm setup wires the same secret into the hook config. Wrong token → 401; the local-only bind keeps the surface tight. |
| Tasks | First-class task records (create / update / list / next) with priority and blockedBy dependencies — the agent's working backlog lives in the same store as its knowledge. |
| Metrics | /agent/:id/metrics exposes precision@k, recall latency (p50/p95), edge-utility rate, retraction rate — so an operator can see whether memory is actually helping. |
Tool-safety tiers (for agents that act, not just answer)
Freedom is earned by containment. The reference deployment is network-isolated (private VPN / Tailscale, no public ingress); because the perimeter is tight the agent can be granted more internal action freedom. Then every tool is classified into a tier whose guard lives in the tool code, not the prompt:
| Tier | Examples | Guard |
|---|---|---|
| READ | query, file read, recall | Auto, no gate, runs concurrently. |
| REVERSIBLE-WRITE | scoped update, file write | Auto, but mandatory read-back verify + audit. |
| EGRESS | email send, outbound POST | Recipient/host allowlist + rate limit + full audit to AWM + kill-switch env var. |
| IRREVERSIBLE | unscoped write, deletes | Snapshot/transaction first, or explicit confirm-token / dry-run-then-apply. |
04Multi-hop: AWM stays precise; the harness does the chaining
A deliberate division of labor — and the data that settled it.
AWM is a fast, precise single-hop retriever. Its final cut is a cross-encoder reranker, by design. A natural temptation is to make AWM itself do multi-hop — spread activation over the association graph and inject graph-neighbors into the result pool. We tried it, and it regressed recall.
| LoCoMo category | baseline | + spread + inject | Δ |
|---|---|---|---|
| Overall | 22.7% | 20.7% | −2.0 |
| Multi-hop (the target) | 13.4% | 12.3% | −1.1 |
| Single-hop | 18.6% | 13.5% | −5.1 |
Graph-neighbor candidates displace genuine evidence and fight the
reranker (AWM's final cut). Adding breadth in the final cut hurts everywhere. These paths are kept
behind default-off flags (AWM_SPREAD) for research; the production path is unchanged.
The design-aligned fix lives in the harness, not the engine: after the first recall, extract the salient proper-noun entities from the top results that aren't already in the instruction, and issue a fresh single-hop recall on each entity (2 rounds, so 3-hop chains resolve). Each follow-up is a high-precision single-hop query whose vocabulary now matches the answer — it never asks AWM to be something it isn't. The model then chains over the merged, primed set.
Gauntlet A/B (memory suite, k=3, bridge off → on):
| Probe | off | on |
|---|---|---|
| multi-hop (3 hops, no restatement) | 0% | 67% |
| sparse-cue | 67% | 100% |
| supersede-due | 67% | 100% |
| recall-person (no regression) | 100% | 100% |
| headline | 70% | 81% |
Cost: ~+20% steps from the extra bridge recalls — acceptable. CI moved
from [56–78] to [78–89] (essentially separating). For "what does X think"-style attribution
queries there's also an opt-in in-engine boost, AWM_QUERY_BRIDGE, which lifted attribution
36%→92% on a controlled eval (kept opt-in for its small adversarial cost).
Principle: breadth in candidate generation, precision in the final cut. Multi-hop is the harness's job (re-query with the entity); AWM stays fast, precise, and single-hop.
05The gauntlet: why we built it, and what it showed
Established memory benchmarks measure a chatbot. Agents need something else measured.
Why a custom suite
LoCoMo, Mem0's eval, and the Letta leaderboard are chatbot-memory benchmarks: long multi-session conversations, "what did we say about X." Useful, and we report on them (§8) — but they don't exercise the capabilities an agent + memory system actually lives or dies on:
- Cross-agent sharing — can agent B use what agent A learned?
- Staleness / supersede — when a fact changes, does recall stop returning the old one?
- Noise rejection & abstention — distractors present; does it return the right fact or confidently return a wrong one?
- Context-switching / bleed — many parallel clients/projects; does one project's data leak into another's answer?
- Sparse cues & multi-hop without restatement — the query doesn't echo the stored wording.
- Each system uses its own canonical write policy — plus a naive-dump ablation. (Comparing a tuned writer to a naive one is unfair.)
- Distractor sweep, not a single point — a curve over 2/5/10/20 distractor turns.
- Required baselines: BM25, hybrid, time-weighted RAG, and long-context-no-memory. Without them the comparison is incomplete.
- Deterministic exact-match scoring for constrained-answer recall; reserve an LLM judge for synthesis only.
- A custom benchmark is a diagnostic supplement, not the headline — "made to win" is a credibility risk. Established benchmarks carry the headline numbers.
The arms
awm (full cognitive substrate) · rag (AWM's own embeddings + plain cosine
top-k — a strong baseline) · notes (flat file, substring match) ·
longctx (stuff the whole store into context, byte-capped) · off (null memory,
ablation control).
What it showed
| Arm | pass (95% CI) |
|---|---|
| rag | 78% [78–78] |
| awm | 70% [67–78] |
| notes | 59% [56–67] |
| longctx | 0% |
| off | 0% |
On a single-fact lookup, AWM's CI overlaps the RAG baseline — no significant advantage, and we say so. Retrieval alone is retrieval alone.
| Arm | B recalls A's facts |
|---|---|
| awm | 100% (3/3) |
| rag | 0% |
| notes | 0% |
| off | 0% |
A categorical gap, not a noisy margin. A per-process library/file cannot share across agents; AWM's shared substrate can. This is the result that isn't a tie.
Efficiency, same suite: AWM ~9–11k input-tokens/task at ~150–200ms recall (rerank
+ expansion included); RAG ~9–10k at ~7–10ms; longctx ~17k tokens/task and 0% on
memory-dependent answers (it truncates and drops the fact). AWM buys correctness and sharing at a few
hundred ms — not free, and we measure the cost.
06Multi-agent: one substrate, a fleet of agents
The capability that follows directly from a shared store with per-agent identity.
Because memories live in one store keyed by agent ID, a workspace turns the store
into shared cognition: when any agent writes or supersedes a canonical memory, every
other agent in the workspace can recall it immediately. That is what produced the 100%-vs-0%
cross-agent result above — and it's the foundation for a coordinated fleet:
- Shared canonical knowledge. A "discovered the prod DB schema" fact written by one agent primes every other agent's next task — no re-discovery.
- Coordination plugin. On the SQLite backend, AWM ships a hive-coordination layer: a worker registry, assignment dispatch, per-decision propagation (peer decisions surface in each agent's recall), and circuit-breaker / stale-worker detection.
- Entity-bridge boost via session/workspace. Facts learned together (shared
session_id) and facts other agents wrote (workspace recall) resurface together.
Practical guidance for fleets: write the facts other agents must see as
memory_class: canonical (the default working class is salience-gated and may
not survive), and recall with the workspace set. Coordination currently requires the
SQLite backend (see §9).
07Context-window & context-switching tests
What's implemented, and what's designed-but-not-yet-run — stated plainly.
Context-switching / bleed implemented
The gauntlet includes a context-switch suite: several parallel "clients/projects," each with its own contact, deadline, and budget, probed in interleaved order (one switch per turn). It directly measures cross-project contamination — does a query about project A ever return project B's budget? This is exactly the failure mode a single shared agent on a big platform must not have, and it's why AWM scopes recall by relevance + identity rather than dumping a window.
Needle-in-haystack / context-window scaling designed, not yet run
A scaling test — plant one fact among an increasing volume of distractor memories and measure recall@k as the haystack grows — is specified but not yet executed (it's on the backlog, not in the results). We're flagging it as pending rather than quoting a number we don't have. The hypothesis it will test: because AWM retrieves a fixed-size scoped slice, recall@k should stay roughly flat as the store grows, where a fixed context window degrades once the haystack exceeds it. The §1 production figures (constant ~630-token recall against a 29M-token corpus) are the real-world version of this claim; the synthetic scaling curve will quantify it.
08Token economics — the honest version
Where the savings are real and large, where a micro-benchmark currently regresses, and why.
The real, large win is structural
The token argument that matters is the one from §1: at 29M tokens you cannot carry the project at all, and a scoped recall answers from ~630 tokens — ~2,000× fewer than carrying the store, ~5× fewer than even opening the single best-matching doc file (a floor — agents usually open several and still miss cross-file facts).
| Retrieval method | total tokens | calls | avg / call |
|---|---|---|---|
| file retrieval (read/grep) | 5,777,217 | 2,743 | 2,106 |
| AWM recall | 591,366 | 131 | 4,514 |
Aggregate cost ratio 9.8 : 1 in AWM's favor — recall replaces the repeated file-rediscovery that dominates a coding agent's token spend. (A single recall is larger per call, but you make ~21× fewer of them.)
The micro-benchmark, and the baseline trap root-caused
A per-turn micro-benchmark (a 44-turn dev-conversation corpus) once looked like a regression (≈−8% "savings"). Chasing it down showed the number was a baseline-choice artifact, not a recall defect. The benchmark now reports both baselines, because the baseline you pick is the result:
| Baseline (the alternative to recall) | savings | accuracy |
|---|---|---|
| Carry the full conversation history — what a memoryless agent must actually do | +67% | 97.5% |
| Oracle: carry only the exactly-relevant task's turns (assumes perfect manual scoping) | ≈ −13% | 97.5% |
The oracle baseline hands the comparison the very thing retrieval exists to produce — a context already narrowed to the right task — so on a 6–8-turn task a fixed top-5 recall is break-even-to-negative by construction. The realistic baseline (carry everything, because you can't know in advance which turn matters) is +67%, consistent with the at-scale story in §1.
And the old "~56%" oracle-bar number? An artifact of a data-loss bug: pre-v0.8.5, reinforce-on-duplicate silently discarded memory content, so recalls were artificially tiny. v0.8.5 fixed it (accuracy ~72%→97.5%); better recall now fills all five slots, which lowers the oracle-bar percentage while raising correctness — less-but-lossy traded for more-but-correct.
Lesson worth keeping: a token-savings number is meaningless without naming the baseline. The savings that justify AWM are structural (you cannot carry 29M tokens at all) — not a per-turn percentage against a baseline that already did retrieval's job for it.
09Backends & roadmap — where Postgres fits
0.9 is the "make it commercially strong for agents" line; full networked Postgres is a v1 goal with real work remaining.
AWM ships two functionally-equivalent storage backends behind one interface:
| Capability | SQLite (default) | PGlite |
|---|---|---|
| Cognitive engines (write/recall/consolidate/retract) | ✓ | ✓ |
| Vector search | JS cosine over slim cache | pgvector (ivfflat) |
| Full-text search | FTS5 (BM25) | tsvector |
| Multi-process safe (concurrent sessions) | ✓ (WAL) | ✗ single-process WASM |
| Hive coordination plugin | ✓ | ✗ (auto-disabled) |
| Native bindings at install | yes (prebuilt) | no (pure-JS WASM) |
| Path to a real Postgres server | ✗ | ✓ (same SQL surface) |
SQLite is the default and the right choice for the common case — multiple Claude Code sessions can safely share one database via WAL. PGlite (embedded Postgres-in-WASM with pgvector) is opt-in; it's single-process, so two processes against the same directory will abort the second, and it currently has a known WASM-init crash on some Node-22 / Windows combinations — which is another reason MCP / multi-session setups stay on SQLite.
- 0.9.x — commercial-grade for agents (this line)
- The recall-quality + agent-feature improvements described on this page. PGlite default for
new installs (target); existing
memory.dbusers stay on SQLite via auto-detect. - 1.0
- Coordination plugin ported to async PGlite;
/memory/exportported; SQLite still supported. - Post-1.0 / v1 target in design
- A real networked Postgres backend for scale — same engine code as PGlite,
swap the connection layer (
AWM_STORE_URL). The honest status: the embedded-Postgres surface is built and tested, but the full networked move still needs the cognitive engines made fully async at every call site, an async adapter for the SQLite path, the export/coordination paths ported, and a backup/integrity story for a server DB. It's a deliberate v1 milestone, not a flag flip.
10When not to use it
The trade-offs, stated up front.
- Small, one-shot tasks. Write/recall overhead exceeds the savings until knowledge is reused or the corpus outgrows the context window. AWM wins on scale and reuse.
- Recall isn't free. A few hundred ms (and a few seconds for cold models) per query buys the token reduction. For a hot inner loop, cache or skip it.
- A generic MCP-tool host. You get recall-as-a-tool, but not the automatic prime+feedback+learn flywheel — that requires the harness to own the wiring (§2).
- It is not your source of truth. The intended pattern is: recall first,
read/grep the code for ground truth on a miss, and
supersedewhen reality differs. - Recall quality is bounded by write quality. Lead with the fact; tag with identifiers (file, table, ticket). A vague write can't be rescued by any retriever.