Two-stage retention. Recover by default.

Memories don't disappear — they archive first. Expired by TTL, swept by forget, or explicitly archived: every path lands the row in archived_memories with full metadata and a reason. Restore brings it back to live storage. Purge removes it irreversibly. Compliance-ready: soft-delete with an audit trail, then hard-delete on a schedule.

5 archive MCP tools restorable by default auto-purge on schedule audit-friendly
The full archive flow

live → archived → restored or purged.

A memory has three durable states: live (in memories), archived (in archived_memories), or gone (purged or hard-deleted). Five archive MCP tools cover every transition.

Live memories table FTS5 indexed HNSW vector active archived_memories full row + reason + timestamp FTS evicted · vector evicted Gone no row anywhere irreversible memory_gc (TTL) memory_forget (pattern) memory_delete + archive_on_gc memory_archive_restore (selective) memory_archive_purge memory_delete + archive_on_gc=false (rare)
The five archive tools

Surface area, end to end.

memory_archive_listMCP · GET /api/v1/archive
Page through archived rows. Filter by namespace, by archive reason, by date window. Default limit 100.
// MCP — memory_archive_list { "namespace": "alphaone/eng/platform", // optional "limit": 100, // max 1000 "since": "2026-04-01T00:00:00Z" // optional RFC3339 window } → {"archived": [{"id":"…","title":"…","namespace":"…","tier":"mid", "archived_at":"2026-04-26T03:00:00Z","reason":"ttl_expired",…}], "count": 42}
memory_archive_restoreMCP · POST /api/v1/archive/{id}/restore
Move a single archived row back to memories. FTS5 + HNSW are rebuilt for the restored row. Federation fanout propagates the un-archive to peers.
// MCP — memory_archive_restore {"id": "550e8400-e29b-41d4-a716-446655440000"} → {"restored": true, "id": "…", "tier": "mid", "expires_at": null} // expires_at is cleared on restore — so a recently-restored memory doesn't // immediately re-expire from a stale timestamp.
memory_archive_purgeMCP · DELETE /api/v1/archive · IRREVERSIBLE
Permanently remove archived rows. older_than_days is the safety knob — only rows whose archived_at is older than the threshold get purged. None means purge everything in the archive (rare; usually scoped). Federation fanout removes peer copies.
// MCP — memory_archive_purge — typical retention sweep { "older_than_days": 90 // only purge rows archived > 90 days ago } → {"purged": 1247} // purge everything (DANGER — usually wrong) {"older_than_days": null} // Normally wired to a scheduled job: cron daily, sweep > 30/60/90 days // for the relevant compliance regime. Or fold into the curator cycle.
memory_archive_statsMCP · GET /api/v1/archive/stats
Aggregate counts. Total archived rows, per-namespace breakdown, oldest/newest archive timestamps, total size in bytes. Operators wire this to dashboards or use it for retention compliance attestation.
{"total": 8421, "by_namespace": [{"namespace":"alphaone/eng","count":3120}, …], "oldest_at": "2026-01-15T00:00:00Z", "newest_at": "2026-04-27T05:30:00Z", "total_size_bytes": 42_881_024}
memory_forgetMCP · POST /api/v1/memories/forget
Pattern-based bulk archive. Combines a namespace + FTS5 pattern + optional tier filter. Always archives (never hard-deletes) — restorable. The "broom" for cleaning up draft notes, transient observations, or anything matching a known-bad pattern.
// MCP — memory_forget { "namespace": "alphaone/eng/platform", "pattern": "draft notes OR scratch", // FTS5 expression "tier": "short" // optional } → {"forgotten": 42, "dry_run": false}
Two retention models

Soft-delete vs. hard-delete.

Soft-delete (default)

  • archive_on_gc = true in config
  • Expired memories → archived_memories
  • Restorable via memory_archive_restore
  • Audit trail: archived_at, reason, full original row
  • Purge runs on a separate schedule (compliance-driven)
  • Best for: general use, GDPR-compliant retention with a recovery window

Hard-delete

  • archive_on_gc = false in config
  • Expired memories: DELETE FROM memories
  • Not restorable — gone the moment GC runs
  • No archive table audit trail (still have daemon logs)
  • FTS5 + HNSW evicted in the same transaction
  • Best for: regulated environments where TTL means "irreversible erasure" (e.g. PII purge SLAs)
Compliance patterns

Common retention regimes.

# Pattern 1 — "30-day soft-delete + 90-day hard-delete" # Soft-delete on TTL expiry, irreversible after 90 days. archive_on_gc = true auto_purge_archive_days = 90 # Pattern 2 — "GDPR right-to-be-forgotten" # Soft-delete with 14-day recovery window for accidental erasure. # After 14 days, the row is gone with no recovery path. archive_on_gc = true auto_purge_archive_days = 14 # Pattern 3 — "Strict compliance erasure" # TTL expiry triggers immediate hard-delete. No archive, no recovery. # For data covered by erasure-deadline regulations where archive # would be considered retention. archive_on_gc = false # Pattern 4 — "Forensics-friendly" # Indefinite archive. Operator triggers purge manually after evidence # release. Hot path stays clean (FTS/HNSW exclude archived rows) but # nothing leaves the daemon without explicit action. archive_on_gc = true auto_purge_archive_days = 0 # 0 disables auto-purge