# xmemory vs Supermemory

> Supermemory is a managed context stack that ingests almost anything, extracts facts into a temporal graph, and serves profiles and search. xmemory is a memory engine that executes a schema you own, so what is stored, how it updates and what it answers are specified rather than steered.

Canonical page: https://xmemory.ai/compare/supermemory/

Supermemory is the broadest product on these pages. It takes documents, PDFs, audio, URLs and
connector feeds, chunks and indexes them for retrieval, and in a second pass extracts memories
into a graph that knows which fact is latest. It ships profiles, a managed RAG, a memory tool for
Claude, and an open-source benchmark harness. If the question is "one API for all my context",
Supermemory is a fair answer. The question this page is about is narrower: when an agent's memory
has to behave as state, what does each system let you specify, and what does it decide for you?

Documentation reviewed 23 October 2026: Supermemory
[how it works](https://supermemory.ai/docs/concepts/how-it-works),
[graph memory](https://supermemory.ai/docs/concepts/graph-memory),
[customization](https://supermemory.ai/docs/concepts/customization),
[user profiles](https://supermemory.ai/docs/concepts/user-profiles),
[MemoryBench](https://supermemory.ai/docs/memorybench/overview); on our side
[How xmemory works](https://xmemory.ai/integration-overview/), [XMD](https://xmemory.ai/xmd/) and the [API](https://xmemory.ai/api/).

## What Supermemory does

Ingestion runs a fixed pipeline: extract text (OCR, transcription, page fetch), contextual
chunking, embedding, indexing. Chunks are searchable as soon as a document is done; memories come
from a second phase the docs call *dreaming*, which batches related documents and extracts facts
into "a fact-based temporal graph that has vector, FTS, and graph built in". Facts relate to each
other as *updates* (the newer fact wins and carries `isLatest`, history kept for audit), *extends*
(both stay valid) and *derives* (a fact inferred across several memories that was never stated).
Forgetting is automatic: temporary facts expire, contradictions resolve to the newest, chatter is
filtered, and memory types decay differently, with preferences strengthening on repetition.

A *profile* is an automatically maintained set of facts per namespace: a *static* collection of
long-lived facts, a *dynamic* collection of recent context, and topic *buckets* (a default
`preferences` bucket plus any you define by name and description) into which a classifier sorts
extracted facts. Each entry is a natural-language sentence with an id. *Namespaces* are hard
tenancy boundaries with scoped API keys; metadata gives soft filters inside one. Extraction is
steered by two free-text fields, an organisation-wide `organizationalContext` and a per-namespace
`supportingContext`, and existing memories are not reprocessed when they change.

## Where xmemory is stronger

**Specified, not steered.** Supermemory's control over extraction is prose: context strings that
guide the extractor, and bucket descriptions that steer a classifier afterwards, with the docs
saying nothing about how strictly either is followed. An
[XMD schema](https://xmemory.ai/xmd/) is executable. Field descriptions are the extraction instructions, enums
bound the values, keys decide identity, relation keys fix cardinality, and `extract` lets you test
a change against awkward inputs before you trust it. When the extractor meets "the plan is now
Pro", it is not interpreting a hint about what matters; it is filling `plan` on the customer's
record from an allowed set. The long version is
[Schema as the Core of Reliability](https://xmemory.ai/schema-as-the-core-of-reliability/).

**Supersession by key, not by judgement.** Supermemory's `updates` relation is the closest thing
to xmemory's write path among these products: the newest fact wins and the old one stays for
audit. The difference is who decides that two facts are about the same thing. In Supermemory the
engine infers relatedness; in xmemory the schema states it, as a primary key, and a mention that
carries the key hits the record every time. The same goes for *derives*: Supermemory will infer
facts across memories on its own initiative and lets you approve, decline or undo low-confidence
ones afterwards; xmemory's grounded inference is bounded by what the descriptions license. Those
controls review generated inferences; schema descriptions specify the intended extraction
beforehand. The
[Why page](https://xmemory.ai/why/) has the worked "who is Kevin's manager" case.

**State, not a profile.** A Supermemory profile is a set of natural-language facts, sorted into
static, dynamic and topic buckets, that you put in the prompt. It is useful, and each entry is a
sentence rather than a typed record. xmemory keeps the facts as typed records over SQL, so
"which customers are on Pro and overdue", "how many open commitments does this person have",
and "which required fields are still empty" are queries over all matching stored records rather
than a selection of facts, and the rows can go to code instead of a model. Lifecycle is explicit
in the same way: a fact that should stop being current gets a `status` or a date the schema
declares, instead of a decay rule the engine applies to a memory type.

**Breadth is theirs; depth is ours.** Supermemory ingests files, audio and connector feeds and
runs a managed RAG beside the memory; xmemory takes text and structured input and does one thing
with it. If you need a single managed stack for documents *and* recollection, Supermemory covers
more surface. If the memory is the thing a workflow acts on, the narrower contract is the point.
(Audio, files and connectors still reach xmemory, through whatever already turns them into text.)

**Tenancy, then fields.** Namespaces with scoped keys are a clean hard boundary, and metadata is
a workable soft filter. Those controls do not establish field-level permissions within a memory
record. xmemory scopes reads and writes by field, with lineage on every stored value, so one
instance can serve several agents and teams with different views of the same records.

**The measurements.** Supermemory's own [MemoryBench](https://supermemory.ai/docs/memorybench/overview)
runs LoCoMo, LongMemEval and ConvoMem across providers, which is a good contribution and measures
recall over conversations. On our four-domain end-to-end benchmark (updates, deletions, relation
changes, aggregation, negative queries) Supermemory scored 80.49 F1 against xmemory's 97.10. On
the Splitwise task, where every read needs arithmetic, it scored 73.75%, the best of the
third-party systems we ran, against 95.2%
([white paper](https://arxiv.org/abs/2604.27906); numbers also in
[Chasing AI memory SOTA](https://xmemory.ai/chasing-sota-in-ai-memory/)). The paper's
[setup](https://arxiv.org/html/2604.27906v1#S8.SS3): the managed service, hybrid mode, a 0.7
decision threshold tuned toward precision, every write awaited to completion including
asynchronous processing. These results measure the tested configuration. They show a substantial
gap on these workloads, but do not isolate its cause or establish the best result achievable with
tuned context strings.

## Choosing

Choose Supermemory when you want one managed service for ingesting everything, a RAG over the
documents and a profile over the person, and the main consumer is a model reading context. Choose
xmemory when the memory is written by agents, read by code, corrected often and counted on, and
you would rather state the rules than tune the hints. The facts Supermemory extracts for you are a
reasonable first draft of what your schema should declare.

## Supermemory's memory types as an XMD schema

Supermemory sorts memories into facts, preferences and episodes and applies a different decay
rule to each. The schema below models a slice of that, a person's preferences and commitments,
with identity and lifecycle as fields you can query rather than behaviour you infer from a type.

```yaml
xmd_version: v1
title: Personal context
description: What is known about a person, their stated preferences, and the commitments they have mentioned, as current state.
objects:
  Person:
    description: The person whose context this is. One record per person.
    fields:
      user_id: { type: str, required: true, description: "The identifier supplied with the input; do not invent one." }
      name: { type: str, required: false }
    primary_key: [user_id]
  Preference:
    description: >-
      One stated preference on one specific dimension. A new statement on the same
      dimension replaces the value; statements on other dimensions are separate
      records. Extract only preferences that fit a listed dimension; skip the rest.
    fields:
      user_id: { type: str, required: true }
      dimension:
        type: str
        required: true
        enum: [seat_position, overnight_flights, meeting_start_time, reply_length, diet]
        description: >-
          The specific thing the preference is about. "Window seats" is seat_position;
          "no red-eyes" is overnight_flights; "nothing before 10" is meeting_start_time.
      category:
        type: str
        required: false
        enum: [travel, schedule, communication, food]
        description: The broad topic the dimension belongs to, for filtering.
      value: { type: str, required: true }
    primary_key: [user_id, dimension]
  Commitment:
    description: >-
      One occurrence of something the person said they will do or must attend. Each
      distinct occurrence is its own record: a second chemistry exam is a new
      Commitment, not an update to the first. A later mention of the same occurrence
      (same thing, same or rescheduled date, referred to as "the exam" or "it")
      updates that record: a new date changes due_on, "done" or "cancelled" changes
      status. Nothing expires on its own.
    fields:
      user_id: { type: str, required: true }
      occurrence_id:
        type: str
        required: true
        description: >-
          A stable handle for this occurrence: the thing plus the first date
          mentioned, e.g. chemistry-exam-2026-11-04. Reuse it when later text refers
          to the same occurrence, even if the date moves. This example covers dated
          commitments with at most one occurrence of a thing per date; an undated
          commitment ("I need to book a dentist appointment") or two occurrences on
          one day need a different identity rule, such as a sequence suffix.
      what: { type: str, required: true, description: "Short noun phrase, e.g. \"chemistry exam\"." }
      due_on: { type: str, required: false, description: "YYYY-MM-DD, current scheduled date." }
      status: { type: str, required: true, enum: [pending, done, cancelled], default: pending }
    primary_key: [user_id, occurrence_id]
relations:
  prefers:
    description: Connect a Preference to its Person.
    objects:
      preference: { type: Preference, on_delete: cascade }
      person: { type: Person, on_delete: cascade }
    keys:
      one_person: [preference]
  committed_to:
    description: Connect a Commitment to its Person.
    objects:
      commitment: { type: Commitment, on_delete: cascade }
      person: { type: Person, on_delete: cascade }
    keys:
      one_person: [commitment]
```

"I prefer window seats" and "I avoid overnight flights" land on two records, because the key is
the specific dimension, not the travel category. "Exam tomorrow drops after it expires" becomes a
`Commitment` with a `due_on` you filter on and a `status` that changes when the person says so;
nothing decays silently, and "what is still pending this week" is a query. The identity rule is
deliberately scoped to dated, one-per-day commitments; widen it before relying on it for the
undated or repeated kind. Supermemory's
"preferences strengthen with repetition" has no direct equivalent here: a schema could carry a
count, but that is an explicit alternative you would design and test, not a reproduction of the
behaviour. More generally, the needs behind `updates`, `extends` and `derives` are met by
different means: a key identifies the record an update lands on, enrichment is a field, a record
or a relation depending on what is being added, and inference is whatever a description
explicitly allows.

## Why we think this matters, and for whom

xmemory works well for short-running agents, and it is at its best for repeated tasks, where each run adds to a body of knowledge the next run can use. Long-horizon agents deserve a special mention, because there is very little objective evidence yet about what memory design works for them. Our working belief, and the reason xmemory exists: an agent running a long, multi-step task does better on structured state than on accumulated context. A schema gives it an explicit feedback loop at write time (what was accepted, what was rejected, what changed), so memory is updated rather than bloated and the trajectory stays on course: fewer re-reads, faster steps, more reliable outcomes.

If that is your workload, try xmemory on it. We are building objective measurements for this claim. The [Toloka evaluation](https://xmemory.ai/toloka-agent-memory-evaluation/) is our first independent measurement of the benefits of structured memory; evaluating changing working state over long-horizon tasks is next, and we would welcome collaborators on it. Write to [info@xmemory.ai](mailto:info@xmemory.ai).
