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

# Memory class: the OMP synchronous client

> The Memory class is the main entry point for the OMP Python SDK. It wraps any supported provider behind a single, consistent interface.

The `Memory` class is the synchronous OMP client. You instantiate it once with a provider string and any provider-specific configuration, then call its methods — `add`, `search`, `get`, `update`, `delete`, `list`, `context`, `audit`, and `capabilities` — the same way regardless of which backend is underneath. Swapping providers requires only changing the constructor arguments; all method calls remain identical.

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

## Constructor

```python theme={null}
Memory(provider="postgres", **config)
```

The `provider` argument is a string that selects the backend adapter. The remaining keyword arguments are forwarded directly to that adapter.

<ParamField path="provider" type="string" required default="postgres">
  Selects the memory backend. Accepted values: `"postgres"`, `"mem0"`, `"supermemory"`, `"letta"`. Pass `base_url=` pointing to any OMP-native HTTP server and the SDK will auto-detect it as a passthrough provider regardless of this string.
</ParamField>

The additional `**config` keyword arguments depend on which provider you choose:

<AccordionGroup>
  <Accordion title="postgres">
    <ParamField path="url" type="string" required>
      PostgreSQL connection string, e.g. `"postgresql://localhost/omp"`. Also accepted as `dsn=`.
    </ParamField>

    <ParamField path="embedder" type="object">
      An embedder instance. Defaults to a lightweight offline embedder that uses zero vectors — suitable for testing without an OpenAI key. Pass `use_openai=True` to use OpenAI embeddings instead, or supply a custom embedder object.
    </ParamField>

    <ParamField path="use_openai" type="boolean" default="false">
      When `True` and no `embedder=` is supplied, initializes an `OpenAIEmbedder` automatically.
    </ParamField>
  </Accordion>

  <Accordion title="mem0">
    <ParamField path="api_key" type="string" required>
      Your Mem0 API key.
    </ParamField>

    <ParamField path="host" type="string" default="https://api.mem0.ai">
      Mem0 API base URL. Override for self-hosted or staging environments.
    </ParamField>
  </Accordion>

  <Accordion title="supermemory">
    <ParamField path="api_key" type="string" required>
      Your Supermemory API key.
    </ParamField>

    <ParamField path="base_url" type="string">
      Override the default Supermemory base URL.
    </ParamField>
  </Accordion>

  <Accordion title="letta">
    <ParamField path="api_key" type="string" required>
      Your Letta API key.
    </ParamField>

    <ParamField path="base_url" type="string">
      Override the default Letta base URL.
    </ParamField>
  </Accordion>

  <Accordion title="passthrough (any OMP-native server)">
    <ParamField path="base_url" type="string" required>
      Base URL of the OMP-native server. When this is provided, the SDK probes `/capabilities`. If the response contains `omp_version`, a passthrough adapter is used and the `provider` string is ignored.
    </ParamField>

    <ParamField path="api_key" type="string">
      API key forwarded as a Bearer token.
    </ParamField>
  </Accordion>
</AccordionGroup>

***

## Methods

### add()

Store a new memory for a user.

```python theme={null}
mem.add(
    content,
    user_id,
    scope=None,
    tags=None,
    source=None,
    confidence=None,
    valid_from=None,
    valid_to=None,
    supersedes=None,
) → MemoryRecord
```

<ParamField path="content" type="string" required>
  The text content of the memory. Must be a non-empty string.
</ParamField>

<ParamField path="user_id" type="string" required>
  Identifies the user this memory belongs to. All subsequent reads and searches are scoped to this user.
</ParamField>

<ParamField path="scope" type="string">
  Slash-delimited hierarchy that organizes the memory, e.g. `"coding/preferences"` or `"health/symptoms"`. Scopes enable fine-grained consent and filtering.
</ParamField>

<ParamField path="tags" type="string[]">
  Free-form labels for filtering, e.g. `["tooling", "nodejs"]`. Supported by all providers; used as a fallback for scopes on providers where `features.scopes == "tags"`.
</ParamField>

<ParamField path="source" type="MemorySource | dict">
  Origin information for the memory. Accepts a `MemorySource` instance or a plain `dict` with `app`, `type`, and/or `ref` keys. See [MemorySource](/sdk/types#memorysource).
</ParamField>

<ParamField path="confidence" type="number">
  A float between `0` and `1` indicating confidence in this memory. Higher values indicate higher certainty.
</ParamField>

<ParamField path="valid_from" type="datetime">
  ISO 8601 datetime at which this memory becomes valid. `None` means immediately.
</ParamField>

<ParamField path="valid_to" type="datetime">
  ISO 8601 datetime at which this memory expires. `None` means no expiry.
</ParamField>

<ParamField path="supersedes" type="string[]">
  A list of memory IDs that this new memory replaces. The referenced memories are retained but semantically superseded.
</ParamField>

Returns a [`MemoryRecord`](/sdk/types#memoryrecord) containing the provider-assigned `id` and all stored fields.

***

### search()

Find memories semantically relevant to a query string.

```python theme={null}
mem.search(query, user_id, scope=None, limit=10, min_score=None) → list[SearchResult]
```

<ParamField path="query" type="string" required>
  The natural-language query to search against stored memories.
</ParamField>

<ParamField path="user_id" type="string" required>
  Restricts results to memories belonging to this user.
</ParamField>

<ParamField path="scope" type="string">
  Restrict results to memories under this scope prefix, e.g. `"coding/*"`.
</ParamField>

<ParamField path="limit" type="number" default="10">
  Maximum number of results to return. Subject to the provider's `limits.max_search_results` cap.
</ParamField>

<ParamField path="min_score" type="number">
  Minimum similarity score (0..1) for a result to be included. Omit to return the top `limit` results regardless of score.
</ParamField>

Returns a list of [`SearchResult`](/sdk/types#searchresult) objects, each containing a `memory` and a `score`.

***

### get()

Fetch a single memory by its provider-assigned ID.

```python theme={null}
mem.get(id) → MemoryRecord
```

<ParamField path="id" type="string" required>
  The provider-assigned memory ID, e.g. `"mem_abc123"`.
</ParamField>

Returns a [`MemoryRecord`](/sdk/types#memoryrecord). Raises [`NotFoundError`](/sdk/errors#notfounderror) if the ID does not exist.

***

### update()

Partially update a memory's fields. Only the fields you provide are changed.

```python theme={null}
mem.update(
    id,
    content=None,
    scope=None,
    tags=None,
    confidence=None,
    valid_to=None,
    supersedes=None,
) → MemoryRecord
```

<ParamField path="id" type="string" required>
  The ID of the memory to update.
</ParamField>

<ParamField path="content" type="string">
  Replacement text content.
</ParamField>

<ParamField path="scope" type="string">
  New scope path to move the memory to.
</ParamField>

<ParamField path="tags" type="string[]">
  Replacement tag list. Replaces all existing tags.
</ParamField>

<ParamField path="confidence" type="number">
  Updated confidence score (0..1).
</ParamField>

<ParamField path="valid_to" type="datetime">
  New expiry datetime.
</ParamField>

<ParamField path="supersedes" type="string[]">
  Additional IDs of memories superseded by this one.
</ParamField>

Returns the updated [`MemoryRecord`](/sdk/types#memoryrecord).

***

### delete()

Permanently delete a memory.

```python theme={null}
mem.delete(id) → None
```

<ParamField path="id" type="string" required>
  The ID of the memory to delete.
</ParamField>

Returns `None` on success. Raises [`NotFoundError`](/sdk/errors#notfounderror) if the ID does not exist.

***

### list()

List memories for a user, optionally filtered by scope, tag, or time range. Results are paginated.

```python theme={null}
mem.list(
    user_id,
    scope=None,
    tag=None,
    since=None,
    until=None,
    limit=50,
    cursor=None,
) → MemoryPage
```

<ParamField path="user_id" type="string" required>
  The user whose memories to list.
</ParamField>

<ParamField path="scope" type="string">
  Filter to memories under this scope prefix.
</ParamField>

<ParamField path="tag" type="string">
  Filter to memories with this exact tag.
</ParamField>

<ParamField path="since" type="datetime">
  Return only memories created at or after this datetime.
</ParamField>

<ParamField path="until" type="datetime">
  Return only memories created before this datetime.
</ParamField>

<ParamField path="limit" type="number" default="50">
  Maximum number of records per page.
</ParamField>

<ParamField path="cursor" type="string">
  Opaque pagination cursor from a previous [`MemoryPage.next_cursor`](/sdk/types#memorypage). Pass `None` to start from the beginning.
</ParamField>

Returns a [`MemoryPage`](/sdk/types#memorypage). When `next_cursor` on the result is non-`None`, pass it back as `cursor=` to fetch the next page.

***

### context()

Retrieve a pre-ranked, prompt-ready text block for injecting into an LLM prompt.

```python theme={null}
mem.context(query, user_id, scope=None, token_budget=500) → ContextBlock
```

<ParamField path="query" type="string" required>
  The user's current query or intent used to rank memories for relevance.
</ParamField>

<ParamField path="user_id" type="string" required>
  The user whose memories to draw from.
</ParamField>

<ParamField path="scope" type="string">
  Restrict context retrieval to memories under this scope.
</ParamField>

<ParamField path="token_budget" type="number" default="500">
  Approximate maximum number of tokens for the returned `text`. The provider fits as many high-scoring memories as possible within this budget.
</ParamField>

Returns a [`ContextBlock`](/sdk/types#contextblock) with a `text` field ready for prompt injection, `citations` linking back to source memories, and an optional `token_count`.

***

### audit()

Retrieve the audit log of operations performed on a user's memories.

```python theme={null}
mem.audit(user_id, app=None, since=None, limit=100) → list[AuditEntry]
```

<Note>
  Audit log support depends on the provider. Check `caps.features.supports_audit` before calling this method.
</Note>

<ParamField path="user_id" type="string" required>
  The user whose audit log to retrieve.
</ParamField>

<ParamField path="app" type="string">
  Filter to entries originating from this app name.
</ParamField>

<ParamField path="since" type="datetime">
  Return only entries at or after this datetime.
</ParamField>

<ParamField path="limit" type="number" default="100">
  Maximum number of entries to return.
</ParamField>

Returns a list of [`AuditEntry`](/sdk/types#auditentry) objects, each describing a single operation.

***

### capabilities()

Retrieve the provider's declared capabilities.

```python theme={null}
mem.capabilities() → Capabilities
```

Returns a [`Capabilities`](/sdk/types#capabilities) object describing which verbs and features the provider supports. The result is cached for the lifetime of the `Memory` instance — the network call is made at most once per session.

Use this to conditionally enable features at runtime:

```python theme={null}
caps = mem.capabilities()
if caps.features.temporal:
    results = mem.search("last week's work", user_id=uid)
if caps.features.supports_audit:
    log = mem.audit(user_id=uid)
```

***

## Full example

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

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

# Check what this provider supports
caps = mem.capabilities()
print(f"Provider: {caps.provider}, OMP version: {caps.omp_version}")

# Add a memory
record = mem.add(
    content="User prefers pnpm over npm",
    user_id="u1",
    scope="coding/preferences",
    tags=["tooling", "nodejs"],
    source={"app": "cursor", "type": "explicit"},
    confidence=0.95,
)
print(f"Stored: {record.id}")

# Search
results = mem.search(
    query="package manager preferences",
    user_id="u1",
    scope="coding/preferences",
    limit=5,
)
for r in results:
    print(f"{r.score:.2f}  {r.memory.content}")

# Fetch a specific memory
fetched = mem.get(record.id)
print(fetched.content)

# Update it
updated = mem.update(
    record.id,
    content="User prefers bun for new projects",
    supersedes=[record.id],
)

# Get prompt-ready context
ctx = mem.context(
    query="set up a new Node project",
    user_id="u1",
    scope="coding/preferences",
    token_budget=400,
)
prompt = f"Relevant memory:\n{ctx.text}\n\nUser: ..."

# List all memories (paginated)
page = mem.list(user_id="u1", scope="coding/preferences", limit=20)
for m in page.items:
    print(m.id, m.content)
if page.next_cursor:
    next_page = mem.list(user_id="u1", cursor=page.next_cursor, limit=20)

# Audit log
if caps.features.supports_audit:
    entries = mem.audit(user_id="u1", limit=10)
    for e in entries:
        print(e.action, e.memory_id, e.timestamp)

# Delete
mem.delete(updated.id)
```

<Note>
  `AsyncMemory` has identical method signatures to `Memory`, but every method is a coroutine and must be awaited. See [AsyncMemory](/sdk/async-memory).
</Note>
