Provenance
An agent that acts on its memory needs to know where that memory came from. So does the person checking the agent’s work. Meaning Memory keeps two kinds of record:
- On each memory: who wrote it, when, and how it got there.
- In its history: every later change to its significance or status, with who made it and why.
Nothing is overwritten without a trace. A memory that is replaced or archived stays in the store with its history; it just stops appearing in search and in the compiled memory file.
What a memory records when it is written
Section titled “What a memory records when it is written”| Field | What it holds |
|---|---|
mem_id |
The memory’s id: 16 hex characters, used by every tool that acts on it. |
writer_agent_id, source_agent |
The agent that wrote it: the agent the server runs as (MM_AGENT). |
writer_tenant_id |
The tenant it was written in (default unless you run several). |
date, created_at |
The day the memory is about, and when it was stored. |
source |
What kind of writer it was: agent, human, or a name of your choosing. |
provenance |
How it entered the store: observed (written by an agent or person), or seed (bulk-loaded from an existing corpus). |
supersedes |
The memories this one replaces, if any. |
Tracing a memory’s history
Section titled “Tracing a memory’s history”mm_provenance shows a memory and everything that has happened to it:
mm_feedback({"mem_id": "83f33219d7033862", "action": "important", "reason": "Renewal date drives the budget"})After the next consolidation applies the feedback:
mm_provenance({"mem_id": "83f33219d7033862"})# Provenance: `83f33219d7033862`
**Text:** Zephyr Logistics renews its support contract every March; the renewal decides next year's budget.**Category:** fact | **Status:** active | **Sig:** 0.95**Date:** 2026-10-03 | **Source:** agent
## Significance Timeline (2 events)
| Time | Event | Old → New | Actor | Reason ||------|-------|-----------|-------|--------|| 2026-10-04T02:55:38 | created | — → sig:0.8 | support-bot | Extracted from agent || 2026-10-04T02:56:52 | sig_adjust | 0.8 → 0.9500000000000001 | support-bot | Renewal date drives the budget |Every change appears here: significance raised or lowered, pinned or unpinned, archived or restored, replaced. Each row has the time, the old and new value, who made the change (the MM_ACTOR name for agent writes) and the reason given. A reason is optional, but it is what makes the history useful later, so ask your agents to give one.
To see the feedback across all of an agent’s memories at once, rather than one memory at a time, use mm_rejections. It lists feedback events newest first, classed as up-votes, down-votes and status changes, with a summary count for the period:
mm_rejections({"window": "24h"}){"events":[{"mem_id":"83f33219d7033862","signal_type":"up_vote","event_type":"sig_adjust", "old_value":"0.8","new_value":"0.9500000000000001","reason":"Renewal date drives the budget", "actor":"support-bot", …}], "total_count":1, "window_summary":{"window":"24h","signal_counts":{"down_vote":0,"up_vote":1,"status_change":0,"other":0}}, …}On Postgres the history is the mm_sig_events table. On the file backend it is sig-events.jsonl in the agent’s workspace. Both travel with an export.
Replacing a memory
Section titled “Replacing a memory”When something changes, write the new memory and name the one it replaces:
mm_remember({"text": "Zephyr Logistics now prefers calls on Thursdays.", "source": "agent", "supersedes": ["ac51561d239e737f"]})Once the new memory is consolidated, the old one is marked superseded. Search returns only the new memory, and the old one keeps its history, including the replacement:
**Status:** superseded
| Time | Event | Old → New | Actor | Reason ||------|-------|-----------|-------|--------|| 2026-10-04T03:01:49 | created | — → sig:0.8 | support-bot | Extracted from agent || 2026-10-04T03:01:51 | superseded | active → superseded | support-bot | Superseded by fbd8456cb7248c3f (written by support-bot) |On the file backend the same change appears in the history as a status_change from active to superseded, with the same reason.
Archiving works the same way on both backends and is recorded like any other change:
| 2026-10-04T03:00:49 | status_change | active → archived | support-bot | One-off request, not a preference |The agent that wrote a memory can bring it back with mm_feedback and restore:
mm_feedback({"mem_id": "ac7f77bfc87e9e6d", "action": "restore", "reason": "Back in use"})| 2026-10-04T03:34:31 | status_change | archived → active | support-bot | Back in use |Who can see a memory’s history
Section titled “Who can see a memory’s history”mm_provenance follows the same access rules as search. On Postgres with an access policy, an agent can trace its own memories and those shared with groups it belongs to; for anything else the answer is “not found”, so it never confirms that another agent’s private memory exists. Not every tool that takes a mem_id checks this yet; Scoping and sharing memory lists which do.