MemorySync
Getting Started

Migrating from Mem0

Move your memories and your calling code from Mem0 to MemorySync. The import runs through one endpoint, and you can keep both providers live until your own queries look right.

Key differences

Mem0MemorySyncWhat it means for your code
user_id passed per callX-End-User-ID request headerIsolation is enforced by the API, so a read cannot be widened by a forgotten filter argument.
filters={"user_id": ...} on searchScope header, not a filterfilters is left free for your own tags and metadata.
messages=[...] extracted into factstext — one statement per recordYou decide what is worth storing, so what comes back is what you put in.
top_kkSame meaning, shorter name.
Org and project ids on the clientX-Project-ID request headerOne key can serve several projects without new client instances.
No update on the managed APIPATCH /memory/{memory_id}Tags, importance, metadata, and source can be corrected in place.

Install the client

python -m pip install memorysync==1.1.1
import os
from memorysync import MemorySyncClient
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="user-123",
)

Operation by operation

client.add(
messages="User prefers dark mode",
user_id="alice",
)
results = client.search(
query="user preferences",
filters={"user_id": "alice"},
top_k=5,
)
memories = client.get_all(filters={"user_id": "alice"})
client.delete(memory_id="mem_123")

Where Mem0 returns an extracted fact it decided to keep, MemorySync returns the record you wrote. If you were reconciling extraction output against your own database, that reconciliation step disappears.

Move your existing memories

  1. 1Export from Mem0. The dashboard export is the least code; the export API works too, and returns records with id, content, metadata, and created_at.
  2. 2Group the exported records by their Mem0 user_id. Each group becomes one MemorySync end-user scope.
  3. 3Import each group with bulk add, keeping the original id in metadata so the two systems stay reconcilable.
  4. 4Read the per-item results. A 207 with skipped items is a normal outcome, not a failure.
import json, os
from memorysync import MemorySyncClient
with open("mem0_export.json") as handle:
export = json.load(handle)
# one MemorySync client per end user keeps the scope explicit
by_user: dict[str, list[dict]] = {}
for record in export["memories"]:
if record.get("content"):
by_user.setdefault(record.get("user_id", "unknown"), []).append(record)
for user_id, records in by_user.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=user_id,
)
result = client.bulk_add(
[
{
"text": record["content"],
"source": "import",
"metadata": {"mem0_id": record.get("id"), **(record.get("metadata") or {})},
}
for record in records
],
deduplicate=True,
)
print(user_id, result.created, "created,", result.skipped, "skipped")

Worth knowing before you cut over

  • Writes are durable when add returns. There is no event id to poll and no queued state to wait through before a memory is retrievable.
  • Nothing is silently rewritten. A record changes only when you call update or forget, so your memory count reflects your own decisions.
  • A memory belongs to one end user. Cross-user reads are not a filter you have to remember to apply.
  • Retrieval returns whole records with their metadata, not fragments to reassemble.
  • Keep your Mem0 export until you have run a full usage cycle here. It is the cheapest rollback available.

Next steps