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

# Conflicts (human-in-the-loop)

> Contradictions are kept, surfaced, and resolved by you, reversibly

## The stance

Most memory systems resolve contradictions silently: last write wins, or an LLM picks a
winner. memloom's position is that **a contradiction between your memories is information,
and deciding it is your call**. When an incoming memory can't be true at the same time as an
existing one, memloom keeps *both* active and records a conflict for you to resolve. Nothing
is auto-overwritten; nothing is lost while the conflict is pending.

## How a conflict is detected

On every save (with dedup enabled), memloom:

1. Short-circuits exact duplicates by content hash (no LLM involved).
2. Finds up to 5 existing active memories with cosine similarity ≥ 0.5 to the incoming one.
3. Asks the LLM to classify each candidate's relation to the incoming memory:

| Relation        | Meaning                                  | What happens                            |
| --------------- | ---------------------------------------- | --------------------------------------- |
| `identical`     | The same fact restated                   | New **version** of the existing belief  |
| `complementary` | Both can be true at once, related or not | Both coexist; the new one is added      |
| `contradictory` | They cannot both be true                 | **Conflict recorded**, both stay active |

The conflict record stores the incoming memory, every contradicting candidate, and the
classifier's stated *reason*, so when you look at it later you see why it was flagged.

## Resolving

Pending conflicts show up in `memloom conflicts`, the viewer's Conflicts tab, the
`GET /memory/conflicts` endpoint, and the `list_conflicts` MCP tool (so an agent can say
*"you have a pending conflict about the staging database"*). Four resolutions:

| Action             | Effect                                                                                                                                                          |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **keep\_new**      | The incoming memory wins and *continues the existing belief's lineage* (it becomes the next version). The old memories go stale with `replaces` edges.          |
| **keep\_existing** | The incoming memory goes stale; the existing one stays current.                                                                                                 |
| **keep\_both**     | They're genuinely distinct facts. Both stay active, linked with a `distinct` edge so they're never re-flagged against each other.                               |
| **merge**          | You (or an agent, with your reconciled text) write the sentence that's actually true. It becomes the next version of the belief; both inputs go stale under it. |

## Auto-resolving with an LLM judge

`memloom conflicts auto` (`POST /memory/conflicts/resolve-auto/stream`) runs the same LLM
over the pending queue a second time, now with context the dedup classifier never had. The
classifier only ever compares two pieces of text in isolation; the auto-resolver also sees
when each side was recorded and, for memories that came from
[`import sessions`](/concepts/distillation), the transcript excerpt it was distilled
from. Most import conflicts are a later session recording a state change ("we moved to
railway") against an older fact ("the deploy target is fly.io"), and with time and context
in view that resolution is mechanical.

The judge answers one of the same four actions, minus merge (there's no reconciled text for
an LLM to author on your behalf):

| Verdict         | Meaning                                                                             |
| --------------- | ----------------------------------------------------------------------------------- |
| `keep_new`      | The incoming memory records a later decision that supersedes the existing one       |
| `keep_existing` | The incoming memory is transient noise or a misreading; the existing one is durable |
| `keep_both`     | They describe different scopes and can coexist                                      |
| `unsure`        | The evidence isn't decisive                                                         |

It is told to prefer `unsure` over guessing: when recording times are close or the excerpts
don't show which side is current, the conflict stays in the queue untouched. Only a
decisive verdict calls `resolveConflict`, so an auto-resolution lands in the same revertable
history as a manual one, and `revert` undoes it exactly the same way.

<Note>
  This is the same one-shot judge that resolves some conflicts during `import sessions`
  itself (see [Session distillation](/concepts/distillation#belief-pipeline-and-conflicts)).
  `conflicts auto` is how you run it again over whatever is left, on demand, for conflicts
  from any source, not just import.
</Note>

## Everything is reversible

No resolution deletes anything. Losers go `status = 'stale'`; the relationships are recorded
as edges (`replaces`, `distinct`) that can be deactivated. `revert` on a resolved conflict:

* reactivates whatever was staled,
* deactivates the edges the resolution created,
* undoes any lineage re-parenting,
* and puts the conflict back in the pending queue.

You can resolve a conflict, change your mind a week later, revert it, and resolve it the
other way.

<Note>
  Conflict detection requires the LLM, so it's off in offline mode (no `OPENROUTER_API_KEY`).
  Offline saves skip the belief pipeline entirely and always report `added`.
</Note>
