agent-memory
Portable, signed agent memory with a code-enforced fact lifecycle.
Overview
agent-memory is the memory standard in the Fareground agent-standards family: one agent's persistent experience across sessions, as a file the agent owns. Typed records (fact / episode / procedure / rule) carry provenance, confidence, and an explicit lifecycle state, are content-addressed and individually signable with fg-agent-id identities, and travel in a signed, canonical memory file that any runtime can verify. Engines compete on pipelines; the record format is the interop contract.
The differentiator is consolidation as code, not vibes. Most memory systems implement contradiction resolution, promotion, and decay as an LLM freely rewriting a store. Here the fact lifecycle is a deterministic state machine: superseding must name its successor and reason, contradiction produces a transition pair instead of a silent overwrite, rules keep machine-readable evidence links and are flagged the moment their evidence is invalidated, and archival is a terminal state — records are never deleted. The LLM is an operator inside the pipeline whose typed proposals are validated against the machine before anything is written; it is never a free rewriter.
The standard is storage-agnostic by construction: RecordStore, SearchIndex, Embedder, and Operator are adapter ports, every invariant is stateable over the record format alone, and the reference ships in-memory implementations plus a deterministic hash embedder and model-free operators so the whole framework runs and tests with no model and no backend.
Status
Alpha. The library is functional end to end, and the byte-level constructions are pinned by golden wire vectors. The wire format version is pinned at 0.1 and is expected to move before a 1.0 freeze — treat on-disk records and signatures as not yet stable across versions, and expect APIs to change. See CHANGELOG.md for the current state and recent changes.
Install
The package is distributed as fg-agent-memory (import path fg_agent_memory); its only dependency, the sibling fg-agent-id identity library, resolves automatically.
pip install fg-agent-memory
# with the optional MCP stdio server
pip install "fg-agent-memory[mcp]"
Until the first PyPI release lands, install straight from GitHub instead:
pip install "fg-agent-id @ git+https://github.com/Fareground/agent-id.git" \ "fg-agent-memory @ git+https://github.com/Fareground/agent-memory.git"
For development from checkouts of this repo and the agent-id sibling:
python -m venv .venv
.venv/bin/pip install -e ../agent-id -e ".[dev]"
Usage
Two calls. No lifecycle vocabulary required.
from fg_agent_memory import Memory
memory = Memory("./memory") # writes a readable directory you can commit to git
memory.remember("Sandro's favorite editor is Zed.")
print(memory.recall("what editor does Sandro use?").as_prompt_block())
Under the hood that was: a canonical-JSON record directory (FileRecordStore), a SQLite FTS index sidecar, content-address dedup, and auto-consolidation every few remembers. All of it is swappable — Memory(store=..., indexes=..., extractor=..., operators=..., identity=...) — none of it is required.
Want every record and export signed by a persistent fg-agent-id identity? Pass a keyfile path — it is created on first run and reloaded ever after:
memory = Memory("./memory", identity="agent.key")
(An existing KeyPair works too; the string form is load_or_create_keys under the hood.)
The ghost-memory demo
The failure mode this standard exists to kill: you learn X, later learn not-X, and the stale X silently haunts retrieval forever. Here a contradiction is a first-class state — both sides stay visible until you decide, and the loser is retired addressably, never deleted.
from fg_agent_memory import Memory
memory = Memory("./memory")
# Two assertions that cannot both be true.
a = memory.remember("The staging database is Postgres.")
b = memory.remember("The staging database is not Postgres.")
# Consolidation detects the contradiction. Neither side is dropped.
memory.consolidate()
print(memory.recall("staging database").as_prompt_block())
# - The staging database is Postgres. [disputed: one side negates the other]
# - The staging database is not Postgres. [disputed: one side negates the other]
# You name the winner, with a reason that goes on the record.
memory.resolve(a.record_id, b.record_id, "checked infra: staging moved off Postgres in March")
print(memory.recall("staging database").as_prompt_block())
# - The staging database is not Postgres.
# The loser is superseded, not gone — history is one flag away.
print(memory.recall("staging database", include_history=True).as_prompt_block())
# - The staging database is not Postgres.
# - The staging database is Postgres. [superseded — kept for history]
This exact snippet is executable as written. The default detector is deterministic negation-polarity matching over shared content words (it catches "X" vs "not X" and "no X needed" phrasings, morphology included); contradictions with no negation marker need an LLM operator plugged into the contradiction port.
MCP server
Any MCP client gets remember / recall / consolidate / status tools over one memory directory (requires the [mcp] extra):
fg-agent-memory-mcp --path ~/agent-memory
{ "mcpServers": { "memory": { "command": "fg-agent-memory-mcp", "args": ["--path", "/home/me/agent-memory"] } } }
Concepts
porcelain: Memory — remember / recall / consolidate / decay / resolve / export
───────────────────────────────────────────────────────────────────────────────
raw text ──► write stage ────► RecordStore ◄──── consolidation ◄──── decay
(extractor (append-only, dedup → contradiction (mechanical
Operator, versioned → resolution → salience;
create-only) history) promotion → flags) protections
│ reported)
▼
SearchIndex ───► retrieval (state-aware, budgeted) ───► prompt block
│
▼
MemoryFile (signed, portable — the file the agent owns)
Every arrow into the store passes through the lifecycle state machine (active | transitional | superseded | archived); operators — LLM or heuristic — only ever emit typed proposals that are validated first and rejected, never repaired.
The reference ships implementations for every port, so the whole framework runs with no model and no backend:
| Port | Shipped implementations | Bring your own |
|---|---|---|
RecordStore |
FileRecordStore (git-friendly canonical-JSON directory), SQLiteRecordStore (WAL, queryable), InMemoryRecordStore |
any append-only versioned backend |
SearchIndex |
SQLiteSearchIndex (FTS5 keyword), InMemorySearchIndex (cosine over an Embedder) |
vector DBs, hybrid search |
Embedder |
HashEmbedder (deterministic, model-free) |
any embedding model |
Operator (write) |
VerbatimExtractor (porcelain default), HeuristicExtractor (regex) |
LLM extractors |
Operator (consolidation) |
TrigramNearDupOperator, HeuristicContradictionOperator, HeuristicResolutionOperator |
LLM detectors / resolvers — see examples/llm_operator.py |
Every store implementation satisfies one shared port contract; conformance is the contract, not the backend.
The wire format, lifecycle legality table, adapter contracts, retrieval scoring, and pipeline authority rules are normatively specified in spec/SPEC.md (RFC 2119); byte-level constructions are pinned by the golden vectors in spec/vectors.json. Where prose and code disagree, the vectors win.
Project structure
src/fg_agent_memory/memory.py— the porcelainMemoryAPIsrc/fg_agent_memory/records.py—MemoryRecord+MemoryFile, the portable formatsrc/fg_agent_memory/lifecycle.py— the state machine (pure functions)src/fg_agent_memory/ports.py— storage/search/operator ports + reference implssrc/fg_agent_memory/stores/— file + SQLite adapters, FTS keyword indexsrc/fg_agent_memory/retrieval.py— state-aware, budgeted retrievalsrc/fg_agent_memory/pipeline/— write stage, consolidation, decaysrc/fg_agent_memory/mcp_server.py— the MCP stdio server ([mcp]extra)spec/SPEC.md+spec/vectors.json— the wire spec and golden vectorsexamples/— the quickstart and an LLM consolidation operator skeleton
Contributing
Development setup, test commands, and style conventions are in CONTRIBUTING.md.
Built by Fareground · Licensed under Apache-2.0.
Metadata
Release files for fg-agent-memory 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fg_agent_memory-0.2.0.tar.gz | 106.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fg_agent_memory-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 173.6 kB
Release files / fg_agent_memory-0.2.0.tar.gz
| Download URL | fg_agent_memory-0.2.0.tar.gz |
|---|---|
| Size | 106.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1e25b6b94f120d4d0f47a469d094d35ab401daff38816e47cbc247969f27e10
|
|
BLAKE2b-256 checksum How to use checksums |
0bb94a0f0ec0a121893ac24e36a933213b47e7da8c5115b5cb9f6045e01ae0c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.
Transparency logRelease files / fg_agent_memory-0.2.0-py3-none-any.whl
| Download URL | fg_agent_memory-0.2.0-py3-none-any.whl |
|---|---|
| Size | 66.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8913c793e0ac8f8632a601ca0b7ecdfa9dd6d7d21e7ad8d2c170b1182c27d0a7
|
|
BLAKE2b-256 checksum How to use checksums |
3d700b7936ca0113fce0504c2e3a76ea4b0d2ebfb767ce5fb7a74e60e21a7247
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.
Transparency log