> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate Memory Systems with COGX

> Import memories from Mem0, LangMem, Letta, Zep, Graphiti, or another Cognee instance using the COGX exchange format.

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.

<Note>
  Migrating a large amount of data? [Chat with us](https://calendly.com/vasilije-topoteretes/) and we'll help you plan it.
</Note>

## 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 / LangMem / 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](/core-concepts/further-concepts/cogx).

You never construct COGX records by hand. You hand a source object to
`cognee.remember()` and it does the rest:

```python theme={null}
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

The import itself is a single call — construct a `Mem0Source` from your export
and hand it to `cognee.remember()`:

```python theme={null}
result = await cognee.remember(
    Mem0Source(MEM0_MEMORIES, mode="re-derive"),
    dataset_name=DATASET,
)
```

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.

<Accordion title="Simple runnable example" icon="play">
  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](#using-real-data).

  <Note>
    Requires `LLM_API_KEY` to be set (in `.env` or your environment) — both the
    import and `recall()` use the LLM.
  </Note>

  ```python migrate_from_mem0.py theme={null}
  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())
  ```
</Accordion>

A longer, fully runnable version of this walkthrough ships with the repo:
[`examples/tutorials/migrate_from_mem0_tutorial.py`](https://github.com/topoteretes/cognee/blob/dev/examples/tutorials/migrate_from_mem0_tutorial.py).
It imports a bundled sample export
([`examples/tutorials/data/mem0_sample_export.json`](https://github.com/topoteretes/cognee/blob/dev/examples/tutorials/data/mem0_sample_export.json))
in both `preserve` and `re-derive` mode, ingests an inline Python payload,
verifies the result with several `recall()` queries, and iterates over
`Mem0Source.records()` so you can see the raw `COGXMemory` records. Run it
with:

```bash theme={null}
uv run python examples/tutorials/migrate_from_mem0_tutorial.py
```

## 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.

| Mode        | What it does                                                                                                                                        | When to use it                                                                                                                             |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `re-derive` | Ingests 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, LangMem, and Letta.**                                          |
| `preserve`  | Maps 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.**                       |
| `hybrid`    | Keeps 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.** |

```python theme={null}
# 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. `preserve` is also valid for Mem0: each memory is
stored as a raw data item with zero LLM calls — the cheapest way to get the
records in, ready for a later `cognify()` run. Note that the memories aren't
queryable via `recall()` until that extraction runs. The
[runnable tutorial](https://github.com/topoteretes/cognee/blob/dev/examples/tutorials/migrate_from_mem0_tutorial.py)
imports the same export both ways so you can compare.

## 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()`.

<AccordionGroup>
  <Accordion title="LangMem (JSON memory exports)" icon="note-sticky">
    `LangMemSource` reads a LangMem memory export and imports each item as an
    atomic **memory** record. It accepts a file path, an already-parsed list, or a
    dict wrapping the list under `memories`, `results`, `items`, or `data` — any
    other shape raises `ValueError`.

    Per memory:

    * **content** is the first string found among `content`, `text`, `memory`,
      `data`, and `message`; items with none of those are skipped
    * **scope** takes `user_id` (falling back to `namespace`), plus `agent_id`,
      `session_id`, and `run_id` when present
    * **categories** accepts either a single string or a list
    * **timestamps** are read from `created_at` / `createdAt` / `timestamp` and
      `updated_at` / `updatedAt`
    * any **`metadata`** is carried over nested under `langmem_metadata`

    Because LangMem memories are free-form text with no derived graph, it defaults
    to `re-derive` mode.

    ```python theme={null}
    from cognee.modules.migration.sources.langmem import LangMemSource

    await cognee.remember(LangMemSource("langmem_export.json"), dataset_name="langmem_import")
    ```
  </Accordion>

  <Accordion title="Letta / MemGPT (.af agent files)" icon="robot">
    `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.

    ```python theme={null}
    from cognee.modules.migration.sources.letta import LettaSource

    await cognee.remember(LettaSource("my_agent.af"), dataset_name="letta_import")
    ```
  </Accordion>

  <Accordion title="Zep / Graphiti (graph exports)" icon="share-nodes">
    `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.

    ```python theme={null}
    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")
    ```
  </Accordion>

  <Accordion title="Another Cognee instance (COGX archive)" icon="box-archive">
    `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.

    ```python theme={null}
    from cognee.modules.migration.sources.cogx_archive import COGXArchiveSource

    await cognee.remember(COGXArchiveSource("./my_cogx_archive"), dataset_name="restored")
    ```
  </Accordion>
</AccordionGroup>

## 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`:

```python theme={null}
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:

```python theme={null}
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:

```python theme={null}
await cognee.remember(Mem0Source("mem0_export.json"), dataset_name="mem0_import")
```

## Next steps

<CardGroup cols={2}>
  <Card title="remember()" icon="brain" href="/core-concepts/main-operations/remember">
    How import and ingestion work under the hood
  </Card>

  <Card title="recall()" icon="magnifying-glass" href="/core-concepts/main-operations/recall">
    Query your migrated memory
  </Card>

  <Card title="COGX Exchange Format" icon="arrows-rotate" href="/core-concepts/further-concepts/cogx">
    The portable format behind every import and export
  </Card>

  <Card title="Configuration" icon="gear" href="/setup-configuration/overview">
    Configure LLM, embedding, and storage backends
  </Card>
</CardGroup>
