Skip to main content
Already storing memories in another system? Cognee can import them directly into a knowledge graph — no manual reformatting. This guide explains the COGX format that makes that possible, walks through a runnable Mem0 example, and lists every other source you can import from.
Migrating a large amount of data? Chat with us and we’ll help you plan it.

What is COGX?

COGX (the Cognee eXchange format) is a common shape that all memory imports are translated into before they enter Cognee. Instead of writing one importer for every memory tool, Cognee defines a single intermediate format and a single loader:
Mem0 / Letta / Zep / Graphiti  ──►  COGX records  ──►  cognee.remember()  ──►  knowledge graph
            (a "source")        (common shape)      (one loader)         (queryable memory)
A source is a small adapter that reads one provider’s export and emits COGX records. Because every source produces the same COGX shape, the rest of the pipeline — loading, graph extraction, storage — is identical no matter where your data came from. COGX is also what cognee.export() writes, so the same format powers backup, restore, and Cognee-to-Cognee migration. For a full breakdown of the format and its record kinds, see COGX Exchange Format. You never construct COGX records by hand. You hand a source object to cognee.remember() and it does the rest:
import cognee
from cognee.modules.migration.sources.mem0 import Mem0Source

await cognee.remember(Mem0Source("mem0_export.json"), dataset_name="my_memories")

Quickstart: import from Mem0

This script uses a small inline sample in the exact shape Mem0 returns, so you can run it without a Mem0 account. Swap in real data using the patterns at the bottom of this page.
Requires LLM_API_KEY to be set (in .env or your environment) — both the import and recall() use the LLM.
migrate_from_mem0.py
import asyncio

import cognee
from cognee.modules.migration.sources.mem0 import Mem0Source

DATASET = "mem0_import"

# A sample Mem0 export — exactly the shape Mem0 produces: a list of memory
# objects (the OSS `client.get_all()` result, or the items inside a platform
# export's {"results": [...]} wrapper).
MEM0_MEMORIES = [
    {
        "id": "0a1b2c3d",
        "memory": "Alex is a senior backend engineer who owns the payments service.",
        "user_id": "alex",
        "categories": ["work", "role"],
        "created_at": "2026-05-01T10:00:00Z",
    },
    {
        "id": "1b2c3d4e",
        "memory": "Alex prefers Python and is wary of premature microservices.",
        "user_id": "alex",
        "categories": ["preferences"],
        "created_at": "2026-05-02T09:30:00Z",
    },
    {
        "id": "2c3d4e5f",
        "memory": "The payments service had a timeout incident caused by a missing DB index.",
        "user_id": "alex",
        "categories": ["incident"],
        "created_at": "2026-05-10T14:15:00Z",
    },
]


async def main() -> None:
    # Start clean so the example is reproducible.
    await cognee.forget(everything=True)

    # Import the Mem0 memories. mode="re-derive" (the default) runs Cognee's own
    # extraction over each memory, building a real entity/relationship graph.
    print(f"Importing {len(MEM0_MEMORIES)} Mem0 memories...")
    result = await cognee.remember(
        Mem0Source(MEM0_MEMORIES, mode="re-derive"),
        dataset_name=DATASET,
    )
    print(f"Done: {result}\n")

    # Query the migrated memory.
    for question in (
        "What does Alex work on?",
        "What caused the payments service incident?",
        "What are Alex's technical preferences?",
    ):
        answer = await cognee.recall(question, datasets=[DATASET])
        print(f"Q: {question}")
        print(f"A: {answer}\n")


if __name__ == "__main__":
    asyncio.run(main())
That’s the whole migration: read the export with Mem0Source, pass it to cognee.remember(), then query with cognee.recall(). Your Mem0 memories are now a queryable Cognee knowledge graph.

Import modes

Every source accepts a mode argument that controls how much work Cognee does on import. Pick it based on whether your source already has an extracted graph and how much you want to spend on LLM calls.
ModeWhat it doesWhen to use it
re-deriveIngests the raw content and runs Cognee’s own extraction (cognify). The source’s own graph (if any) is ignored.You want the richest graph and don’t mind the LLM cost. Default for Mem0 and Letta.
preserveMaps the source’s already-extracted entities and facts straight into the graph with zero LLM calls. Raw content is stored but not re-processed.Your source already has a good graph, or you want a fast, free, deterministic import. Default for COGX archives.
hybridKeeps the source’s graph and re-cognifies the raw content.Your source has both verbatim content and a derived graph (e.g. Zep/Graphiti) and you want the best of both. Default for Zep/Graphiti.
# Override the default for any source:
COGXArchiveSource("./archive", mode="hybrid")  # preserve the graph and re-cognify raw content
ZepSource(data, mode="re-derive")    # ignore Zep's graph, re-extract from scratch
Mem0 exports contain short memory records, not a graph, so use the default re-derive mode for Mem0 imports when you want Cognee to build a knowledge graph from those memories.

Other sources you can import from

Every source has the same interface — construct it from a file path (or in-memory data) and pass it to cognee.remember().
LettaSource reads a Letta Agent File (.af, a JSON serialization of one or more agents) and imports:
  • core memory blocks → memory blocks in the graph
  • message history → one conversation episode per agent
  • archival memory → one document per passage
The parser tolerates key-name differences across Letta versions.
from cognee.modules.migration.sources.letta import LettaSource

await cognee.remember(LettaSource("my_agent.af"), dataset_name="letta_import")
ZepSource reads a JSON export of a Zep or Graphiti knowledge graph and imports:
  • episodes (verbatim ingested content)
  • entity nodes
  • relation edges (“facts”), including their bi-temporal valid_at / invalid_at validity windows
It defaults to hybrid mode because Zep/Graphiti keep both verbatim episodes and a derived graph.
from cognee.modules.migration.sources.zep import ZepSource, GraphitiSource

# Zep export
await cognee.remember(ZepSource("zep_export.json"), dataset_name="zep_import")

# OSS Graphiti export (same shape; produce the JSON from a Cypher dump of
# EntityNode / EpisodicNode / RELATES_TO records)
await cognee.remember(GraphitiSource("graphiti_export.json"), dataset_name="graphiti_import")
COGXArchiveSource re-imports an archive produced by cognee.export(..., format="cogx"). This is the restore half of backup/restore and the receiving end of Cognee-to-Cognee migration. It defaults to preserve mode (zero-LLM), because a Cognee archive already carries a fully extracted graph.
from cognee.modules.migration.sources.cogx_archive import COGXArchiveSource

await cognee.remember(COGXArchiveSource("./my_cogx_archive"), dataset_name="restored")

Export: Cognee → COGX

Migration runs both ways. cognee.export() writes a dataset’s graph to a portable COGX archive that you can back up, move to another Cognee instance, or re-import later with COGXArchiveSource:
import cognee

# Write a COGX archive directory
await cognee.export(dataset="mem0_import", format="cogx", destination="./my_cogx_archive")

# ...later, on any Cognee instance:
from cognee.modules.migration.sources.cogx_archive import COGXArchiveSource
await cognee.remember(COGXArchiveSource("./my_cogx_archive"), dataset_name="restored")

Using real data

The Mem0 example above uses an inline sample. Here’s how to point any source at real data. From a provider’s client (live API). Fetch with the provider’s own SDK and pass the response straight in — sources accept already-parsed Python lists and dicts, not just file paths:
from mem0 import MemoryClient
from cognee.modules.migration.sources.mem0 import Mem0Source

client = MemoryClient(api_key="...")
memories = client.get_all(user_id="alex")      # a list (or {"results": [...]})
await cognee.remember(Mem0Source(memories), dataset_name="mem0_import")
From an exported file. Point the source at the export on disk:
await cognee.remember(Mem0Source("mem0_export.json"), dataset_name="mem0_import")

Next steps

remember()

How import and ingestion work under the hood

recall()

Query your migrated memory

COGX Exchange Format

The portable format behind every import and export

Configuration

Configure LLM, embedding, and storage backends