How Supermemory stores memory
Supermemory separates documents (the content you ingest) from memories (short facts extracted from those documents). Both are organised by container tags — flat string identifiers, each with its own isolated namespace. Tags can encode structure by convention, such asorg:acme:user:john, but they are not hierarchical: to Supermemory they are opaque strings. A tag holding one person’s chat history and a tag holding your company handbook look identical.
That last point is the whole migration. Synap organises memory into three scopes — client, customer, and user — and nothing in a Supermemory export records which tag belongs where. You decide that, and this guide has you verify it twice before it becomes permanent.
Before you start
Export your data from Supermemory
documents section (your original content) and a memories section (the facts Supermemory extracted from it).Check the export is complete
truncated is false in both sections. If either says true, the export was cut short at its item limit — re-export before going further. The script warns you, but cannot recover content that is not in the file.Configure your Instance for your agent
Have a Synap Instance ready
Get the script
supermemory_to_synap.py
map and convert run offline using only the standard library. ingest and verify talk to Synap through the SDK:
The migration, step by step
List your container tags
scope_map.json listing every container tag it found, with the number of documents and memories in each:key:value convention, the script pre-fills a suggestion. Everything else is a guess you need to correct.Assign a scope to every tag
scope_map.json and set user_id and customer_id for each tag.You never name a scope directly. Synap works out the scope from which identifiers you provide:isolation to match your Instance: b2b if customers and users are separate, b2c if one customer is one user.In the example above, acme_handbook is company reference material, so its correct mapping is both fields null — client scope — not the user_id the script guessed.Convert the export
report.json and confirm scope_breakdown matches what you intended, and that skipped is empty or contains only documents you expect to lose.Review the scope assignment
report.json gives you totals per scope. Before ingesting, check the assignment tag by tag against the actual content — the totals will look correct even when a tag is in the wrong place.- A tag at client scope whose samples are somebody’s personal conversation. That content is about to become readable by every user on your account.
- A tag at user scope whose samples read like policy, product, or reference documentation. That content will be copied into one person’s memory instead of shared, and no one else will be able to retrieve it.
scope_map.json and re-run convert until every tag reads correctly. Nothing has been sent yet, so this loop is free.Check how timestamps were resolved
report.json includes a dct_sources breakdown:session_header— the original conversation date was recovered from the content. This is what you want.created_at— no original date was available, so the document’s upload date was used instead.
createdAt records when a document was uploaded to Supermemory, not when the conversation happened. If you imported history into Supermemory, those two dates can be years apart. Memories dated from the upload date still work for recall, but questions like “what did I decide last spring?” answer against the wrong timeline.Pilot one tag
pilot_map.json.Now run steps 9 and 10 against this one tag. Only continue once its isolation and retrieval both check out.Ingest everything
Verify ingestion completed
incomplete.json. A partial_success result means the document was processed but some of its memories were not stored; re-ingesting that document is safe.Confirm scope isolation
Spot-check retrieval coverage
baseline.json is useful here: it holds Supermemory’s own extracted memories for each document, so you can sample a few and check they are retrievable from Synap too.Do not compare counts. One document does not become one memory, and the two systems extract differently by design — judge the migration by what you can retrieve.If the scope assignment was wrong
If you discover a misplaced tag after ingesting, correct it one tag at a time. Leave every other tag alone. Step 1 — Delete only the affected tag’s memories.ingest writes ingestion_ids.json in the output directory, and each ingestion’s status names the document it came from, which the batch files tie back to a container tag:
scope_map.json, then build a single-tag map and convert it into its own directory, exactly as in the pilot step:
ingestion_ids.json is the only record of which memories the migration created — without it, telling them apart from memories your live application has written since is difficult.Why the script ingests documents, not memories
A Supermemory export contains both your original documents and the memories Supermemory extracted from them. The script deliberately ingests the documents. Supermemory’s memory entries are short summaries of your content. Importing them means Synap extracts from summaries rather than from what your users actually said — you inherit whatever the original extraction got wrong, and lose the detail it dropped. Because every memory in the export points back to the document it came from, you can re-extract from the original source instead, which is almost always better. There is a second, more important reason to re-extract. Every Synap instance runs its own Memory Architecture Configuration (MACA) — a per-instance memory policy generated from the use-case file you provide when you create the instance. It governs what gets extracted and how, tuned to your agent’s domain and audience. Re-extracting your imported documents through that configuration means your migrated history is processed by the same rules as your live traffic. From the very same source conversations, a support agent’s instance surfaces issues and resolutions, while a companion agent’s instance surfaces preferences and emotional context. Importing Supermemory’s pre-extracted memories would bypass this entirely and leave your historical data shaped by generic rules that do not match your agent — so re-ingestion is not overhead, it is how your old data starts behaving as if your agent created it all along. There is one case where re-extraction is not possible: documents brought in through a Supermemory connector sometimes keep no local copy of their text. Those appear inreport.json as empty content in export. Re-sync the connector on the Supermemory side and export again, or accept the loss.
The extracted memories are still useful — that is what baseline.json is for. Use them to check your coverage after migrating, not as the thing you migrate.
What you gain
- Typed extractions — facts, preferences, episodes, emotions, and temporal events as separate lists, rather than one undifferentiated pool of strings.
- Three scopes, not one flat namespace — client, customer, and user, with roll-up between them, so shared knowledge is stored once instead of copied into every tag.
- Entity resolution across conversations — the same person or product recognised across sessions.
- Context compaction — long histories stay usable without you managing the window.
What you’ll need to adapt
Some Supermemory structure is not present in a dashboard export, and no migration can recover it:- Version history and superseded facts. The export contains only current memories, without their revision chains.
- Relationships between memories. Supermemory’s
updates/extends/deriveslinks are not included. - Inferred-fact flags. There is no way to tell which memories Supermemory derived rather than observed.
- Embeddings. Vectors are never exported by either system; Synap generates its own during ingestion.
Troubleshooting
convert skipped every document
convert skipped every document
user_id but no customer_id is rejected, which is deliberate — it prevents documents landing in an unintended scope. Set customer_id for those tags, or switch isolation to b2c if that matches your Instance.A tag is missing from the scope map
A tag is missing from the scope map
map only lists tags that appear in the export. If a tag exists in Supermemory but has no documents or memories in the file, it will not appear — and nothing needs migrating for it.Documents skipped as 'empty content in export'
Documents skipped as 'empty content in export'
Documents skipped as 'session-date header present but unparseable'
Documents skipped as 'session-date header present but unparseable'
Fewer memories than documents ingested
Fewer memories than documents ingested
Ingestion stopped partway through
Ingestion stopped partway through
ingest command. Completed batches are recorded and skipped, so it resumes rather than re-sending.After you cut over
Work through the shared migration method, which covers the parts common to every source: configuring your instance so extraction quality is good from day one, deciding yourconversation_id strategy, swapping your retrieval call sites, and adding graceful degradation.
Once you are cut over, retire the old service. Do not dual-write — diverging memory state is a harder problem than a clean cutover.