Getting Started
Migrating from Supermemory
Move from container tags and document ingestion to explicit end-user scopes and durable memory records. The mapping is mostly about splitting one string into a scope and a set of tags.
Key differences
| Supermemory | MemorySync | What it means for your code |
|---|---|---|
containerTag string carrying scope and labels | X-End-User-ID header plus tags | Isolation stops being a naming convention you have to keep consistent. |
| Documents, chunked on ingest | Memory records, stored as written | A retrieval result is the record you wrote, not a fragment of one. |
queued then done | Durable when add returns | No polling loop, and no window where a write is not yet retrievable. |
search.execute({ q, containerTag }) | POST /memory/query | Scope comes from the header; filters stays yours. |
| Chunks with scores | Whole records with metadata | Nothing to stitch back together before you show or use it. |
| URLs, PDFs, and files ingested directly | You extract, then store what matters | A deliberate tradeoff — see the note below. |
Install the client
python -m pip install memorysync==1.1.1
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="user-123",)
Operation by operation
client.memories.add(content="User prefers dark mode",container_tags=["user_alice", "preferences"],)
results = client.search.execute(q="user preferences",container_tag="user_alice",)
Move your existing data
1
Decide what each container tag meant
This is the only decision that matters. A tag like user_alice is a scope and becomes X-End-User-ID. A tag like preferences is a label and becomes an entry in tags. A tag that mixed both, such as user_alice_preferences, has to be split.
2
Export your documents
Pull your documents out with their container tags and metadata, and keep the export on disk. It is your rollback.
3
Import one scope at a time
import json, osfrom memorysync import MemorySyncClientwith open("supermemory_export.json") as handle:documents = json.load(handle)# map the tag that identified a user onto the scope headerdef split_tags(tags: list[str]) -> tuple[str, list[str]]:scope = next((t for t in tags if t.startswith("user_")), "unknown")return scope.removeprefix("user_"), [t for t in tags if t != scope]batches: dict[str, list[dict]] = {}for document in documents:end_user_id, labels = split_tags(document.get("containerTags", []))if not document.get("content"):continuebatches.setdefault(end_user_id, []).append({"text": document["content"],"source": "import","tags": labels,"metadata": {"supermemory_id": document.get("id")},})for end_user_id, items in batches.items():client = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id=end_user_id,)result = client.bulk_add(items, deduplicate=True)print(end_user_id, result.created, "created,", result.skipped, "skipped")
4
Verify the boundary
Query as one migrated end user and confirm only their memories return. If a container tag was ambiguous, this is where you find out, before it matters.