Before you start
A key with write
Listing needs
read. Closing one needs graph:write, which a write key grants.Some history
A contradiction needs two beliefs that disagree. One import is rarely enough.
A place to show them
A review queue, a Slack channel, or a pull-request comment.
The shortest call that works
200 OK
Reading a contradiction
a and b are the two poles. What they contain depends on the kind of conflict:
tension is a 0 to 1 salience computed when you read, not stored. Retractions score higher than reversals because dropping a belief outright is a stronger signal than changing your mind about which option wins. Sort by it to put the sharpest conflicts at the top of a review queue.
Note also that a Contradiction carries no node ids. a and b are text. Closing one therefore takes an extra step: find the node behind the losing side first.
The review loop
Get told, do not poll
Subscribe to
contradiction.detected rather than sweeping the list on a timer. Register a webhook so the review still happens when nobody has the dashboard open.contradiction.detected is a person-scoped event: it reaches only endpoints registered by the person whose beliefs conflict. See Reacting to change.Page the open list
Deliveries are thin by design, so fetch current state rather than trusting the payload. Page with
nextCursor until hasMore is false.Show a human both sides
Render
a and b side by side with detectedAt and tension. Do not pick a winner automatically. The whole value of surfacing a conflict is that a person decides, and the person usually knows something the graph does not.A useful review card reads: βOn 11 July you held Mobile is the 2026 priority. On 14 July you held Defer mobile until the API ships. Which one still stands?βFind the node behind the losing side
GET /v1/recall/graph/search does a full-text match over stored chunk text and returns node ids, which is what the supersede call needs.GET /v1/graph/nodes?q= is the alternative when you want a title substring match with cursor pagination instead.Supersede the side that lost
POST /v1/graph/nodes/{id}/supersede records old -> superseded_by -> new. The old belief is not deleted: it stays in the chain, and authority moves to the successor.200 OK
content (create a successor from text) or nodeId (link an already-owned node as the successor). Sending both, or neither, is a validation error. Both nodes must belong to the effective subject; anything else is a 404.Choosing a confidence
confidence drives the authority transfer. The successor inherits the higher of the two authorities, and the superseded belief decays by 1 - confidence.
Reach for a value below 1.0 when the old belief may still be right in some context. That is what keeps the chain honest rather than turning supersession into a soft delete.
Contradictions inline with retrieval
You do not have to run a separate review to see conflicts.POST /v1/retrieve returns the ones bearing on the current query in the same response as the answer:
includeContradictions defaults to true, so set it to false only when you want the cheaper call.
When it goes wrong
Next
Contradiction
The object itself, why
status is always open, and how tension is derived.Belief and supersession
Authority transfer, and reading a chain from
GET /v1/graph/nodes/{id}/history.