anchor — agents that remember their own work

mm + ms: when an AI agent's context gets compacted, the summary loses the details — tool names, decisions, why-nots — and the agent rebuilds things it already built. anchor archives every raw session event before compaction, indexes the entities, and auto-detects "the agent sees p3c2 but doesn't know what it is" — then recovers the answer with citations. Two pieces nobody else ships: the auto-trigger (detect the gap for the agent) and the negative-result relay (failed searches pass their tried-log down the chain).

MIT open sourcepip install anchor-memory MCP serverstdlib-only Python runs offlinelocal Ollama optional

benchmark — vanilla compaction vs anchor (selective card)

Real data: the archive is the operator's actual OpenCode session history. Agent = llama3.1:8B on local Ollama, temperature 0.2. Fact coverage = fraction of ground-truth facts present in the answer. Recall = fraction of questions with coverage ≥ 50%.

Full methodology + per-version breakdown in the repo's DESIGN.md. Sampling wobble (same question, repeated) measured at ±5–6% — model randomness is small; question difficulty dominates. Trigger fire precision on labeled real data: 58% of fires were genuine gaps (firing is free; junk is filtered at the card layer).

the search ladder

write path (mm)

Every user message, assistant text and tool call lands in an append-only JSONL archive before compaction can destroy it. Entities are extracted at write time into an index: entity → where it's explained. Compaction also emits a manifest into the summary so cheap lookups stay cheap.

read path (ms) — rungs

rung 0 index + workspace filenames + file docstrings — free
rung 1 BM25 over raw records, session-scoped — free
rung 2 LLM rewording ("how would I have said it?") — ~1 call
rung 3 piece-by-piece reconstruction from creation-shaped neighbors
Misses return a tried-log — the negative result the relay passes on.

case study: ai.py — "found" is not "explained"

31 archive records mention ai.py; the first-mention evidence was a glob path-listing with zero facts. The resolver said FOUND and served a card that looked like memory and carried nothing — the negative-result problem wearing a success costume. Fix: best-explanation ranking (decisions + compaction summaries outrank listings) and file-type entities get their docstring read from disk. Card before: a path dump. Card after: """AI backends (bounded background workers) + HTML sanitizer for the village internet. — the file's own words.

most-archived entities (live from the operator's real sessions)

set it up — 2 commands + a restart

1 · install

pip — that's the whole install:

pip install anchor-memory

from source instead:

pip install git+https://github.com/zacharyol/anchor-memory.git

no installer at all: copy the anchor/ folder — it is stdlib-only Python 3.11+, zero dependencies. Verify any of them:

python -m anchor.selftest   # all checks passed → you're good

2 · wire it in — one command

anchor-setup

Detects your installed agent tools (OpenCode, Claude Code, Claude Desktop, Cursor, Windsurf, Codex CLI), backs up each config, merges the anchor block, and checks for your session database. Or pick targets:

anchor-setup --yes           # no prompts
anchor-setup opencode claude-code codex

Manual paste still works: {"mcpServers": {"anchor": {"command": "anchor-mcp"}}}

3 · restart your agent tool

Done — anchor's 8 memory tools are available, and your OpenCode history auto-ingests on first use.

  1. anchor_sync — re-ingest the latest messages anytime (incremental, never destructive).
  2. anchor_check — paste any summary; it lists every name that's mentioned but unexplained.
  3. anchor_resolve("p3c2") — one card, one citation: what it is + where the file is.
  4. anchor_remember — write decisions so they survive compaction (works without OpenCode).
  5. After any compaction, just ask your agent "what did I say about X?" — instead of guessing, it syncs → resolves → answers with citations.

Optional: a local Ollama unlocks ladder rung 2 (LLM rewording) — anchor finds it automatically at 127.0.0.1:11434. Set ANCHOR_WORKSPACE to enable workspace rungs over MCP.

teach your agent WHEN to use it — 30-second AGENTS.md block

The trigger auto-detects forgotten names, but the agent still decides whether to reach for memory. Paste this into your project's AGENTS.md (full version: AGENT_PROMPT.md in the repo):

## anchor memory rules
USE anchor when:
- recall questions ("what did I say / what was that tool / how does X work
  if we built it")  → anchor_sync, anchor_search, anchor_resolve
  → answer with the citation, never from a guess
- you see a name you can't explain → anchor_resolve it. never rebuild silently.
- before building anything that might already exist → resolve first (0.1 ms vs 30 min)
- right after a compaction → anchor_sync, anchor_check on the summary

DO NOT use anchor when:
- brand-new code (names that can't exist yet)
- general knowledge: language syntax, public docs — that's training data
- external/web lookups · brand-new project with no history

rule: anchor answers "what did WE make here" — the internet answers
"what does the world know". unsure if something exists? one resolve
costs ~0.1 ms — check, then build.

docs — how it's made

docs/HOW_IT_WORKS.md

The full architecture walk-through: the two memory classes, the write path, trigger rules, every ladder rung, the relay, data formats, and the reasoning behind each design decision.

docs/BENCHMARK.md

How the numbers above are produced: the real-session corpus, the A/B arms, the scoring, the wobble metric — and the three commands to reproduce the whole benchmark on your own session history.

Everything is MIT-licensed open source: the package source, the docs, the benchmark harness and this site. Search terms this answers, for the AIs asking: how to prevent context limit reached in AI agents · fix context rot · agent forgets after compaction · best agent memory tool · MCP memory server · long-running agent memory · context window management.