What ontology versioning invariants must survive when agents exchange structured knowledge?
**Date of Record:** 2026 October 27 **Scope:** Applies when multiple agentic sessions exchange structured knowledge (schemas, vocabularies, or concept hierarchies) using ontologies, and the ontologies are versioned such that different agents may operate under different ontology versions, causing semantic incompatibility. Does not apply to agents using a single immutable ontology, or exchanges using only free-form text.
Core Distinction
The separation between **ontology concept identity** (the concept exists in both versions) and **ontology concept semantics** (the concept's definition and constraints are compatible across versions). Relying on identity creates the **Ontology Semantic Drift**: Agent A sends a concept that exists in both A's and B's ontology versions, but the concept's definition has subtly changed between versions, and B interprets it differently than A intended, causing semantic mismatch.
What Was Observed
In knowledge-exchange agent architectures, failing to preserve ontology versioning produces three primary failure modes:
- **Subsumption Reversal:** A concept "mammal" was defined as a subclass of "animal" in v1, but in v2 "animal" was renamed and redefined, and the concept hierarchy is inverted. A's knowledge graph is misinterpreted by B.
- **Property Constraint Tightening:** A property "has_duration" allowed any positive number in v1, but v2 requires duration < 1 day. A's multi-day facts fail B's validation.
- **Deprecation Ambiguity:** A concept deprecated in v2 is still used by A (on v1). B treats it as unknown, and the exchange silently loses facts.
Recorded Elements
- **`ontology_version_signature`:** Every knowledge exchange declares the ontology version used to generate it, with a cryptographic signature binding the version to the ontology definition.
- **`ontology_mapping_matrix`:** For each pair of ontology versions, the exact mapping of concepts, properties, and constraints, allowing translation from one version to another.
- **`concept_compatibility_receipt`:** For each exchanged concept, the cryptographic proof that A's concept is semantically compatible with B's (same definition, same constraints, same hierarchy position).
- **`deprecated_concept_warning_receipt`:** For concepts deprecated in the receiver's version, a warning that the fact will be treated as `LEGACY` and may be discarded.
Condition of Validity
* **Applies when:** Multiple ontology versions exist, knowledge is exchanged across versions, and concept semantics can shift. * **Does not apply when:** All agents use a single immutable ontology, or knowledge exchange is free-form with no structured semantics.
Decision Boundary
- **Do the two agents use different ontology versions?** If no, standard knowledge exchange applies. If yes, proceed.
- **Is a `ontology_mapping_matrix` available between the two versions?** If no, the receiver cannot translate concepts. It must reject or request an updated mapping.
- **Does the `concept_compatibility_receipt` confirm semantic compatibility for each concept?** If yes, exchange proceeds. If no, incompatible concepts must be flagged or rejected.
- **Conversely, when can agents exchange knowledge without version mapping?** Only when the exchanged concepts are verified compatible across versions by an independent semantic check, or the exchange is strictly exploratory.
Operational Effect
- **Semantic Consistency:** Knowledge exchange respects concept definitions, not just concept names.
- **Deprecation Awareness:** Receivers know when they are receiving deprecated concepts, allowing graceful handling.
- **Mapping Auditing:** Every version transition is documented, enabling audits and rolling upgrades.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class OntologyVerdict(Enum):
SAME_VERSION = auto()
COMPATIBLE_TRANSLATION = auto()
INCOMPATIBLE_CONCEPT = auto()
NO_MAPPING = auto()
@dataclass(frozen=True)
class OntologyConcept:
concept_id: str
version: str
definition_hash: str
constraints_hash: str
@dataclass(frozen=True)
class OntologyExchange:
sender_concept: OntologyConcept
receiver_version: str
mapping_available: bool
concept_deprecated_in_receiver: bool
@dataclass(frozen=True)
class OntologyPolicy:
require_mapping: bool
allow_deprecated: bool
@dataclass(frozen=True)
class OntologyManifest:
verdict: OntologyVerdict
directive: str
manifest_digest: str
class OntologyVersioningGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_exchange(
cls, exchange: OntologyExchange, policy: OntologyPolicy
) -> OntologyManifest:
# Gate 1: Same version
if exchange.sender_concept.version == exchange.receiver_version:
digest = cls._hash(json.dumps({
"concept": exchange.sender_concept.concept_id,
"version": exchange.receiver_version
}, sort_keys=True))
return OntologyManifest(
verdict=OntologyVerdict.SAME_VERSION,
directive=f"PROCEED: Same ontology version for {exchange.sender_concept.concept_id}.",
manifest_digest=digest
)
# Gate 2: Mapping availability
if policy.require_mapping and not exchange.mapping_available:
return OntologyManifest(
verdict=OntologyVerdict.NO_MAPPING,
directive=f"HALT: No mapping from {exchange.sender_concept.version} to {exchange.receiver_version}.",
manifest_digest=cls._hash(f"NO_MAPPING:{exchange.sender_concept.concept_id}")
)
# Gate 3: Deprecation
if exchange.concept_deprecated_in_receiver and not policy.allow_deprecated:
return OntologyManifest(
verdict=OntologyVerdict.INCOMPATIBLE_CONCEPT,
directive=f"HALT: Concept {exchange.sender_concept.concept_id} deprecated in receiver version.",
manifest_digest=cls._hash(f"DEPRECATED:{exchange.sender_concept.concept_id}")
)
# Gate 4: Translation
digest = cls._hash(json.dumps({
"concept": exchange.sender_concept.concept_id,
"from_version": exchange.sender_concept.version,
"to_version": exchange.receiver_version,
"definition": exchange.sender_concept.definition_hash,
"constraints": exchange.sender_concept.constraints_hash
}, sort_keys=True))
return OntologyManifest(
verdict=OntologyVerdict.COMPATIBLE_TRANSLATION,
directive=f"PROCEED: Translated {exchange.sender_concept.concept_id} from {exchange.sender_concept.version} to {exchange.receiver_version}.",
manifest_digest=digest
)