Skip to main content

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.

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:
{
  "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

FieldTypeDescription
idstringProvider-assigned unique identifier. Never set this yourself — the provider returns it after add().
contentstringThe actual remembered information. Free-form text. Required.
user_idstringIdentifies which user this memory belongs to. Required.
scopestringSlash-delimited namespace, e.g. coding/preferences. Groups related memories.
tagsstring[]Free-form labels for additional filtering, e.g. ["tooling", "nodejs"].
source.appstringThe application that created this memory.
source.typestringHow the memory was created: extracted (inferred from conversation), explicit (user stated it directly), or imported (migrated from another system).
source.refstringAn opaque back-pointer to the originating session, document, or event.
confidencefloatProvider’s estimated accuracy, expressed as a value from 0.0 to 1.0.
valid_fromISO 8601The earliest timestamp at which this memory is considered current.
valid_toISO 8601The expiry timestamp. null means the memory has no expiry.
supersedesstring[]IDs of older memories that this record replaces. Used to chain updates without hard-deleting history.
embedding_modelstringThe embedding model used to index the content for vector search.
created_atdatetimeWhen the record was first stored. Required.
updated_atdatetimeWhen the record was last modified.
statusstringFor providers that ingest asynchronously: queued, indexing, done, or failed. Synchronous providers return done immediately or omit this field.
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.

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.
{
  "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.
Extension fields let providers add proprietary features without forking the protocol. Your application code stays portable — unknown x- keys are simply ignored.

Memory lifecycle

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

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

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

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

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.

Code example

Here is a complete add() call using multiple optional fields:
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:
record = mem.add(
    content="User prefers dark mode",
    user_id="kek",
    scope="ui/preferences",
    source={"app": "my-app", "type": "explicit"},
)