# How to Implement Conflict Detection and Resolution for Multi-Source Knowledge in Semantica

> Learn how Semantica implements conflict detection and resolution for multi-source knowledge. Discover how ConflictDetector ConflictAnalyzer and ConflictResolver manage clashes while preserving provenance.

- Repository: [Semantica /semantica](https://github.com/semantica-agi/semantica)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Semantica resolves multi-source knowledge conflicts by detecting clashes with `ConflictDetector`, analyzing them with `ConflictAnalyzer`, and reconciling values through `GraphBuilder`'s built-in `ConflictResolver` while preserving full provenance metadata in the knowledge graph.**

Merging data from documents, APIs, and ontologies into a single knowledge graph inevitably produces duplicate or contradictory facts. The `semantica-agi/semantica` repository solves this with a dedicated conflicts pipeline that separates detection from resolution and plugs directly into the graph-building workflow. This guide walks through the Python APIs, CLI commands, and extension points needed to implement conflict detection and resolution for multi-source knowledge.

## How Semantica Detects Conflicts in Multi-Source Graphs

In [`semantica/conflicts/conflict_detector.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflict_detector.py), the `ConflictDetector` class traverses the candidate graph after ingestion to spot inconsistencies. It delegates rule-based classification to `ConflictAnalyzer` in [`semantica/conflicts/conflict_analyzer.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflict_analyzer.py), which applies SHACL shapes and custom Python callables to produce a machine-readable report.

### Entity-Level Clashes and Value Mismatches

The detector flags two distinct semantic issues. **Entity-level clashes** occur when separate nodes claim to represent the same real-world object but carry different identifiers or attribute sets. **Value mismatches** arise when an identical property key on the same entity holds divergent values, such as two different `birthDate` strings.

### Structural Contradictions and Schema Violations

`ConflictAnalyzer` also identifies **structural contradictions**. These are incompatible edge types or cardinality violations that would break schema constraints defined by SHACL shapes or custom validation rules.

```python
from semantica.conflicts import ConflictDetector

# `graph` is the merged knowledge graph produced by GraphBuilder

detector = ConflictDetector()
report = detector.detect_conflicts(graph)

print(f"Found {report['count']} conflicts")
for c in report["conflicts"]:
    print(f"- Entity {c.entity_id}: {c.conflict_type}")

```

## Resolution Strategies in GraphBuilder

Once `ConflictDetector` catalogues issues, reconciliation is handled by `ConflictResolver` inside [`semantica/kg/graph_builder.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/kg/graph_builder.py). The resolver updates the graph **in-place**, attaching provenance metadata so audit tools can trace every final value back to its origin.

### Built-in Resolution Policies

`GraphBuilder` ships with configurable per-property strategies:

- **First-wins / last-wins** – retains the earliest or latest ingested value.
- **Longest-string / most-recent-timestamp** – applies domain-specific heuristics when temporal length or recency signals higher quality.
- **Custom merge functions** – user-supplied callables for complex scenarios, such as merging partial address fields.

### Registering Custom Merge Functions via the Registry

Domain-specific logic is registered in the **`conflict_resolution_registry`** defined in [`semantica/conflicts/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/registry.py). You supply a callable that receives the conflicting values and returns the canonical result.

```python
from semantica.kg.graph_builder import GraphBuilder
from semantica.conflicts.registry import register_resolution

# Prefer the longest string for the "description" property

def longest_string(a, b):
    return a if len(a) >= len(b) else b

register_resolution("description", longest_string)

builder = GraphBuilder(resolve_conflicts=True)
final_graph = builder.build(sources)  # `sources` = list of source graphs

```

## Integrating the Pipeline from Ingestion to Persistence

The end-to-end flow in Semantica is a four-stage pipeline orchestrated by `GraphBuilder` when `resolve_conflicts=True`.

1. **Ingest** each source into a provisional sub-graph.
2. **Merge** sub-graphs via `GraphBuilder`, which calls `ConflictDetector.detect_conflicts()` on the combined graph and passes the conflict list to `ConflictResolver.resolve_conflicts()`.
3. **Persist** the reconciled graph to the chosen vector store, such as Weaviate or Qdrant.
4. **Expose** the conflict summary through the CLI command `semantica validate conflicts` or programmatically via the `conflicts` package.

Provenance tracking is maintained by [`semantica/conflicts/conflicts_provenance.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflicts_provenance.py), ensuring source-level metadata survives resolution for downstream lineage viewers.

```bash
semantica validate conflicts --json

# {"conflicts": [...], "count": 7}

```

## Extending the Conflicts Module

The architecture is fully pluggable. New conflict types are added by extending `ConflictAnalyzer` with additional validation functions. Upstream sources can emit arbitrary provenance tags that the resolver consumes to prioritize trusted data. Because resolution policies live in [`semantica/conflicts/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/registry.py), teams can inject organization-specific business rules without modifying core framework code.

## Summary

- **`ConflictDetector`** in [`semantica/conflicts/conflict_detector.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflict_detector.py) walks the graph to find entity clashes, value mismatches, and structural contradictions.
- **`ConflictAnalyzer`** applies SHACL shapes and custom rules in [`semantica/conflicts/conflict_analyzer.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflict_analyzer.py) to classify issues into a JSON report.
- **`GraphBuilder`** in [`semantica/kg/graph_builder.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/kg/graph_builder.py) embeds `ConflictResolver` to merge values in-place while preserving provenance via [`semantica/conflicts/conflicts_provenance.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflicts_provenance.py).
- Register custom strategies in [`semantica/conflicts/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/registry.py) with `register_resolution()` for domain-specific merge logic.
- Run `semantica validate conflicts --json` from [`semantica/cli.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/cli.py) to surface conflict summaries after ingestion.

## Frequently Asked Questions

### How does Semantica detect conflicts between different knowledge sources?

Semantica uses the `ConflictDetector` class in [`semantica/conflicts/conflict_detector.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/conflict_detector.py) to scan merged graphs for duplicate entities and divergent property values. It partners with `ConflictAnalyzer` to apply SHACL shapes and custom Python rules, returning a compact report containing `entity_id`, `conflict_type`, and a total count.

### What resolution strategies are available for conflicting property values?

The built-in `ConflictResolver` inside [`semantica/kg/graph_builder.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/kg/graph_builder.py) supports first-wins, last-wins, longest-string, and most-recent-timestamp heuristics. Each strategy can be assigned per-property, and provenance metadata is retained so auditors can trace the winning value back to its original source.

### Can I define custom conflict resolution logic in Semantica?

Yes. You can register a callable through `register_resolution()` in [`semantica/conflicts/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts/registry.py). The function receives conflicting values as arguments and returns the canonical value, which `GraphBuilder` invokes automatically when `resolve_conflicts=True`.

### How can I view conflict reports after merging multiple sources?

After ingestion, run `semantica validate conflicts --json` from the CLI entry point in [`semantica/cli.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/cli.py) to emit a JSON summary. Programmatically, call `ConflictDetector.detect_conflicts(graph)` on any merged graph to obtain the same report dictionary consumed by CI pipelines and UI tools.