# What Is the ContextGraph Class in Semantica? Core Architecture Explained

> Discover Semantica's ContextGraph class, the core architecture for unified contextual knowledge. Learn how this in-memory graph store manages entities, time, decisions, and analytics via a thread-safe API.

- Repository: [Semantica /semantica](https://github.com/semantica-agi/semantica)
- Tags: architecture
- Published: 2026-09-05

---

**The `ContextGraph` class is Semantica's single source of truth for all contextual knowledge, serving as an in-memory graph store that unifies entity management, temporal validity tracking, decision recording, and advanced knowledge graph analytics behind a thread-safe API.**

The `ContextGraph` class sits at the heart of the [semantica-agi/semantica](https://github.com/semantica-agi/semantica) repository, powering the framework's knowledge graph and decision-tracking ecosystem. This article examines its architecture, responsibilities, and implementation based on the source code in [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py).

---

## Core Responsibilities of the ContextGraph Class

The `ContextGraph` class fulfills ten distinct responsibilities that together enable Semantica's cognitive architecture.

### In-Memory Graph Storage

At its foundation, `ContextGraph` maintains nodes (`ContextNode`) and edges (`ContextEdge`) in efficient data structures:

- `self.nodes` — dictionary mapping node IDs to `ContextNode` objects
- `self.edges` — dictionary mapping edge IDs to `ContextEdge` objects
- `self._adjacency` — adjacency list for fast traversal

These structures enable O(1) lookups and efficient BFS-based graph traversals.

### Unified Mutation API

The class exposes high-level methods for graph construction:

- `add_node()`
- `add_edge()`
- `add_nodes()`
- `add_edges()`

All mutations are guarded by `self._lock`, a re-entrant lock guaranteeing **thread safety** for concurrent access.

---

## Temporal Validity and Time-Aware Queries

The `ContextGraph` class handles **temporal knowledge** through timestamp-aware nodes and edges. Every entity can carry `valid_from` and `valid_until` properties.

Helper functions in [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py) normalize temporal inputs:

- `_parse_iso_dt()` — parses ISO datetime strings
- `normalize_temporal_input()` — converts various inputs to canonical tz-naive UTC ISO format

This enables queries like "all programming languages valid after 2023" or decisions that expired.

---

## Querying and Neighbor Discovery

Rich traversal methods support complex graph queries:

| Method | Purpose |
|--------|---------|
| `query()` | General-purpose filtered search |
| `get_neighbors()` | BFS traversal with hop limits |
| `get_neighbor_distances()` | Distance-weighted results |
| `neighbors` | Property-based quick access |

Parameters include:
- `hops` — BFS depth limit
- `min_weight` — confidence threshold
- `edge_type` — relationship filtering
- `skip` / `limit` — pagination

---

## Decision Management and Causal Analysis

The `ContextGraph` class embeds **decision intelligence** through specialized capabilities:

**Causal Edge Types**
The private constant `_CAUSAL_EDGE_TYPES` defines relationship semantics for decision tracing.

**Key Methods:**
- `record_decision()` — persists a decision with category, scenario, reasoning, outcome, confidence, and linked entities
- `find_precedents()` — retrieves similar historical decisions
- `analyze_decision_influence()` — traces causal chains through the graph

This transforms the knowledge graph into a **decision support system** where past choices inform future reasoning.

---

## Advanced Knowledge Graph Analytics

When `advanced_analytics=True` is passed to the constructor, `ContextGraph` instantiates optional components (lines 45–55 in [`context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/context_graph.py)):

- `CentralityCalculator` — PageRank, betweenness, closeness metrics
- `CommunityDetector` — graph clustering (Louvain, label propagation)
- `NodeEmbedder` — vector representations of nodes
- `PathFinder` — shortest paths, bidirectional search
- `SimilarityCalculator` — structural and embedding-based similarity

Exposed methods include:
- `get_node_centrality()`
- `find_similar_nodes()`
- `analyze_graph_with_kg()`

These require the optional KG package but enable **production-grade graph intelligence** without external databases.

---

## Persistence and Version Control

The `ContextGraph` class supports **knowledge-as-code** workflows:

- `export_node_markdown()` — serializes nodes to canonical Markdown with YAML front-matter
- `apply_node_markdown()` — applies updates with **atomic revision checking**

The `expected_revision` parameter prevents concurrent modification conflicts, enabling Git-based versioning of knowledge artifacts.

---

## Indexing and Performance Optimization

For query acceleration, `ContextGraph` maintains:

- `self.node_type_index` — maps type labels to node ID sets
- `self.edge_type_index` — maps relationship types to edge ID sets

These indexes synchronize automatically during mutations and power efficient label-based filtering. Decision-specific indexes support fast precedent retrieval.

---

## Extensibility and Lifecycle Management

Two advanced features enhance operability:

**Mutation Callbacks**
The `mutation_callback` constructor parameter accepts a callable invoked on every graph change—useful for audit trails, event streaming, or reactive updates.

**Retraction and Tombstoning**
Separate maps handle safe removal:
- `self._retractions` — logical deletions (preserving ID space)
- `self._tombstones` — permanently removed entities

Implemented in coordination with [`semantica/context/erasure.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/erasure.py), this allows **time-travel queries** and regulatory compliance without data destruction.

---

## Practical Code Examples

### Initialize with Advanced Analytics

```python
from semantica.context import ContextGraph

graph = ContextGraph(
    advanced_analytics=True,
    centrality_analysis=True,
    community_detection=True,
    node_embeddings=True,
)

```

### Build a Basic Knowledge Graph

```python
graph.add_node("Python", "language", content="Programming language")
graph.add_node("Programming", "concept")
graph.add_edge("Python", "Programming", edge_type="related_to")

```

### Query with Constraints

```python
neighbors = graph.get_neighbors(
    "Python",
    hops=2,
    min_weight=0.5,
    include_distance_metadata=True,
)

```

### Record and Analyze Decisions

```python
decision_id = graph.record_decision(
    category="loan_approval",
    scenario="First-time homebuyer",
    reasoning="Good credit score",
    outcome="approved",
    confidence=0.95,
    entities=["customer_123", "property_456"],
)

precedents = graph.find_precedents(decision_id, limit=5)

```

### Version-Controlled Node Updates

```python
md = graph.export_node_markdown("Python")

# Modify and apply with revision safety

updated_md = md.replace("language", "language\nvalid_from: 2024-01-01")
graph.apply_node_markdown(
    "Python",
    updated_md,
    expected_revision=graph.export_node_markdown("Python")[:32],
)

```

---

## Key Source Files

| File | Role |
|------|------|
| [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py) | Main `ContextGraph` implementation (lines 1–2000+) |
| [`semantica/context/erasure.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/erasure.py) | Retraction and tombstoning utilities |
| [`semantica/context/markdown.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/markdown.py) | Markdown serialization and parsing |

`ContextNode` and `ContextEdge` dataclasses are defined within [`context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/context_graph.py) (approximately lines 18–30 and 61–74).

---

## Summary

- **`ContextGraph`** is the **central data structure** for Semantica's knowledge ecosystem, implemented in [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py)
- Provides **thread-safe** graph mutations through re-entrant locking
- Supports **temporal validity** with ISO datetime normalization
- Enables **decision tracking** via causal edges and precedent analysis
- Optionally integrates **advanced analytics**: centrality, community detection, embeddings, pathfinding
- Exports to **Markdown** for version-controlled knowledge management
- Uses **type indexes** for performant queries and **tombstoning** for safe deletion

---

## Frequently Asked Questions

### What is the difference between ContextGraph and a standard graph database?

`ContextGraph` is an **embedded, in-memory** structure optimized for Semantica's cognitive workflows—decision recording, temporal queries, and Markdown persistence. Unlike Neo4j or similar databases, it requires no external service, supports atomic revision tokens for version control, and includes built-in causal analysis primitives for decision intelligence.

### How does ContextGraph ensure thread safety?

All mutations acquire `self._lock`, a `threading.RLock` (re-entrant lock). This allows nested acquisitions by the same thread while preventing concurrent modifications. The lock wraps `add_node`, `add_edge`, and all bulk operations, as visible in the method implementations within [`context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/context_graph.py).

### Can ContextGraph scale to large datasets?

`ContextGraph` is designed for **working-set** scenarios where hot knowledge resides in memory. Its adjacency lists and type indexes provide O(1) lookups for indexed fields and O(V + E) BFS traversals. For datasets exceeding RAM, Semantica integrates with external vector stores—the `ContextGraph` serves as the coherent, queryable layer while heavy embeddings persist elsewhere.

### What happens when a node is deleted?

Deletions use **logical retraction** by default: the node enters `self._retractions` with an invalidation timestamp but remains queryable for historical analysis. Physical removal (tombstoning) moves entries to `self._tombstones`, freeing the ID for reuse while preserving audit trails. Both patterns are implemented in coordination with [`semantica/context/erasure.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/erasure.py).