What Is Temporal Validity in Semantica Context Graphs? A Complete Guide to Bi-Temporal Knowledge Modeling

Temporal validity in Semantica Context Graphs is a bi-temporal modeling system where every node and edge carries validity windows that track both when a fact was true in the real world (valid_from/valid_until) and when it was recorded in the system (recorded_at/superseded_at).

Semantica's Context Graph is a thread-safe, in-memory property graph that treats time as a first-class dimension. This article explains how temporal validity works, why it matters for AI applications, and how to use the full temporal stack (v0.4.0) to build time-aware knowledge systems according to the semantica-agi/semantica source code.

The Bi-Temporal Model: Two Independent Timelines

Semantica implements a bi-temporal data model where each fact stores two distinct time dimensions that operate independently:

  • Valid time — the real-world interval when a fact was actually true
  • Transaction time — the system interval when the fact was known and recorded

The default "open-ended" sentinel TemporalBound.OPEN represents an indefinite end date, allowing facts to remain valid until explicitly superseded. This design separates what happened from when we knew about it, enabling retroactive corrections without destroying audit history.

In docs/reference/temporal.md (lines 7-15), the bi-temporal model is specified as the foundation for all temporal operations in the graph.

Temporal Layers and the Full Stack

Semantica ships with a comprehensive temporal stack (v0.4.0) that extends basic validity windows into a complete time-aware query system:

  • Point-in-time snapshots — freeze the graph state at any moment
  • Allen-interval algebra — formal temporal logic for comparing intervals
  • Natural-language temporal parsing — convert phrases like "last quarter" into valid bounds
  • Three-axis query filtering — filter by "valid", "transaction", or "both" timelines

As documented in docs/reference/temporal.md (lines 9-33), these layers transform the Context Graph from a static structure into a temporal database capable of answering "what-was-true-when" questions deterministically.

Core API: TemporalGraphQuery

The TemporalGraphQuery class in semantica/kg/temporal_query.py provides the primary interface for temporal operations. Key methods include:

Method Purpose
query_at_time(kg, query, at_time) Execute a query against the graph as it existed at a specific timestamp
reconstruct_at_time(kg, timestamp) Build a complete subgraph containing only valid nodes/edges
find_temporal_paths(..., enforce_causal_ordering) Discover paths where temporal ordering respects causality
validate_temporal_consistency(kg) Detect inverted intervals, overlaps, and other temporal anomalies

These methods respect the validity windows of every node and edge, ensuring that query results reflect the exact slice of reality that mattered at any given moment (docs/reference/temporal.md, lines 18-26).

Building Time-Aware Graphs

Validity windows are attached at construction time through the GraphBuilder class in semantica/kg/graph_builder.py.

from semantica.kg import GraphBuilder

builder = GraphBuilder()
kg = builder.build(sources=[{
    "entities": [
        {"id": "alice", "type": "Person"},
        {"id": "acme_corp", "type": "Organization"},
    ],
    "relationships": [
        {
            "source": "alice",
            "target": "acme_corp",
            "type": "ceo_of",
            "valid_from": "2018-01-01",
            "valid_until": "2022-06-01",
        },
        {
            "source": "alice",
            "target": "beta_ltd",
            "type": "ceo_of",
            "valid_from": "2022-06-01",
            # valid_until omitted → defaults to TemporalBound.OPEN

        },
    ],
}])

The builder automatically attaches both valid-time and transaction-time bounds to entities and relationships.

Querying at Specific Points in Time

The TemporalGraphQuery class enables precise temporal filtering:

from semantica.kg import TemporalGraphQuery

query = TemporalGraphQuery(temporal_granularity="day")
result_2020 = query.query_at_time(kg, query="", at_time="2020-06-15")

print(result_2020["relationships"])

# → shows only relationships valid during 2020

For low-level subgraph reconstruction:

snapshot = query.reconstruct_at_time(kg, "2021-06-15")

# snapshot contains only nodes/edges whose validity windows include 2021-06-15

Temporal Path Finding with Causal Ordering

The find_temporal_paths method enforces that path traversal respects the arrow of time:

paths = query.find_temporal_paths(
    kg,
    source="alice",
    target="beta_ltd",
    start_time="2022-01-01",
    end_time="2024-12-31",
    enforce_causal_ordering=True,
    ordering_strategy="strict",
)

for p in paths["paths"]:
    print(" → ".join(p["path"]))

Setting enforce_causal_ordering=True with ordering_strategy="strict" ensures that each step in a path temporally precedes the next, eliminating logically impossible causal chains.

Validating Temporal Consistency

Temporal validity windows can contain inconsistencies—inverted intervals, overlapping contradictory facts, or gaps in required coverage. The validation API detects these automatically:

from semantica.kg import TemporalGraphQuery

report = TemporalGraphQuery().validate_temporal_consistency(kg)
print(f"errors: {len(report.errors)}, warnings: {len(report.warnings)}")

This validation is critical for maintaining data quality in long-running knowledge systems.

ContextGraph: Public Temporal API

The ContextGraph class in semantica/context/context_graph.py exposes simplified temporal methods for common operations:

  • add_node(..., valid_from, valid_until) — create nodes with explicit validity
  • find_active_nodes(at_time=...) — retrieve nodes valid at a specific timestamp

These methods wrap the lower-level TemporalGraphQuery functionality for convenience.

Temporal Reasoning Engine

The TemporalReasoningEngine in semantica/kg/temporal_reasoning.py implements Allen-interval algebra, providing formal operations for comparing temporal intervals:

  • IntervalRelation — enumeration of 13 possible interval relationships (before, meets, overlaps, during, etc.)
  • TemporalBound — bounds handling including the OPEN sentinel

This engine powers all temporal comparison operations in the query system.

Real-World Use Cases

Temporal validity windows enable several critical applications according to the Semantica documentation:

  • Policy versioning — track how regulations evolved and which version applied when
  • Historic responsibility tracing — determine who had what role at a specific time
  • Versioned snapshots — reconstruct system state for debugging or audit
  • Consistency validation — guarantee that graph state reflects intended time spans

These use cases all rely on the bi-temporal foundation to ensure that the knowledge graph remains a faithful record of changing reality (docs/reference/temporal.md, lines 46-53).

Summary

  • Temporal validity in Semantica Context Graphs is implemented as a bi-temporal model with independent valid-time and transaction-time axes.
  • Every node and edge carries valid_from/valid_until and recorded_at/superseded_at windows, with TemporalBound.OPEN for indefinite periods.
  • The temporal stack (v0.4.0) adds snapshots, Allen-interval algebra, natural-language parsing, and three-axis filtering (valid, transaction, both).
  • TemporalGraphQuery in semantica/kg/temporal_query.py provides the core API for time-aware queries, path finding, and consistency validation.
  • GraphBuilder attaches validity windows at construction; ContextGraph exposes simplified temporal methods; TemporalReasoningEngine implements formal interval algebra.

Frequently Asked Questions

What is the difference between valid time and transaction time in Semantica?

Valid time represents when a fact was actually true in the real world, while transaction time records when the system became aware of that fact. These timelines are independent—valid time allows retroactive corrections (stating that something was true earlier than we knew it), and transaction time maintains an immutable audit trail of when information entered the system.

How does TemporalBound.OPEN work for open-ended validity?

TemporalBound.OPEN is a sentinel value representing an indefinite end date. When valid_until or superseded_at is set to OPEN, the fact remains valid until explicitly changed. This is implemented in semantica/kg/temporal_reasoning.py and is the default behavior when no end bound is specified during graph construction.

Can I query Semantica graphs using natural language time expressions?

Yes. The temporal stack (v0.4.0) includes natural-language temporal parsing that converts expressions like "last quarter," "FY2023," or "three months ago" into concrete validity bounds. This integrates with TemporalGraphQuery methods that accept datetime strings or relative time phrases.

What happens if two contradictory facts have overlapping validity windows?

The validate_temporal_consistency method detects overlapping contradictory edges as warnings or errors depending on severity. For explicit conflict resolution, applications must implement domain-specific logic—the bi-temporal model preserves all facts for audit purposes rather than automatically merging or discarding them.

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 →