Provenance and Auditability
How the Clinia Context Engine records where every clinical fact came from, what conflicts existed between sources, and how each conflict was resolved.
Provenance and Auditability
Clinical AI systems that aggregate patient data across sources face a fundamental question: why does the chart show this value? A merged entity might draw from three different documents with three different opinions on the patient's medication dose. The system has to pick one, and that decision must be traceable.
Provenance is a first-class design constraint in the Clinia Context Engine. Every resolved entity carries a complete audit trail from the moment it enters the graph.
The ProvenanceTrace
Every ClinicalEntity in the resolved graph carries a ProvenanceTrace:
{
"sources": [
{ "type": "fhir", "origin": "FHIR Bundle", "reliability": 0.85, "ref": "Condition/abc" },
{
"type": "cda",
"origin": "Summary_20230907.xml",
"reliability": 0.8,
"ref": "observation/456"
}
],
"conflicts": [
{
"field": "status",
"values": ["active", "resolved"],
"resolution": "Selected 'active' from FHIR Bundle: more recent source (2023-09-07 vs 2021-04-12)."
}
],
"resolvedBy": "deterministic-code-exact",
"reasoning": "settled by deterministic-code-exact",
"confidence": 0.95
}sources
Each SourceRef in sources represents one contributing record. A single-element array means the entity appeared in only one source and was never merged with another. Multi-element arrays represent deduplicated entities.
| Field | What it records |
|---|---|
type | Which reader produced this source (fhir, cda, document) |
origin | Human-readable label for the source document |
reliability | Weight (0–1) given to this source when resolving conflicts. |
ref | The original resource reference within the source, enabling exact lookup in the source file |
conflicts
When contributing sources disagree on a field value, a ConflictRecord is written. Every conflict record includes the raw values from each source and an explanation of which value was chosen and why.
An empty conflicts array means all sources agreed on all field values.
resolvedBy
Id of the stop rule that settled this fact's most recent merge decision — the rule, not just the 4-layer cascade layer it belongs to.
| Value | What happened |
|---|---|
source-ref-equality | Identical source reference — same data point re-ingested |
deterministic-code-exact | Entities share a standard code. Cheapest, most certain |
deterministic-code-hierarchical | Entities share hierarchically related codes in the same system |
deterministic-code-mismatch | Different codes in a shared system — confident non-match |
nlp-normalization-match | Same concept, different text or minor variation |
embedding-similarity | Semantically similar, no shared codes |
llm-adjudication | Ambiguous case decided by an LLM with clinical context |
cascade-exhausted-default-reject | Every layer escalated without a match — the weakest reject there is |
novel-entity | No pair was ever compared. Treated as unique |
reasoning
Names the rule that settled the merge, as settled by <rule>. It identifies the decision; it does not describe the pair. In particular, when resolvedBy is llm-adjudication, reasoning does not carry the model's natural-language rationale — that explanation is not retained.
Conflict resolution strategies
When sources disagree, the pipeline applies one of these strategies:
| Strategy | When used |
|---|---|
corroboration | The majority of sources agree on one value. Pick the majority value |
recency | No majority. Prefer the value from the most recently dated source |
reliability | Same date or no date. Weight by source reliability score |
llm-judgment | Complex conflict where all simpler strategies are inconclusive |
The strategy used and the outcome are recorded in every ConflictRecord. This means the audit trail answers not just what was chosen but by what rule and from which source.
Confidence scores
Every entity has a confidence score (0–1). For a merged entity it reports the quality band the merge was settled at, not a continuous score — so it takes one of three values:
| Band | confidence |
|---|---|
confirmed | 0.95 |
probable | 0.7 |
uncertain | 0.25 |
A single-source entity was never merged, so there is no band to report; it inherits the reliability of its one source instead.
Read confidence as "how sure the pipeline is that these records are the same entity", and resolvedBy for how it got there. The two are independent: a merge is not less confident for having taken more layers to settle.
Confidence scores propagate to inferred relationships. For example, a prescribed_for edge from the clinical knowledge base is only emitted at confidence 0.90 (strong), 0.75 (moderate), or 0.60 (weak), depending on the knowledge base entry.
Accessing provenance
Full resolution report
GET /v1/patients/{patientId}/resolution returns every entity in the graph with its complete ProvenanceTrace. Use this to:
- Verify that two records were (or were not) merged and understand why
- See all field-level conflicts and how each was resolved
- Identify which source "won" for a given field value
Reconciliation summary
GET /v1/patients/{patientId}/reconciliation returns a higher-level summary: merge counts, the merge groups themselves, and the complete list of inferred relationships. Use this to understand what the pipeline did overall rather than for a specific entity.
See Review the Reconciliation Summary.
Per-entity structured read
Every entity in the VFS can be read at its slug path with format=structured. This returns the entity's full field set, all its clinical codes, and its typed relationships, but not the full ProvenanceTrace. For provenance detail, use the resolution report.
Evidence that is not in the trace
The ProvenanceTrace answers one question: why does this fact hold the value it holds, given the records that were merged into it. Two other kinds of evidence bear on a fact and are deliberately not in it.
A narrative — clinical prose from an ingested document — and a memory each link to a fact through a typed corroborates, enriches or conflicts edge rather than through its trace. Neither changes the fact, so neither belongs in the record of how its value was decided. To see what prose says about a fact, follow its edges; see Relationship Inference.
The word conflict covers both, and the distinction between them matters. A conflict inside the trace has been resolved — one source's value won, and the trace says why. A conflict on an edge has not been resolved and is not going to be: it records that prose disagrees with the record, and leaves both standing.
One consequence for auditing. When adjudication considers a narrative and a fact and finds nothing worth asserting, it writes nothing at all — so there is no way to distinguish a pair that was weighed and passed over from one that was never paired. Absence of an edge is not evidence that a judgement was made.
Design rationale
Provenance is recorded at write time, not reconstructed later. Every merge decision writes its audit trail into the entity as resolution runs. This means the resolution report is an O(1) read. There is no post-hoc reconstruction from logs.
The design also means that if the same patient is re-ingested with a corrected data source, the provenance trace reflects the new state once that submission settles, not the prior one. Provenance represents the current resolved state, not a history of ingestions.
Relationship Inference
How the Clinia Context Engine constructs a typed graph of clinical relationships between deduplicated entities, and what nodes and edges that graph contains.
Clinical Knowledge Base
How the Clinia Context Engine uses a curated vocabulary to infer relationships between conditions, medications, and labs that are not present in the source data.