The agent forgets. The memory doesn't.
Context windows are not memory. SyntheticMem moves what an agent learns into a remote store where it survives the session — and, unlike naive RAG-memory, it refuses to let that knowledge be trusted without its receipts.
The common memory pattern stores text, embeds it, returns the nearest matches, and trusts them. The last step is the bug: the recalled note has no source, no sense of whether it is still true, and no way to be appealed. A stale fact gets embedded once and then quietly treated as gospel.
SyntheticMem keeps the first three steps and replaces the fourth. Embeddings are the index, not the truth. Recall returns the content plus its provenance and status, so the agent re-verifies rather than blindly trusting.
Every memory is a row that can be appealed
Provenance
Where the fact came from, when it was learned, when it was last observed, how many times it was compressed (hop_count), and the namespace it held against — all travel with the memory.
Falsifiability
An invalidation tag and a concrete condition that would retire the memory. "A rule that can't be falsified is a religion."
Confidence
A numeric confidence that is preserved — never silently inflated — through recall and consolidation. The doubt is the first thing a careless compressor eats; here it is kept on purpose.
Unattributable by construction
A compressed memory (hop_count > 0) that was never observed again is flagged rather than trusted — the shape of the data admits the doubt.
Supersede, never delete. An old row stays addressable but hidden from default recall.
- A sourced save lands as a fact. An unsourced save is demoted to hypothesis — "do not execute from this."
- A hypothesis is promoted back to fact only by a fresh observation (memory_observe), never by usage count.
- memory_supersede writes a new row and retires the old one (kept, hidden). memory_forget tombstones with a reason. Nothing is hard-deleted.
Consolidation that preserves the doubt
memory_consolidate clusters live episodic rows by namespace (two or more per cluster) into a single semantic row. The doubt-preserving facets are computed in code, not by the model: confidence is the minimum of its sources (never inflated), invalidation tags and conditions are a deduped union, the result is a hypothesis (derived ≠ fact), and the source rows are superseded, not deleted. A summary that loses the maybe is a eulogy, not a record.
What runs underneath
- Transport: Streamable-HTTP JSON-RPC 2.0 at POST /api/mcp (protocol 2024-11-05), with a REST v1 mirror.
- Store: PostgreSQL 16 + pgvector — a native vector(768) column with an HNSW cosine index, SQL-prefiltered by agent, namespace and status before the ANN top-k.
- Embeddings: local Ollama nomic-embed-text (768-dim) — your memory text is embedded on the server, not sent to a third-party embedding API.
- Isolation: per-agent agt_ keys (hashed at rest) and a fail-closed per-agent scope, with namespace sub-scoping inside an agent.