How ContextGraph.record_decision() Integrates with Causal Relationship Tracking in Semantica
ContextGraph.record_decision() creates Decision nodes that serve as anchors for causal edges added via add_causal_relationship(), enabling trace_decision_causality() to reconstruct influence chains through explicit graph traversal.
The Semantica AGI framework provides sophisticated decision tracking through its ContextGraph class, where ContextGraph.record_decision() serves as the foundational method for persisting decision metadata. This functionality integrates seamlessly with causal relationship tracking to map how decisions influence one another over time. Understanding this integration is essential for building explainable AI systems that can trace decision provenance through directed causal chains.
The Decision Recording Pipeline
At the core of the integration is the transformation of decision data into graph-native structures.
Creating Decision Nodes with record_decision()
In semantica/context/context_graph.py (lines 3083-3130), the record_decision() method instantiates a ContextNode with type "Decision" and populates its properties with the decision's metadata. The method generates a unique UUID for the decision and delegates node insertion to _add_internal_node().
decision_id = str(uuid.uuid4())
node = ContextNode(
node_id=decision_id,
node_type="Decision",
content=decision.scenario,
properties={
"category": decision.category,
"reasoning": decision.reasoning,
"outcome": decision.outcome,
"confidence": decision.confidence,
"timestamp": normalized_timestamp.isoformat(),
"decision_maker": decision.decision_maker,
**metadata,
},
valid_from=decision.valid_from,
valid_until=decision.valid_until,
)
self._add_internal_node(node)
This node creation establishes the necessary graph entity that subsequent causal operations reference.
Decision Node Structure and Properties
The properties dictionary captures comprehensive decision context including category, reasoning, outcome, and confidence scores. Temporal boundaries are enforced through valid_from and valid_until fields, enabling time-aware causal analysis. The entities field links decisions to specific domain objects, creating connection points for heuristic causal inference when explicit edges are absent.
Establishing Causal Relationships Between Decisions
Once decisions exist as nodes, the graph supports explicit causal linkage through a dedicated API.
The add_causal_relationship() Method
Located at lines 2643-2670 in context_graph.py, add_causal_relationship() validates that source and target IDs reference existing decision nodes before creating a directed ContextEdge. The method accepts relationship types from the canonical set defined in _CAUSAL_EDGE_TYPES: CAUSED, INFLUENCED, and PRECEDENT_FOR.
edge = ContextEdge(
source_id=source_decision_id,
target_id=target_decision_id,
edge_type=relationship_type, # "CAUSED", "INFLUENCED", or "PRECEDENT_FOR"
weight=1.0,
metadata={"recorded_at": datetime.utcnow().isoformat()},
)
self._add_internal_edge(edge)
The edge is persisted via _add_internal_edge(), making it available for subsequent traversal operations.
Causal Edge Types and Validation
The integration enforces strong typing for causal relationships. Before edge creation, the system verifies both endpoints exist in the internal _decisions registry. This validation ensures causal chains only connect actual decision nodes, preventing spurious links to other entity types like observations or hypotheses.
Traversing Causal Chains with trace_decision_causality()
The retrieval mechanism completes the integration by consuming the nodes and edges created by the previous steps.
Building the Reverse Causal Index
The trace_decision_causality() method (lines 3453-3505) begins by constructing a reverse index of all explicit causal edges. It iterates through _CAUSAL_EDGE_TYPES and maps target decision IDs to their incoming edges using a defaultdict(list) structure.
incoming_causal_edges = defaultdict(list)
for edge_type in _CAUSAL_EDGE_TYPES:
for edge in self.edge_type_index.get(edge_type, []):
if edge.source_id in self._decisions:
incoming_causal_edges[edge.target_id].append(edge)
This index enables efficient O(1) lookup of causal predecessors during graph traversal.
Explicit vs. Heuristic Causal Discovery
The tracing algorithm performs a depth-first walk starting from the target decision, prioritizing explicit edges from incoming_causal_edges. Each hop is recorded with its direction, type, and weight:
hop = {
"from": cause_id,
"to": current_id,
"type": edge.edge_type,
"edge_weight": edge_weight,
}
Only when no explicit causal edges exist does the system fall back to heuristic inference based on shared entities or temporal proximity. This precedence guarantees that manually curated causal relationships override automated assumptions.
Practical Implementation Example
The following example demonstrates the complete integration workflow: recording decisions, establishing causality, and tracing the resulting chain.
from semantica.context import ContextGraph
# Initialize the graph
graph = ContextGraph()
# Record two related decisions
d1 = graph.record_decision(
category="loan_approval",
scenario="First-time homebuyer",
reasoning="Excellent credit score",
outcome="approved",
confidence=0.96,
entities=["customer_123"],
decision_maker="analyst_1",
)
d2 = graph.record_decision(
category="loan_approval",
scenario="Refinance request",
reasoning="Stable income, low LTV",
outcome="approved",
confidence=0.93,
entities=["customer_123"],
decision_maker="analyst_2",
)
# Establish explicit causal link
graph.add_causal_relationship(
source_decision_id=d1,
target_decision_id=d2,
relationship_type="CAUSED",
)
# Retrieve causal chain
chain = graph.trace_decision_causality(d2)
print(chain)
Output structure:
[
{
"from": "d1-uuid",
"from_scenario": "First-time homebuyer",
"to": "d2-uuid",
"to_scenario": "Refinance request",
"type": "CAUSED",
"edge_weight": 1.0
}
]
Summary
- ContextGraph.record_decision() creates strongly-typed Decision nodes in
semantica/context/context_graph.py(lines 3083-3130), storing comprehensive metadata as node properties. - add_causal_relationship() (lines 2643-2670) validates decision nodes and creates directed edges with types
CAUSED,INFLUENCED, orPRECEDENT_FOR. - trace_decision_causality() (lines 3453-3505) builds a reverse index of explicit causal edges and performs depth-first traversal to reconstruct influence chains.
- The system prioritizes explicit causal edges over heuristic inference based on shared entities or timestamps.
- All operations maintain temporal validity through
valid_fromandvalid_untilattributes on decision nodes.
Frequently Asked Questions
What data structure does record_decision() use to store decision metadata?
The method stores metadata within a ContextNode object's properties dictionary, which includes fields like category, reasoning, outcome, confidence, and timestamp. These properties are indexed alongside the node's temporal bounds (valid_from, valid_until) to support time-aware causal queries.
How does trace_decision_causality() prioritize causal relationships?
The method always prioritizes explicit causal edges created via add_causal_relationship(). It first builds a reverse index of edges with types in _CAUSAL_EDGE_TYPES (CAUSED, INFLUENCED, PRECEDENT_FOR) and traverses these before falling back to heuristic inference based on shared entities or temporal proximity.
Can causal relationships be established between non-decision nodes?
No. The add_causal_relationship() method explicitly validates that both source_decision_id and target_decision_id exist in the internal _decisions registry. This constraint ensures that causal chains specifically map decision provenance rather than general entity relationships.
Where are the core implementations of these methods located?
All three methods reside in semantica/context/context_graph.py. The record_decision() implementation spans lines 3083-3130, add_causal_relationship() is at lines 2643-2670, and trace_decision_causality() occupies lines 3453-3505. Supporting data models are defined in semantica/context/decision_models.py.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →