AgentWorkingMemory · for builders & researchers

AWM for Agents: a harness playbook and what the benchmarks actually showed

AWM is a fast, precise recall substrate for long-running agents — not a multi-hop reasoner and not a sponge that remembers everything. This page explains why it was built, how to wire it into an agent so the agent learns by working, the full agent-facing feature surface, and the honest results from a benchmark suite we had to build because the established memory benchmarks don't test what agents need.

Audience: developers & researchers evaluating AWM as agent memory  ·  Scope: design rationale, integration pattern, measured findings  ·  Companion: pipeline-walkthrough.html (how recall works internally)

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.

TO ANSWER ONE QUESTION, CARRY… accumulated memory store (~20K memories) ~1.3M tok the project's notes & transcript docs ~2M tok the whole system (code + docs) ~29M — fits in no window AWM scoped recall — ~630 tokens, flat (≈2,000× fewer than carrying the store) Figures from real use on the platform project. A scoped recall answers from the relevant slice, not the whole corpus.
The wall is structural: at ~20K memories, "carry everything" isn't an option — retrieval is the only door.

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_supersede retires 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.

Headline result measured

On a real domain-support workload (a 15-task stress suite over a member-support investigation domain):

ConfigurationScoreCost / task
cheap reasoning-mini model + AWM (primed)14 / 15$0.0069
frontier model, no substrate priming7 / 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 auto recall → prompt 2 · ACT cost-tiered tools 3 · VERIFY read-back + substance 4 · LEARN auto feedback + capture AWM substrate — recall feeds in ↑ · learning feeds back ↓
The loop. Priming and learning are harness-owned and automatic — the model never has to "decide to remember."
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.

Two integration depths

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

  1. Embed AWM (in-process if possible); own recall + feedback in the harness, never leave it to the model.
  2. Prime before the model runs — recall + domain topic files into the prompt; use compact granularity to keep token cost low (~70% trim).
  3. Cost-tier the loop — cheap model for lookups, escalate only when needed.
  4. Wire the post-turn learning pipeline — feedback, canonical capture with supersede-on-correction, working-pattern capture, reflection.
  5. Add verify gates — read-back on writes, substance validation.
  6. 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:

PartDo
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.
TagsAlways 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

FeatureWhat it gives the agent
Agent IDHard memory isolation per agent. Default recall is agent-scoped — you only see your own memories.
Workspace multi-agentA 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 IDGroup memories from one conversation. Memories sharing a session_id get an entity-bridge recall boost (things learned together resurface together).
IncognitoA mode where the agent can read the store without writing — for exploratory or read-only tasks.

Writing & correcting knowledge

FeatureWhat it gives the agent
Memory classescanonical (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-tagsStructured, 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.
SupersedeRetire 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.
RetractInvalidate a wrong memory, attach the correction, and propagate penalties to associated memories (depth 2, decaying).
FeedbackMark 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-duplicateA 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

FeatureWhat it gives the agent
Cognitive recallNot cosine-only: dual BM25 (keyword + expanded) + vectors + cross-encoder rerank + graph walk + ACT-R decay + coreference expansion. See the pipeline walkthrough.
Granularityfull (default), compact (a query-aware ~200-char snippet per result — ~70% fewer output tokens when scanning many), auto (confidence-adaptive).
Abstentionrequire_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

FeatureWhat it gives the agent
MCP server16 first-class memory tools over stdio — recall / write / supersede / retract / feedback / tasks / checkpoint / restore.
HTTP API18 routes (write / activate / search / supersede / feedback / tasks / stats / metrics) for any non-Claude-Code agent or service.
Lifecycle hooks + bearer tokenA 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.
TasksFirst-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:

TierExamplesGuard
READquery, file read, recallAuto, no gate, runs concurrently.
REVERSIBLE-WRITEscoped update, file writeAuto, but mandatory read-back verify + audit.
EGRESSemail send, outbound POSTRecipient/host allowlist + rate limit + full audit to AWM + kill-switch env var.
IRREVERSIBLEunscoped write, deletesSnapshot/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.

In-engine spreading / injection — disconfirmed on LoCoMo honest negative
LoCoMo categorybaseline+ spread + injectΔ
Overall22.7%20.7%−2.0
Multi-hop (the target)13.4%12.3%−1.1
Single-hop18.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.

Harness-side entity bridge — validated validated

Gauntlet A/B (memory suite, k=3, bridge off → on):

Probeoffon
multi-hop (3 hops, no restatement)0%67%
sparse-cue67%100%
supersede-due67%100%
recall-person (no regression)100%100%
headline70%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.
Methodology guardrails (from an adversarial design review)
  • 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

Plain single-fact recall honest tie
Armpass (95% CI)
rag78% [78–78]
awm70% [67–78]
notes59% [56–67]
longctx0%
off0%

On a single-fact lookup, AWM's CI overlaps the RAG baseline — no significant advantage, and we say so. Retrieval alone is retrieval alone.

Cross-agent shared recall categorical win
ArmB recalls A's facts
awm100% (3/3)
rag0%
notes0%
off0%

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.

CROSS-AGENT SHARED RECALL — % OF AGENT A'S FACTS THAT AGENT B CAN RECALL awm 100% rag 0% notes 0% off 0%
The one place AWM doesn't tie a vector store is the one a library architecturally can't reach.

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).

Production audit — real coding-agent sessions
Retrieval methodtotal tokenscallsavg / call
file retrieval (read/grep)5,777,2172,7432,106
AWM recall591,3661314,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)savingsaccuracy
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:

CapabilitySQLite (default)PGlite
Cognitive engines (write/recall/consolidate/retract)
Vector searchJS cosine over slim cachepgvector (ivfflat)
Full-text searchFTS5 (BM25)tsvector
Multi-process safe (concurrent sessions)✓ (WAL)✗ single-process WASM
Hive coordination plugin✗ (auto-disabled)
Native bindings at installyes (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.

Roadmap
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.db users stay on SQLite via auto-detect.
1.0
Coordination plugin ported to async PGlite; /memory/export ported; 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 supersede when 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.