Skip to main content
A surfaced conflict between two things the same subject believed. Returned by GET /v1/contradictions.
200 application/json

What it is

Contradiction, a pair of beliefs from one subject’s own content that cannot both be current (in practice, a place where they changed their mind and the older position is still sitting in the graph). Exo does not resolve these. It finds them and hands them to you with both sides intact, because which side is right is a judgement about the subject’s intent, not about the text. An assistant that knows a user once committed to usage-based pricing and later argued for seats can say so. An assistant that silently retrieved whichever chunk scored higher cannot.

Where it comes from

Contradictions are mined from the subject’s stored content during the background cognition cycle, not computed per request. Two kinds are detected. A retraction is a statement that walks back an earlier one, found through the language the subject used to walk it back. A reversal is a swap of one concept for another in the same role, for example one datastore replacing another as the chosen option.

Fields

How tension is derived

tension is computed when you read, not stored, so the same conflict can come back with different numbers on different routes. That is deliberate: on a retrieval the number also reflects whether the conflict touches the answer you just asked for. Retractions score above reversals because an explicit walk-back is stronger evidence of a changed mind than a substituted concept.

The two shapes, and which one you are holding

This is the trap on this object. The array on a retrieval is not the Contradiction schema above.
The list route returns the stable camelCase object with an id you can store. The retrieval array returns the mining shape in snake_case, with no id and no status, plus node_id so you can drill into the source and in_active_subgraph so you know whether the conflict actually touched this answer. For a reversal it also carries from_concept and to_concept. Use the retrieval array to warn in the moment. Use the list route when you need something you can reference later.

How to use it

Surface the conflict alongside the answer instead of picking a side.
To close one, supersede the side that lost with POST /v1/graph/nodes/{node_id}/supersede. That records the newer belief as the successor and transfers authority away from the older one, which is how Exo represents a resolved conflict. See Belief and supersession.

Details worth knowing

Because the v1 store has no resolution lifecycle. status is a fixed open on every row, so it carries no information today. It exists so a later release can report a resolved conflict without a breaking change. Do not build a filter on it, and do not show it as a state the user can toggle.
Three ordinary reasons. The subject has no mined contradictions yet, because the background cycle has not run over their content. The query did not activate any node that carries one. Or you sent includeContradictions: false. An empty array is not an error and does not mean the graph is consistent.
The retrieval selector caps what it attaches: at most one per node, at most three per subkind, and at most eight in total. It prefers conflicts on nodes that are in the answer, then fills from recent rows. The list route paginates normally instead, so use it when you want the full set.
It drops out. The selector reads live content, so tombstoning a node with DELETE /v1/graph/nodes/{node_id} removes the conflicts that rest on it from the next read. Restoring the node within the undelete window brings them back, because nothing about the conflict was stored separately.

Limits

  • status is always open. There is no route that resolves a contradiction directly; you resolve one by superseding a side.
  • Contradictions are mined from a subject’s own content. Exo does not compare one subject against another, so it will not tell you that two people on a team disagree.
  • The array on POST /v1/retrieve is typed as an open object in the contract, so a generated client hands you an untyped map. The field list above is what the route emits today.
  • Detection is language-driven. A belief someone changed without ever writing down the change is not detectable, and will not appear.

Next

Belief and supersession

How to close a conflict by recording what replaced what.

List contradictions

The route that returns the stable form, with pagination.