Repository settings: .asf.yaml Follows tooling-llmao: description, homepage, PR and issue subjects, and notifications to commits@tooling.apache.org. main is not yet protected, so the placeholder can be replaced by this history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared memory and coordination for fleets of agents, built so that the record outlives every agent, harness, model, and vendor it was written with. This repository holds the reference implementation and the plan for building it.
The design is the paper in docs/. The plan, including the first milestone, is PLAN.md. The stack this grows into is docs/reference-stack.md.
What is proven here is the paper‘s contracts, not a system that scales. The entry format and its frontmatter, the ledger’s rules (one holder, leases, dedup by origin and upstream event, recursive invalidation), the MCP surface, trust tiers and review clocks, summaries first, the hook protocol, the egress as the only way out, and the containment set (canaries, an independent checker, reversible writes) are built and exercised end to end, by real harnesses on real models, and the conformance suite in crates/memory/tests is the statement of them. Beyond the read path, so are the paper‘s other commitments: trust tiers that move only by a person’s approval, policy as memory with scoped exceptions, the write gates and the quarantine, the task fabric‘s rubric, the librarian’s curation and its own telemetry, prefetch and the read metrics, vendor-drift probes, transcripts kept as sources, spend limits at the egress, and frozen-context replay. Every store behind those contracts is the simplest thing that could hold them on one laptop: the record as files under one directory, the index, the ledger and the metering each a SQLite file, the read log a JSONL file, one process holding every lock, one host. That is deliberate. It let the contracts be tried against ten harnesses in two weeks, and it is also why none of it is the production shape.
amem replay, on decision contexts the egress records, and so is live re-execution, amem reenact: a prompted session run again on its prompt at its commit, its memory calls answered from a tape of what they returned until the run diverges. An interactive session has no prompt to run again, a task run‘s tape does not yet carry its task’s prompt, and a login run through a tunnel, which the egress cannot see into, has no contexts, so its replay falls back to the harness's own transcript, a self-report, and says so. Re-enactment has run on Codex through the gateway (demo act 8), not yet on the other harnesses.platform <kind> <name> blocks: an agent definition and a template that open a task‘s prompt, an eval suite amem golden --platform scores, and a harness’s default model. Each loads only from an active entry a person verified, as a policy rule is enforced only once verified (amem platform list says why the rest do not). Not yet: harness settings beyond the model, decomposition templates for the board, authoring agent definitions, and the loop that proposes changes to them from cost and telemetry.human) and as approvers by convention; nobody authenticates.amem log). The ledger keeps its events in its own table rather than the domain's log, the index is not yet fed from the log as it grows, only rebuilt from it, and there is no freshness fast lane with a published bound.--drift, against fixed thresholds.amem cost, amem usage, the evaluation). Not yet: a task's own duration from claim to completion, accelerator time, which only the gateway can count, bytes stored, and CPU or memory limits on the sandbox.make verify run by hand.These do what the paper says, on one laptop, and each names what replaces it.
SKIP LOCKED claim, but one connection per process and no pool. Production: the Postgres shape, pooled, as a projection of the log.state/, and everything computed from them, the librarian’s retrieval signals and telemetry, taint, the read metrics, the policy rates, the relay and write-rate alarms, prefetch's co-retrieval, reads them whole. Production: the same events as OpenTelemetry spans, already emitted, into a collector and analytics tables.state/log, behind a file lock. Production: a partitioned log, Kafka in the reference stack, a partition per domain and the materializer a consumer of it.state/, reviewed by a model on request, released by the owner by hand.amem tool-server) that runs the same components for launchers elsewhere, or fetch natively when no component is installed, behind the same gate; called through the egress like a model call: held to the tool’s ceiling, metered and timed under the tool‘s name, the server’s bearer put on there. Every source says where it was fetched from. A held answer is released by the owner by hand (amem source release). Production: the tool servers registered in the Foundation's gateway, found by name rather than by URL.wait4), which sees a process tree only as far as each level reaps its children, and peak memory is the largest process’s, not the tree‘s sum. Production: the gateway’s per-key spend, with each call tagged with its task and trace.None of this is hidden in the code: the conformance suite states the contracts, the reference stack in docs/reference-stack.md names each production backend, and the register in PLAN.md the order. Production backends go in behind the same crates and must pass the same suite, and the evaluation harness and amem savings give the numbers for each swap, so that nothing in the move is argued from taste.
Two halves around one record. The memory server is what an agent harness reaches over MCP: it serves the record by summaries first, holds the task ledger, and checks every read and write against the policy. The launcher runs a harness confined, with no network except the egress, which forwards its model calls to a provider or a gateway, meters them, holds the credentials, enforces spend limits and records each call's decision context. An agent starts empty, loads a small index called T0, works a task it claimed, and writes a handoff when it stops; the next agent continues from the handoff, not a transcript. Around them, the librarian curates the record on a budget, the perimeter decides what may be read, written and admitted, and a person promotes what the system may rely on.
person ──▶ amem: web launcher, CLI, profiles
│ launch / work (a claimed task)
▼
┌─ confined harness, no network ───────┐
│ Claude Code, Codex, Gemini CLI, ... │──MCP──▶ memory server ──▶ record/ entries, transcripts, contexts, tapes
└──────────────┬───────────────────────┘ │ policy: ├──▶ index SQLite FTS5, BM25
│ model calls │ Rego ├──▶ ledger SQLite, or PostgreSQL
▼ │ └──▶ logs the event log; reads, writes, decisions
egress ──▶ provider or gateway │
metered, spend-limited, contexts recorded └── librarian: curation, checker, canaries, drift
Everything lives under one root, ~/memory unless --root or MEMORY_ROOT says otherwise, and the process touches nothing outside it:
| Path | What |
|---|---|
grants.toml | The perimeter's data: domains and their labels, destinations and their ceilings, [gates], [spend.<destination>], [taps.<name>] for taps and tools (hosted for one a tool server serves), platform = "<domain>", and [ledger] for PostgreSQL |
credentials.env | API keys, LLMAO_KEY, GH_TOKEN, as NAME=value, mode 600; the environment wins |
profiles.toml | Named launches: harness, auth, model, subagents |
prices.toml | USD per million tokens per model, and per CPU-hour and GiB-hour under [resources], for amem cost |
policy/*.rego | Optional: replaces the built-in policy |
record/<domain>/ | The entries, Markdown with frontmatter, never edited in place; .history, .erasures, .transcripts, .contexts and .tapes (re-enactment‘s, the owner’s alone) beside them |
state/ | Operational, and rebuildable but for the event log: log/<domain>.jsonl, the event log, the order of record the index is rebuilt from; index.db, ledger.db, telemetry.db; the read, write and decision logs as JSONL; the quarantine; drift, replay and re-enactment runs |
Rust stable, then:
cargo install --path crates/memory --locked # or `make install`; puts `amem` on the PATH amem init --domain dom-me # a root at ~/memory amem doctor # what this host can run, and what is missing amem # the web launcher, opened in the browser
amem with no command starts the web launcher over the root, or finds the one already running, and opens the browser on a link that pairs it: a code good once, for two minutes, which the page trades for a key of its own. Run it from the project sessions should start in, or give --workdir. The server listens on loopback only and answers nothing past its static pages without a key. amem doctor names which credentials are found where, never their values. LLMAO_KEY alone points at a local LiteLLM on port 4000; a PAT for the Foundation's gateway wants LLMAO_URL=https://llm.apache.org beside it.
The page has a companion: a browser extension in crates/web/companion (Chrome, load it unpacked from chrome://extensions) that fetches for a session with the browser‘s own logins. A [taps.fetch] grant with browser = true sends that tool’s fetches there, so a page you are signed in to answers the session as it would answer you, and no credential goes into a grant. The policy still decides every URL before the browser is asked and every URL that answered before anything is kept, and the extension holds its requests to the session‘s hosts with the browser’s own request rules, so a redirect elsewhere is stopped before it is made. A fetch with render opens the page in a tab instead and reads it as its scripts built it, for a page that is empty without them; the page shows whether the companion is connected. It works only while amem runs with the page open in that browser.
A profile names the flags of a launch, so the name is the whole command. Every harness is one, amem claude, and profiles.toml adds more:
[nightly] harness = "codex" auth = "gateway" model = "qwen3.8-27b" subagents = "board"
amem nightly launches it, amem work nightly works the ledger with it, and a flag typed after the name wins over the file. The launcher runs ten harnesses, Claude Code, Codex, Gemini CLI, Qwen Code, Grok Build, Copilot CLI, OpenCode, Antigravity, Muse and pi, in native Linux namespaces from the harness image once make unpack has put it in place (every one but Antigravity is in it), under WSL containers, or, not yet run on a Mac, under Seatbelt on macOS; auth is key, gateway, or subscription, the harness's own login, which the egress passes through and meters as plan quota. local/README.md is the full guide.
Or point a harness at the memory server alone over stdio, unconfined:
claude mcp add memory -- /path/to/amem --root ~/memory serve --author "agent:claude-code"
The agent gets t0, search, get, write, list, recall, promote, the ledger's tools and transcript_turn, and its writes land at raw trust under the author given.
Most parts are described in local/README.md under their own heading; re-enactment, the event log, the platform domain and the Gofannon bridge so far only in PLAN.md's register.
| Part | What it does | Commands |
|---|---|---|
| The read path | T0, BM25 search with summaries first, one body on get, recall as a cited brief or a pack, prefetch on claim and at fetch | t0, search, get, list, recall, write |
| The task fabric | Tasks with leases and handoffs; a rubric from the L1 strategy ranks along the ledger's edges at admission and in the triage cycle, and workers only claim; subagents filed on the board as children with a continuation | task create, admit, claim-next, complete, release, tree, retry, rescore, stats, work |
| Trust tiers | Raw, curated, verified; verified only by a person who did not propose it; review clocks and decay | promote, approve |
| The perimeter | Rego over grants.toml and policy entries in the record (L0 to L3, enforced once verified, with scoped exceptions); admission, the read filter, the write scan and quarantine, blast-radius gates; every decision logged | policy show, eval, list, lint, quarantine, taint |
| The librarian | A survey of what needs curation, an independent checker, contradiction hunting, canaries, its own telemetry and alarms, a cycle on a budget | librarian, curate, check, canary |
| The egress | Model calls forwarded, metered and timed, spend limits per destination, decision contexts recorded; each run's wall clock, CPU and peak memory kept beside its tokens | launch, usage, cost |
| Sources and replay | Transcripts kept in the record and reached by citation, swept on a clock; frozen-context replay on the recorded contexts; re-enactment of a session at its commit against the tape of its memory calls, the tapes on the transcripts' clock unless pinned | transcript, replay, reenact run, report, tapes, show, pin, unpin |
| The event log | Every entry write through its domain‘s append-only log, ids and digests only; a materializer builds the index from it and replays the ledger’s events | log show, log materialize |
| The platform | Agent definitions, templates, eval suites and harness defaults as artifacts in a platform domain, loaded only once a person verified them | platform list, show, golden --platform |
| Vendor drift | A pinned probe set per model, checked against a baseline, detector by detector | drift probe, drift check |
| Measurement | The read-path claims on this record, a golden recall suite, and the evaluation with memory against without | savings, golden, scripts/eval.py |
| Interchange | Bundles at or below a label, erasure with a stub and a receipt, taps as WASI components | export, import, erase, tap |
| Tools | Fetch and search as taps an agent calls mid-turn: every request decided by the policy at the session's label, answers scanned and kept as sources; or hosted, the same components served by a tool server another launcher calls through its egress, which reaches only the hosts the calling session may and says where it went, kept on the source | tool, source, tool-server; MCP fetch, web_search |
| Gofannon | Its deployed agents as a tool tap on the same terms: listed, run, read back; and a worker that runs one on the ledger's tasks, its result filed as the handoff | gofannon agents, gofannon work; MCP gofannon |
| Traces | OpenTelemetry spans for model calls, reads, policy decisions and task transitions, to any OTLP collector | OTEL_EXPORTER_OTLP_ENDPOINT |
From the command line:
echo "Stopped at step 3. Next: digests." | amem write --kind handoff --title "Import, step 3" amem search digests amem get mem-me-xxxxxxxx amem task create "Finish the import" --priority 5 amem task admit task-me-xxxxxxxx amem work --harness claude # claim the top task, run the harness on it amem recall "how does the import retry?" --provider anthropic amem curate --auth gateway --contradictions # one curation cycle amem quarantine list amem taint mem-me-xxxxxxxx # where a bad entry may have reached amem replay <session> --model gemma4-26b # the same decisions, another model amem reenact run <session> --auth gateway --model qwen3.8-27b --runs 3 # the same task again amem reenact report <session> # each harness and model against the tape amem cost # spend, wall clock, CPU and memory per session and task amem savings # the paper's read-path claims, measured amem savings --judge-provider anthropic # with a small model judging what was "used"
crates/memory/tests/cli.rs runs the paper's first milestone end to end against the built binary, and scripts/conformance.py runs the same steps over MCP against any server exposing the surface (make conformance): a serving layer that passes it serves the harnesses this one serves.
make demo-all HARNESS=claude runs the whole demo in acts on one record, DEMO_ROOT, ~/memory-demo by default, seeded from the Markdown directories in DEMO_FROM. The acts that need a model use local/.virtual-key on llm.apache.org, so they want the network, and act 9 reads api.github.com; ACTS="1 4" runs a subset. Act 7 gives the record a second domain, the platform‘s, so run the acts in order on a fresh record. Each act and each step opens with a rule, a number and a sentence on what it shows; TRANSCRIPT=demo.txt also writes the whole run there as plain text, to read back with docs/demo-narrative.md, the presenter’s cues and a handout keyed to the step numbers. DEMO_FROM is examples/decisions docs by default: a small fictional decision register, which the demo and the evaluation set ask about, and the papers.
make demo-ready HARNESS=claude gets it to a state it can run first: it seeds the record when there is none (RESET=1 starts a demo record over), builds the harness image at its pins when the one unpacked is not and unpacks it into the record, checks that the gateway answers with the key, and shows the logins amem doctor finds. It says what is missing and how to fix it, and ends with the command to run. The demo needs no podman where wslc.exe builds the image; the local stack does, and make local-up now says how to fix a shell whose /run/user/<uid> is missing.
make init installs the pre-commit hook, which runs make check (only the guard‘s tests when a commit stages Markdown alone): formatting, clippy with -D warnings, the workspace’s tests including the browser reader‘s under a Chrome from CHROME or Playwright’s image, the conformance script's own test against a fake server with one defect switched on per run, the guard and docs-only scripts, unsafe-code and taps checks. make verify adds cargo deny, machete, coverage with a 90% floor on lines, and the WebAssembly build. CI has not run since a billing failure, so the hook is the gate, and make verify is run by hand.
| Path | What |
|---|---|
crates/core | Entries, frontmatter, bundles, digests, labels. No I/O |
crates/store | The record over OpenDAL |
crates/index | SQLite FTS5 index, summaries first |
crates/ledger | Tasks, leases, origin dedup, the rubric; SQLite and PostgreSQL |
crates/policy | The grants file, the Rego policy through regorus, the write scan and the gates |
crates/server | The MCP surface, prefetch, transcripts and contexts, the event log, tapes, the platform and sources |
crates/egress | The way out: forwarding, metering, spend limits, recorded contexts |
crates/sandbox | Confinement in Linux namespaces, and a Seatbelt profile for macOS |
crates/mount | The projection as a live mount: the record as files the memory server itself serves, every open of an entry a get, where the host has FUSE |
crates/client | A typed MCP client for the ledger and the record, used by the launcher and an orchestrator |
crates/otel | OpenTelemetry traces over OTLP |
crates/taps | Taps as WASI components, with exactly the access their grant allows; the native fetch behind the same gate |
crates/fetch | What fetch does with a page, shared by its component and the native fetch: the URL split, redirects resolved, HTML made text, the answer shaped |
crates/reader | The core crate for the browser reader, compiled to WebAssembly |
crates/web | The web launcher: sessions in pseudo-terminals, a reading pane, the board, and the companion extension that fetches with the browser's logins |
crates/wslc-api | The WSL containers C API, bound by hand, Windows only |
crates/memory | The binary, amem: the launcher, the librarian, the CLI |
taps/ | The taps: GitHub issues and comments, fetch, search and Gofannon |
probes/drift.toml | The pinned vendor-drift probe set |
images/harness | The harness image: the harnesses, Node, Python and amem, pinned by version, Muse by its release channel |
scripts/ | The demo and its acts, the evaluation, conformance |
docs/ | The paper, the reference stack, the design book, seeding a foundation, proposals for llm.apache.org, the demo's narrative |
As of 12 October 2026, the paper‘s contracts are built and exercised end to end on one laptop, and the demo runs them live against real harnesses on the Foundation’s gateway and a Claude login. A few parts have met only stand-ins so far: the Gofannon bridge and the search tool fakes of their services, and Seatbelt no Mac; the first list above says so with the rest of what is not built, and the list after it is what works only at demo scale. PLAN.md holds the decisions and the register, and the order production backends go in.
What we propose to the Foundation's gateway, llmao at llm.apache.org, and why, from one trace across the wrapper and the gateway to the tool servers the gateway hosts, is in docs/llm-apache-org.md.