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

# What is a memory? The OMP data model explained

> A memory is an atomic unit of information the OMP schema stores. Learn every field, how extension fields work, and the full memory lifecycle.

Every piece of information that OMP stores is called a **memory** — a single, self-contained record representing one fact, preference, event, or document chunk about a user. Understanding the memory schema is the foundation for working effectively with any OMP provider.

## What is a memory?

A memory is the atomic unit of remembered information in OMP. It is always scoped to a specific user (`user_id`), optionally grouped into a hierarchical namespace (`scope`), and identified by a provider-assigned `id`. Because OMP is provider-agnostic, the same schema works whether the backing store is Postgres, Mem0, Supermemory, or any other OMP-compatible backend.

## Memory schema

The full JSON representation of a memory looks like this:

```json theme={null}
{
  "id": "mem_abc123",
  "content": "User prefers pnpm over npm",
  "user_id": "kek",
  "scope": "coding/preferences",
  "tags": ["tooling", "nodejs"],
  "source": {
    "app": "cursor",
    "type": "extracted",
    "ref": "session_xyz"
  },
  "confidence": 0.92,
  "valid_from": "2026-04-27T10:00:00Z",
  "valid_to": null,
  "supersedes": ["mem_old456"],
  "embedding_model": "text-embedding-3-small",
  "created_at": "2026-04-27T10:00:00Z",
  "updated_at": "2026-04-27T10:00:00Z"
}
```

### Field reference

| Field             | Type      | Description                                                                                                                                               |
| ----------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string    | Provider-assigned unique identifier. Never set this yourself — the provider returns it after `add()`.                                                     |
| `content`         | string    | The actual remembered information. Free-form text. **Required.**                                                                                          |
| `user_id`         | string    | Identifies which user this memory belongs to. **Required.**                                                                                               |
| `scope`           | string    | Slash-delimited namespace, e.g. `coding/preferences`. Groups related memories.                                                                            |
| `tags`            | string\[] | Free-form labels for additional filtering, e.g. `["tooling", "nodejs"]`.                                                                                  |
| `source.app`      | string    | The application that created this memory.                                                                                                                 |
| `source.type`     | string    | How the memory was created: `extracted` (inferred from conversation), `explicit` (user stated it directly), or `imported` (migrated from another system). |
| `source.ref`      | string    | An opaque back-pointer to the originating session, document, or event.                                                                                    |
| `confidence`      | float     | Provider's estimated accuracy, expressed as a value from `0.0` to `1.0`.                                                                                  |
| `valid_from`      | ISO 8601  | The earliest timestamp at which this memory is considered current.                                                                                        |
| `valid_to`        | ISO 8601  | The expiry timestamp. `null` means the memory has no expiry.                                                                                              |
| `supersedes`      | string\[] | IDs of older memories that this record replaces. Used to chain updates without hard-deleting history.                                                     |
| `embedding_model` | string    | The embedding model used to index the content for vector search.                                                                                          |
| `created_at`      | datetime  | When the record was first stored. **Required.**                                                                                                           |
| `updated_at`      | datetime  | When the record was last modified.                                                                                                                        |
| `status`          | string    | For providers that ingest asynchronously: `queued`, `indexing`, `done`, or `failed`. Synchronous providers return `done` immediately or omit this field.  |

<Note>
  **Required fields:** `id`, `content`, `user_id`, and `created_at` are the only fields a provider must return. All other fields are optional but normalized when present.
</Note>

## Extension fields

OMP supports provider-specific data via `x-<provider>`-prefixed extension fields. Providers use these to expose proprietary metadata — such as graph node IDs or internal embedding versions — without breaking OMP compliance.

```json theme={null}
{
  "id": "mem_abc123",
  "content": "User prefers pnpm over npm",
  "user_id": "kek",
  "scope": "coding/preferences",
  "x-mem0": {
    "graph_node_id": "g_456",
    "embedding_version": "v3"
  },
  "x-supermemory": {
    "space_id": "sp_789"
  }
}
```

The rules for extension fields are:

* Extension fields **must** use the `x-<provider>` prefix (e.g. `x-mem0`, `x-supermemory`).
* They **must not** override or conflict with standard field semantics.
* Any application that does not recognize an extension field **must ignore it** — forward-compatibility is required.
* Extensions **must not** be required for an OMP-compliant client to read or use the memory.

<Tip>
  Extension fields let providers add proprietary features without forking the protocol. Your application code stays portable — unknown `x-` keys are simply ignored.
</Tip>

## Memory lifecycle

A memory follows a straightforward lifecycle from creation to eventual removal:

<Steps>
  <Step title="Add">
    Call `mem.add()` with at minimum `content` and `user_id`. The provider assigns an `id` and returns the stored record. Async providers may return `status: "queued"` while indexing is pending.
  </Step>

  <Step title="Search or list">
    Retrieve memories with `mem.search()` for semantic queries or `mem.list()` for filtered enumeration. Both support `scope` filtering to narrow results to a specific namespace.
  </Step>

  <Step title="Update or supersede">
    Call `mem.update()` to modify a memory in place. Pass `supersedes=[old_id]` on a new `mem.add()` call to create a replacement record while preserving the history chain.
  </Step>

  <Step title="Delete">
    Call `mem.delete(id)` to permanently remove a memory. This is a hard delete — use `supersedes` instead when you want to retain a history trail.
  </Step>
</Steps>

## Code example

Here is a complete `add()` call using multiple optional fields:

```python theme={null}
from openmem import Memory, MemorySource

mem = Memory(provider="postgres", url="postgresql://localhost/omp")

record = mem.add(
    content="User prefers pnpm over npm",
    user_id="kek",
    scope="coding/preferences",
    tags=["tooling", "nodejs"],
    source=MemorySource(app="cursor", type="extracted", ref="session_xyz"),
    confidence=0.92,
)

print(record.id)        # "mem_abc123"
print(record.status)    # "done" for synchronous providers
```

You can also pass `source` as a plain dictionary — the SDK converts it automatically:

```python theme={null}
record = mem.add(
    content="User prefers dark mode",
    user_id="kek",
    scope="ui/preferences",
    source={"app": "my-app", "type": "explicit"},
)
```
