Extraction is easy when a fact appears once. The hard, and far more common, case is when the same fact appears in three documents with three different values — or once as a summary and again as a detailed schedule that disagrees with it. This is where most extraction tools quietly fail: they take the last value they saw, or the one with the highest model confidence, and move on. Both are wrong often enough to be dangerous.

InsightXtract treats conflict resolution as a first-class, deterministic step. Every field has a declared source-of-truth order. Each document is extracted independently, then a resolver — not the model’s whim — picks the correct value and records exactly why. Contradictions aren’t hidden; they’re surfaced, flagged, and cited.

The four principles

  • Declared source-of-truth, not guesswork. Each field names which documents can supply it, ordered by authority. The ACORD is authoritative for the legal entity; the financials for revenue; the vehicle schedule for the fleet.
  • Detail beats summary. A counted schedule outranks a stated number. “100 vehicles” on an application loses to 118 rows in the fleet schedule — and the gap is flagged.
  • Flag, don’t “fix.” When printed numbers don’t reconcile, InsightXtract keeps what the document actually says and attaches a validation note — it never silently rewrites a total to make the math work.
  • Every value carries its reasoning. The resolved answer travels with its confidence, its source document and page, and a plain-language reason. A missing value says “not found in any source,” not null with no explanation.

How resolution actually runs

Documents are extracted independently and in parallel (each cached, so a re-run only re-reads the file that changed). Then consolidation walks each field’s declared sources in priority order and takes the first authoritative, non-empty value — carrying its provenance with it.

flowchart LR E[Email] --> X[extract each doc
independently] A[ACORD] --> X W[Exposure workbook] --> X V[Vehicle schedule] --> X L[Loss runs] --> X X --> R[resolve per field
walk sources by priority
first authoritative non-null wins] R --> C[reconcile & validate
detail vs summary · math checks] C --> O[resolved value
+ confidence · source · page · reason]

Resolution is declared per field in the agent spec, so it’s governed and auditable, not buried in code:

// In the agent's output schema — the source-of-truth order for one field
{
  "name": "annual_revenue",
  "sources": [
    { "role": "financials", "priority": 1 }, // authoritative
    { "role": "application", "priority": 2 },
    { "role": "submission_email", "priority": 3 }
  ]
}

Six conflicts, and how each resolves

Each example shows the raw values pulled from every document, the priority order, the value that wins, and the reasoning InsightXtract records.

1 · The legal entity name — insured_name
SourceExtracted valuePriority
ACORD applicationAcme Logistics, LLC1Winner
Broker emailAcme Logistics3skipped
Application narrativeACME LOGISTICS INC2skipped
Why: the ACORD is the declared authority for the legal entity, so its exact form wins — the email’s casual short name and the narrative’s all-caps variant are lower priority. The resolver takes the first non-empty value in priority order; it doesn’t “average” strings or pick the most frequent.
2 · Detail beats summary — total_vehicles
SourceExtracted valuePriority
Vehicle schedule (counted rows)1181Winner
Application (stated)1002delta flagged
Why: the schedule is the authoritative source and its count is derived from the actual rows, so 118 wins over the round “100” a broker typed. But the 18-unit gap isn’t swallowed — it’s recorded as a discrepancy so an underwriter can see the application understated the fleet. Detail wins and the summary’s disagreement is preserved.
3 · Authoritative by domain — annual_revenue
SourceExtracted valuePriority
Audited financials$88,200,0001Winner
Application$85,000,0002delta flagged
Broker email“~$85M”3skipped
Why: revenue is a financial fact, so the financials outrank the application and the email’s approximation. The resolver takes $88.2M, but the ~4% gap against the application is flagged — a delta that size is exactly what an underwriter wants to notice, not have quietly reconciled away.
4 · Reconcile, don’t rewrite — loss-run totals
ValueAmount
Sum of per-claim incurred (computed)$312,500
Printed “Total Incurred” on the report$310,000Kept as-is
Reconciliation checkoff by $2,500does_not_reconcile
Why: when the rows don’t sum to the printed total (beyond a small rounding tolerance), InsightXtract keeps the printed values and attaches a does_not_reconcile note with lowered confidence — it does not “fix” a figure to force the math. The document is reported as it truly is, and the mismatch becomes a review signal rather than a silent corruption.
5 · Strip noise before judging — effective_date
Location in documentValue seen
Policy period on the ACORD body07/01/2026Winner
Date in the email signature / disclaimer footer05/14/2026ignored
Why: not every value that looks like the field is the field. The date in a signature block or a “sent” header is noise; the operative policy period is on the form body. InsightXtract discards non-substantive noise before it judges, so a stray date in a footer never wins over the real one.
6 · Graceful fallback — fein
SourceExtracted valuePriority
ACORD application— (blank)1empty
Financials cover page47-28319052Winner
Why: the highest-priority source is empty, so resolution falls through to the next declared source rather than returning null. Provenance records that the value came from the fallback (financials, not the ACORD) — so the reviewer knows precisely where it originated.

The reasoning is the product

A resolved value is never a bare number. Each one is a small record — the value, how confident the system is, which document and page it came from, and a human-readable reason. Contradictions are attached, not discarded.

// The resolved field, as it lands in the record
{
  "annual_revenue": {
    "value": 88200000,
    "confidence": 0.94,
    "source": "financials",
    "page": 3,
    "reasoning": "Taken from audited financials (priority 1). Application stated $85.0M — 3.6% lower; flagged as a discrepancy.",
    "conflicts": [{ "source": "application", "value": 85000000 }]
  }
}

Escalate, never silently guess

The resolver only breaks ties toward more scrutiny, never less. When the top sources are all empty, confidence is low, or a total won’t reconcile, the field is flagged for human review instead of returning a confident-looking fabrication. For an insurer, a flagged “we’re not sure” is far cheaper than a clean-looking wrong number.

You configure the outcome, not the code

Because resolution is declarative, changing it is a governance decision, not an engineering ticket:

  • Per-field source order — list the roles that may supply a field and their priority. Reorder them and the outcome changes, with a full audit trail.
  • Authoritative tables — a table (the fleet, the loss run, the SOV) names its authoritative source document, with fallback to any role that produced it.
  • Reconciliation rules — declare the math that must hold (rows sum to the total, incurred = paid + reserved) and the tolerance; violations flag rather than fix.
  • Review thresholds — set the confidence floor below which a field is routed to a human. Tune it as data, not code.

Why it matters to the business

  • The right number reaches the rate. Pricing off the authoritative source — not whichever document was read last — is the difference between an adequate rate and a mispriced one.
  • Disagreements become underwriting signal. A fleet understated by 18 units or revenue off by 4% is exactly what a reviewer should see. Surfacing conflicts turns a data problem into a risk insight.
  • Nothing is silently invented. Keeping documents as they are — flagging mismatches instead of rewriting them — is what keeps the record defensible in an audit or dispute.
  • Every value is explainable. When a number is questioned, the answer is one click: this source, this page, this reasoning, these alternatives considered.