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

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, 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, 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.

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. 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. You supply a callable that receives the conflicting values and returns the canonical result.

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, ensuring source-level metadata survives resolution for downstream lineage viewers.

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, teams can inject organization-specific business rules without modifying core framework code.

Summary

Frequently Asked Questions

How does Semantica detect conflicts between different knowledge sources?

Semantica uses the ConflictDetector class in 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 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. 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →