Skip to main content
Every migration onto Synap follows the same shape, regardless of where your data comes from. The per-platform guides (Mem0, Zep, Letta, Supermemory) cover how to get data out of each source and how its concepts map onto Synap. This page is the method they all share — read it once.
For the SDK methods used below — batch_create, idempotency via document_id, per-document status — see the Migration reference.

1. Map your identity model onto scopes

Synap organises memory into three scopes: client, customer, and user. You never name a scope directly — Synap derives it from which identifiers you pass when you ingest: The first task in any migration is deciding, for each slice of your source data, which identifiers it should carry. A source that only has a user_id concept maps cleanly to user scope; shared or company-wide material belongs at customer or client scope. See Memory scopes for the full model.
Getting this wrong is the highest-impact mistake in a migration. Content placed at client scope is readable across your whole account; content wrongly placed at user scope is invisible to everyone but one person. Step 4 has you verify the assignment before it becomes permanent.

2. Configure the Instance for your agent — before you import

Extraction quality depends on your Instance’s Memory Architecture Configuration (MACA) — a per-instance memory policy generated from the use-case file you supply at instance creation. It governs what gets extracted and how, tuned to your agent’s domain and audience. See Memory Architecture. Do this before the bulk import. If you import against an instance with no use-case file, your historical data is extracted with generic defaults, and you would re-import later to benefit from a tuned configuration. The same MACA governs your migrated history and your live traffic, so configuring first is what makes old data behave as if your agent created it.

3. Choose one Instance or many

One Instance per environment (production, staging) is the usual answer. Use a separate Instance per customer only when data residency or the memory architecture genuinely differs between them.

4. Decide your conversation_id strategy

If your source stores conversations or sessions, map each to a stable conversation_id (a UUID per thread). This lets Synap compact long histories and group turns correctly. Sources that store only flat facts don’t need this.

5. Backfill

Ingest through batch_create at mode="long-range":
  • Pass document_created_at from the source’s original timestamp, not today’s date — otherwise every memory is dated to import day and time-relative recall answers against the wrong timeline.
  • Set document_id to the source record’s ID. Ingestion is idempotent on it, so a re-run never duplicates.
  • Prefer ingesting original content (conversations, documents) over a source’s pre-extracted memory strings, so Synap extracts natively instead of inheriting the upstream extraction. Each platform guide says which is available.

6. Pilot one slice

Before migrating everything, run one representative user or tenant end to end — backfill, then the verification in step 7. Only continue once that slice checks out. A mistake caught on one user is cheap; the same mistake across your whole dataset is not.

7. Verify

Two checks, both on the pilot and again after the full run:
  • Scope isolation. Fetch context as one user with a search term you know belongs to a different user, and confirm nothing from that user appears. For client-scoped material, fetch as two users and confirm both can retrieve it.
  • Retrieval coverage. Fetch for facts you know exist and confirm they come back. Do not compare raw memory counts — Synap and your source extract differently by design, so judge by what you can retrieve.

8. If you got a scope wrong, fix it one slice at a time

If you discover misplaced data after ingesting, correct only that slice — delete the memories created for it, then re-ingest it at the right scope.
Do not delete everything and re-run the whole backfill. Ingestion recognises content it has already seen at the same scope for several days and returns the earlier result instead of rebuilding, so a blanket re-run leaves the slices you deleted but did not re-scope permanently gone. Re-ingesting works precisely because the scope changed. Keep the IDs of what you ingested until the migration is verified.

9. Swap your retrieval call sites

Replace your old retrieval calls with sdk.user.context.fetch(...). Synap returns a ContextResponse with typed lists (facts, preferences, episodes, emotions, temporal events) rather than one flat list — iterate over the types your prompt needs. See Response shapes.

10. Cut over

Add graceful degradation so memory never blocks your agent’s hot path, then retire the old service. Do not dual-write — diverging memory state across two systems is a harder problem than a clean cutover.