docs / agent-memory / getting started

Getting started

Install

No published package yet — install from a source checkout, next to a checkout of fg-agent-id (the only runtime dependency; everything else is stdlib):

python -m venv .venv
.venv/bin/pip install -e ../fg-agent-id -e ".[dev]"

# with the optional MCP stdio server
.venv/bin/pip install -e ../fg-agent-id -e ".[dev,mcp]"

Requires Python ≥ 3.11. The mcp extra pulls mcp>=1.0; only the MCP server imports it — the core never does.

Verify with the test suite (hermetic — no network, no model):

.venv/bin/python -m pytest -q

Two calls

from fg_agent_memory import Memory

memory = Memory("./memory")          # readable directory you can commit to git
memory.remember("John's favorite editor is Zed.")
print(memory.recall("what editor does John use?").as_prompt_block())

That's the whole porcelain: remember writes, recall reads a budgeted, prompt-ready block. Remembering the same content twice deduplicates automatically — the repeat reinforces the record and merges tags instead of duplicating it.

The ghost-memory demo

The problem: you learn X, later learn not-X, and stale X haunts retrieval forever. Watch what happens here instead:

from fg_agent_memory import Memory

memory = Memory("./memory")
a = memory.remember("The staging database is Postgres.")
b = memory.remember("The staging database is not Postgres.")

memory.consolidate()                 # detects the contradiction; neither side dropped
print(memory.recall("staging database").as_prompt_block())
# Relevant memories (query: staging database):
# - The staging database is Postgres. [disputed: one side negates the other]
# - The staging database is not Postgres. [disputed: one side negates the other]

Both sides are surfaced, explicitly marked as disputed. The dispute stays visible until you resolve it, with a reason:

memory.resolve(a.record_id, b.record_id,
               "checked infra: staging moved off Postgres in March")

print(memory.recall("staging database").as_prompt_block())
# Relevant memories (query: staging database):
# - The staging database is not Postgres.

The loser isn't deleted — it is superseded and rides the history trail:

print(memory.recall("staging database", include_history=True).as_prompt_block())
# Relevant memories (query: staging database):
# - The staging database is not Postgres.
# - The staging database is Postgres. [superseded — kept for history]

Under the hood the loser's full version trail is preserved (active → transitional → superseded), with superseded_by pointing at the winner and your reason recorded as state_reason.

What just happened

MCP server

With the [mcp] extra installed, expose a memory directory over stdio:

fg-agent-memory-mcp --path ~/agent-memory

Client configuration:

{ "mcpServers": { "memory": { "command": "fg-agent-memory-mcp",
                              "args": ["--path", "/home/me/agent-memory"] } } }

The server exposes five tools: remember, recall, consolidate, redact, status. There is deliberately no resolve tool — settling a contradiction requires the Python API, keeping dispute resolution a deliberate act. Memory holds one lock around every public operation, so sharing an instance across threads or MCP worker pools is safe.

Where to go next