Not every memory provider supports the same features. One backend may offer full vector search and temporal queries; another may support only basic keyword lookup. OMP solves this with a capabilities system: every provider declares exactly what it supports, and your application can inspect that declaration at runtime to decide how to behave.
What are capabilities?
Capabilities are a structured declaration of the features, verbs, and limits a provider exposes. They are returned by the GET /capabilities endpoint on any OMP server, and surfaced through mem.capabilities() in the SDK. Rather than hardcoding assumptions about what a provider can do, you query capabilities once and let that answer drive your code path.
Querying capabilities
from openmem import Memory
mem = Memory(provider="mem0", api_key="...")
caps = mem.capabilities()
print(caps.provider) # "mem0"
print(caps.omp_version) # "0.1"
print(caps.verbs) # ["add", "search", "get", "update", "delete", "list", "context"]
print(caps.features.vector_search) # True
print(caps.features.temporal) # True
print(caps.features.scopes) # "native"
print(caps.limits.rate_limit_per_minute) # 600
The SDK caches the capabilities response per session. Subsequent calls to mem.capabilities() return the cached result without any additional network round-trip.
Capabilities response structure
The raw JSON response from GET /capabilities looks like this:
{
"omp_version": "0.1",
"provider": "mem0",
"verbs": ["add", "search", "get", "update", "delete", "list", "context"],
"features": {
"vector_search": true,
"keyword_search": true,
"graph_queries": true,
"temporal": true,
"scopes": "native",
"max_content_length": 10000,
"supports_e2e": false,
"supports_audit": true,
"supports_supersession": true
},
"limits": {
"rate_limit_per_minute": 600,
"max_search_results": 100
}
}
Field reference
Top-level fields
| Field | Type | Description |
|---|
omp_version | string | The OMP spec version the provider implements. Its presence signals that the provider speaks OMP natively; the SDK uses a passthrough adapter when this field is present. |
provider | string | A human-readable identifier for the provider, e.g. "mem0" or "postgres". |
verbs | string[] | The list of OMP verbs this provider supports. Common values: "add", "search", "get", "update", "delete", "list", "context", "audit". |
features object
| Field | Type | Description |
|---|
vector_search | boolean | Whether the provider supports semantic/vector similarity search. |
keyword_search | boolean | Whether the provider supports exact keyword or full-text search. |
graph_queries | boolean | Whether the provider supports graph-based relationship queries. |
temporal | boolean | Whether search supports time-range filters like since and until. |
scopes | string | How scopes are implemented: "native" (first-class), "tags" (simulated via tag filtering), or "none" (not supported). |
max_content_length | integer | Maximum number of characters allowed in the content field of a single memory. |
supports_e2e | boolean | Whether end-to-end encryption is supported (deferred to OMP v0.2). |
supports_audit | boolean | Whether the audit verb is available on this provider. |
supports_supersession | boolean | Whether the provider tracks memory lineage via supersedes chains. |
limits object
| Field | Type | Description |
|---|
rate_limit_per_minute | integer | Maximum number of API requests the provider accepts per minute. |
max_search_results | integer | Maximum value you can pass for the limit parameter in search() or list(). |
Capability-aware code
The recommended pattern is to query capabilities once at startup and then branch on the features you need:
from datetime import datetime, timezone
from openmem import Memory
mem = Memory(provider="mem0", api_key="...")
caps = mem.capabilities()
uid = "u1"
# Use temporal list when the provider supports it
if caps.features.temporal:
page = mem.list(
uid,
since=datetime(2026, 4, 20, tzinfo=timezone.utc),
)
else:
# Fall back to semantic search
results = mem.search("what did I work on last week?", user_id=uid)
You can apply the same pattern to guard any feature-dependent code path:
# Guard graph queries
if caps.features.graph_queries:
# Use graph-aware prompting strategy
...
# Guard audit log access
if caps.features.supports_audit:
log = mem.audit(uid, limit=20)
# Respect content length limits before adding
if caps.features.max_content_length:
content = content[:caps.features.max_content_length]
Because capabilities are cached per session, it is safe to call mem.capabilities() inside a helper function without worrying about repeated network overhead.