---
title: "When an AI agent holds contradictory facts"
description: "Contradictory facts in AI memory come in two kinds: a value that changed, and sources that disagree. How to detect each case and resolve it without guessing."
canonical: https://past.dev/guides/contradictory-facts
last-updated: 2026-09-02
---
# When an AI agent holds contradictory facts

Source: https://past.dev/guides/contradictory-facts

Contradictory facts are stored statements that assign different values to the same subject and property. They arise from two situations that look identical at recall time: the value changed and both versions were kept, or independent sources disagree about the same period. A memory system must separate the two at ingestion. A changed value is resolved with validity windows: the newer fact supersedes the older one. A true conflict has no automatic winner, so the system should return evidence from both sides instead of picking one silently.

## Two situations, one appearance

An agent's memory contains two values for the seat count on the Acme contract: a stored fact says 40, a new email says 25. At recall time the store simply shows two values for one property. That single appearance hides two different situations, and the two need opposite handling.

- **The fact changed.** Acme renegotiated on March 12, 2026, and the seat count really went from 40 to 25. Both statements are true for their own periods. This case is handled by [validity windows](/glossary/validity-window): the newer fact closes the older fact's window and supersedes it. [Facts that change over time](/guides/facts-that-change-over-time) covers this case in full.
- **The sources disagree.** The signed order form dated March 12, 2026 says 40 seats and the billing export dated March 13, 2026 says 25 seats, both describing the same renewal period. At least one source is wrong. This is a true conflict, and no timestamp arithmetic can settle it.

The two cases look identical in storage: same subject, same property, two values. They must be separated at ingestion, while the system still has each statement's own date and source. A statement claiming a later period describes a change. A statement about the same period describes a disagreement.

## Why collapsing the two fails silently

Most pipelines collapse conflicting information into a single stored value, usually by a last write wins rule. The failure is silent because every query still returns one confident answer.

- **A disagreement treated as a change** makes the answer depend on ingestion order. Ingest the same two documents in the other order and the agent flips its answer. Nothing records that a choice was made.
- **A change treated as a disagreement** freezes the record. The agent keeps hedging about a value that legitimately moved, or routes every routine update to human review.
- **Ranked retrieval decides by similarity.** When both statements match the query, chunk ranking chooses which one the model reads. The losing statement is absent from context, and its absence is invisible.

Silent collapse also removes the audit trail. When someone asks why the agent reported 25 seats, the store carries no trace that a conflicting 40 ever existed or that a rule chose between them. [Data provenance](/guides/data-provenance) depends on keeping both sides with their sources.

## Detecting a true conflict

Conflict detection runs at ingestion by comparing each new statement against stored facts. Four conditions must all be met before two statements count as contradictory facts:

- **Same subject.** Both statements must refer to the same entity after [entity resolution](/guides/entity-resolution). 'Acme', 'Acme Corp' and 'ACME-2231' have to resolve to one company first, or every alias produces a phantom conflict.
- **Same property.** Seat count against seat count. A statement about seats and a statement about price cannot conflict.
- **Overlapping validity.** The periods the two statements claim must intersect. Sequential periods describe a change, and the pair goes to [fact supersession](/glossary/fact-supersession) instead.
- **Different values after normalization.** '40 seats' and 'forty seats' agree. Normalize units, casing and formats before comparing, or the detector floods review queues with false conflicts.

Statements that meet all four conditions are a genuine conflict and move to a resolution policy.

## Resolution policies compared

A conflict resolution policy decides what recall returns while sources still disagree. Each policy fails in a specific way, so the choice should be explicit per field rather than a global default.

| Policy | How it decides | Failure mode |
| --- | --- | --- |
| Most recent source wins | The statement with the latest event time is treated as correct | Recency is evidence of change, never of accuracy. A stale spreadsheet exported yesterday beats a correct contract signed last year. |
| Source authority ranking | A configured ranking of sources, contract above email above chat | Rankings go stale as systems change, equal-rank sources still tie, and someone has to maintain the list. |
| Human review | A person inspects both sides and picks | Queues grow faster than reviewers clear them, and answers stay blocked while items wait. |
| Surface both sides | Recall returns each value with its source and date | Every caller must handle a multi-valued answer, so application code carries the complexity. |

The automatic policies share one property: each converts a data quality problem into a confident answer. That trade is acceptable for low-stakes fields and dangerous for billing terms, dosage or anything contractual.

## The surface-the-conflict pattern

The safest default reports the disagreement instead of resolving it. Recall returns evidence from both sides: each value with its source, its date and the period it claims. The application then decides, and different applications decide differently.

- **A chat agent** states both values with their sources and asks the user which source to trust.
- **A workflow engine** routes the disputed record to a review queue and continues with the undisputed fields.
- **A reporting job** excludes the disputed field and footnotes the exclusion.

The pattern keeps the choice visible and reversible. When the order form later proves authoritative, the resolution enters the store as its own dated statement, and the conflict closes with a record of how it was settled.

## How past.dev reports a conflict

past.dev recall returns one of four status values rather than forcing a single answer. When credible sources disagree about the same period, the response carries the Conflicted status value and returns the evidence from both sides, each item dated and attributed to its source. Request and response shapes are in the [quickstart](/docs/memory-api/quickstart).

## Testing conflict handling

Conflict behavior is testable with no model in the loop. Ingest two statements that disagree, ask, and assert on the shape of the response rather than its wording.

```aconflictfixtureanditsassertions
ingest { "content": "Order form signed 2026-03-12: the Acme renewal covers 40 seats.",
         "timestamp": "2026-03-12T09:14:00Z" }

ingest { "content": "Billing export 2026-03-13: the Acme renewal shows 25 seats.",
         "timestamp": "2026-03-13T16:02:00Z" }

recall { "query": "How many seats does the Acme renewal cover?" }

Pass: the response reports the disagreement and returns both
      values with their sources and dates.
Fail: the response returns one value and never mentions the other.
```

Add the control case: two statements where the later one describes a change with a later period. The correct response reports the newer value as current and the older value as history, with no conflict raised. A system that reports this pair as a disagreement fails the control. Conflicting-evidence questions of this shape also appear in public memory benchmarks; the [benchmark methodology](/benchmarks/methodology) page describes how such responses are scored.

## Frequently asked questions

### How should an AI agent handle conflicting information from two sources?

First decide whether the value changed or the sources genuinely disagree about the same period. A changed value is superseded by the newer one. A genuine disagreement should be reported with both values and their sources so the application or a person can decide.

### Why does my AI agent give different answers to the same question?

A common cause is two contradictory facts stored for the same subject, with retrieval ranking deciding which one the model sees on each run. Detecting the conflict and surfacing it explicitly makes the answer stable.

### Is the most recent information always correct when sources disagree?

No. Recency shows when a statement was made or received, and a stale export can easily be newer than a correct contract. Use recency to detect change over time, and use source authority or review to settle a same-period disagreement.

### What does the Conflicted status in past.dev mean?

It means credible stored sources disagree about the answer for the same period. The response includes the evidence from both sides with dates and sources so the caller can decide what to do.

## Related

- [Facts that change over time](https://past.dev/guides/facts-that-change-over-time)
- [Data provenance](https://past.dev/guides/data-provenance)
- [Entity resolution](https://past.dev/guides/entity-resolution)
- [Fact supersession](https://past.dev/glossary/fact-supersession)
- [Validity window](https://past.dev/glossary/validity-window)