Skip to main content
This guide moves a Supermemory export into Synap. It comes with a script that does the mechanical work, and explains the two decisions the script cannot make for you: which scope each container tag belongs to, and what to do about memory quality.
This is the hands-on procedure for Supermemory. For the method every migration shares — scope mapping, configuring your instance, verifying, and cutting over — see How migration works.

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 as org: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

1

Export your data from Supermemory

Download the export from your Supermemory dashboard. You get a single JSON file with a documents section (your original content) and a memories section (the facts Supermemory extracted from it).
2

Check the export is complete

Confirm 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.
3

Configure your Instance for your agent

Extraction quality depends on your Instance’s memory architecture, generated from the use-case file you supply at instance creation. If you created your Instance without one, add it before this import — otherwise your historical data is extracted with generic defaults, and you would re-import later to benefit from a tuned configuration. See Memory Architecture.
4

Have a Synap Instance ready

You need an Instance and an API key; see Quickstart. Note whether your Instance treats customers and users as separate (B2B) or as the same thing (B2C) — you need this in step 2.

Get the script

supermemory_to_synap.py

Download the migration script
map and convert run offline using only the standard library. ingest and verify talk to Synap through the SDK:

The migration, step by step

1

List your container tags

This reads the export and writes a scope_map.json listing every container tag it found, with the number of documents and memories in each:
Where a tag follows Supermemory’s key:value convention, the script pre-fills a suggestion. Everything else is a guess you need to correct.
2

Assign a scope to every tag

Open 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:Also set 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.
Container tags are flat and mutually isolated, so nothing in the export distinguishes one person’s history from company-wide material. A tag left at client scope by mistake becomes readable across your whole account. Step 4 has you check this before anything is sent.
3

Convert the export

This writes files only and contacts no server:Open report.json and confirm scope_breakdown matches what you intended, and that skipped is empty or contains only documents you expect to lose.
4

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.
Read the samples, not just the scope labels. Two things to look for:
  • 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.
Fix scope_map.json and re-run convert until every tag reads correctly. Nothing has been sent yet, so this loop is free.
5

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.
Supermemory’s 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.
6

Pilot one tag

Migrate a single tag first and confirm it behaves before committing the rest.Copy your scope map, keep one representative tag, and convert that alone into its own directory:
Every other tag will be reported as skipped during the pilot conversion. That is expected — they are not in pilot_map.json.Now run steps 9 and 10 against this one tag. Only continue once its isolation and retrieval both check out.
7

Ingest everything

Dry-run first to see what would be sent:
Then run it for real:
The script records progress as it goes, so if it is interrupted you can re-run the same command and it resumes rather than sending anything twice. Each document is submitted with its original Supermemory ID, so re-running a batch does not create duplicates.
Your whole batch is checked against your quota before any of it is accepted. If you hit the limit, the script waits and retries automatically — you do not need to split the files yourself.
8

Verify ingestion completed

Memories are built in the background, so ingestion finishing is not the same as memories being ready.
This waits for every submitted document and reports how many memories were created. Anything that did not complete cleanly is written to 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.
9

Confirm scope isolation

This is the check that catches a wrong scope map. Do it on the pilot, and again after the full migration.Fetch context as one user and confirm nothing belonging to another user comes back:
Choose a search term you know belongs to a different user’s history. Nothing from that user should appear.Then check the reverse for anything you placed at client scope: fetch as two different users and confirm the shared material is retrievable by both. If it reaches only one, that tag is at user scope and needs correcting.
10

Spot-check retrieval coverage

Confirm the facts you expect actually come back:
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.
Do not delete all of ingestion_ids.json and re-ingest the whole export. Ingestion recognises content it has already seen at the same scope for several days, so a blanket re-ingest returns the earlier result instead of rebuilding. The tags you deleted but did not re-scope would stay deleted. Only remove the memories belonging to the tag you are actually fixing.
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:
Step 2 — Re-convert that tag alone. Fix its entry in scope_map.json, then build a single-tag map and convert it into its own directory, exactly as in the pilot step:
Because the tag’s scope has changed, this content is treated as new and is processed rather than matched against the earlier run. Re-run the isolation check from step 9 before moving on.
Keep every output directory until the migration is fully verified. 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 in report.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.
Supermemory’s memory entries are typically a single short sentence. Content that brief carries too little signal to memorise on its own and is discarded on arrival, so importing those strings directly would quietly lose most of them. The script checks length locally and reports anything at risk rather than letting it disappear.

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 / derives links 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.
None of this is a real loss, because re-extracting from your original documents rebuilds the equivalent structure natively — Synap tracks its own memory lineage and relationships as it ingests.

Troubleshooting

Your scope map still has unfilled entries. On a B2B Instance a tag with a 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.
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.
These came from a Supermemory connector that kept no local copy of the text. Re-sync the connector in Supermemory and export again.
The document announces a session date the script could not read. This is treated as an error rather than silently falling back to the upload date, because a wrong date is worse than a skipped document. Report the format and we will add it.
Expected. One document does not become one memory — long conversations are split, and content with nothing worth remembering produces none. Judge the migration by what you can retrieve, not by counting rows.
Re-run the same 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 your conversation_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.