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.
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 throughbatch_create at mode="long-range":
- Pass
document_created_atfrom 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_idto 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.9. Swap your retrieval call sites
Replace your old retrieval calls withsdk.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.