# How to Implement Causal Decision Chain Analysis and Impact Analysis in Semantica

> Implement causal decision chain and impact analysis in Semantica by building a knowledge graph and traversing it. Enhance with LLM-driven CausalChainAnalyzer for deeper insights.

- Repository: [Semantica /semantica](https://github.com/semantica-agi/semantica)
- Tags: how-to-guide
- Published: 2026-08-20

---

**You implement causal decision chain analysis and impact analysis in Semantica by building a causal knowledge graph in `ContextGraph`, traversing it via `get_causal_chain()`, and optionally enriching results with the LLM-driven `CausalChainAnalyzer`.**

Semantica treats every decision as a node inside a persistent knowledge graph called the **ContextGraph**. Edges between nodes capture causal semantics—such as `CAUSED`, `INFLUENCED`, or `PRECEDENT_FOR`—and the system supports both pure-graph traversal and LLM-augmented reasoning to analyze chains and impacts. According to the semantica-agi/semantica source code, the implementation is split between graph storage, an optional analyzer wrapper, and an MCP tool endpoint.

## How Semantica Models Decisions and Causality

In [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py), the `ContextGraph` class persists decision nodes and their causal edges in a pluggable vector store. When a decision is recorded—typically via `semantica.context.decision_recorder.DecisionRecorder`—the graph stores metadata such as the decision ID, description, and provenance.

## Building the Causal Graph

### Adding Decisions and Relationships

To construct a chain, first add decisions to the graph, then link them with causal relationships. The following example shows a simple three-node chain in pure Python:

```python
from semantica.context.context_graph import ContextGraph

g = ContextGraph()

# Create causal edges: d_root -> d_child -> d_grandchild

g.add_causal_relationship("d_root", "d_child", "CAUSED")
g.add_causal_relationship("d_child", "d_grandchild", "CAUSED")

```

In production, these calls are usually made by `DecisionRecorder` as decisions are ingested. The underlying storage backend—whether SQLite, PG-Vector, Pinecone, or FAISS—is abstracted behind the graph API, so the causal-chain logic remains identical across environments.

## Querying Causal Chains

Semantica provides two ways to retrieve a causal chain: a pure-graph traversal method on `ContextGraph` and an optional LLM-driven wrapper in `CausalChainAnalyzer`.

### Pure-Graph Traversal with ContextGraph

The core method is `ContextGraph.get_causal_chain()`, defined in [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py). It accepts a `node_id`, a `direction` (`"upstream"` or `"downstream"`), and a `max_depth` parameter.

```python
downstream = g.get_causal_chain(
    node_id="d_root",
    direction="downstream",
    max_depth=5,
)

# downstream -> ["d_child", "d_grandchild"]

```

If the analyzer layer is unavailable, the MCP endpoint falls back directly to this method. The tests in [`tests/test_030_context_graph_realworld_extended.py`](https://github.com/semantica-agi/semantica/blob/main/tests/test_030_context_graph_realworld_extended.py) verify upstream and downstream behavior, depth limits, and graceful handling of missing nodes.

### LLM-Enhanced Analysis with CausalChainAnalyzer

When an LLM integration is configured, [`semantica/context/causal_analyzer.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/causal_analyzer.py) exposes `CausalChainAnalyzer.get_causal_chain()`. This wrapper can augment the returned chain with narrative explanations, confidence scores, and suggested mitigation actions before returning the final result.

The analyzer follows the same signature—`node_id`, `direction`, `max_depth`—so it acts as a drop-in replacement for the pure-graph implementation. If the LLM path fails or is not configured, the system falls back to `ContextGraph.get_causal_chain()`.

## Performing Impact Analysis

Impact analysis is a direct application of causal chain traversal. **Downstream** nodes represent decisions impacted by the starting node, while **upstream** nodes represent prerequisites. End-to-end examples in [`tests/test_030_realworld_comprehensive.py`](https://github.com/semantica-agi/semantica/blob/main/tests/test_030_realworld_comprehensive.py) demonstrate how a supply-disruption decision propagates through inventory draw-down and price-increase decisions.

After retrieving a chain, you can enumerate the affected decisions and inspect their payloads:

```python
chain = g.get_causal_chain("supply_disruption", direction="downstream", max_depth=5)
impacted = [g.get_decision(dec_id) for dec_id in chain]

for d in impacted:
    print(f"Impacted: {d.decision_id} – {d.description}")

```

For richer reporting, `ContextGraph.trace_decision_causality()` returns a list of causal paths rather than a flat list of IDs. Use this when you need to visualize branch points, measure blast radius, or identify bottleneck decisions in the graph.

## MCP Endpoint for Decision Chains

The public interface for causal chain queries is `handle_get_causal_chain` in [`semantica/mcp/tools/decisions.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/mcp/tools/decisions.py). The orchestration flow is:

1. Extract `decision_id`, `direction`, and `max_depth` from the request payload.
2. Instantiate `CausalChainAnalyzer` if the LLM integration is present.
3. Call `analyzer.get_causal_chain(node_id, direction, max_depth)`.
4. On failure, fall back to `graph.get_causal_chain(...)`.
5. Wrap the resulting ID list or decision objects in a consistent JSON response.

A typical call through the MCP tool looks like this:

```python
from semantica.mcp.tools.decisions import handle_get_causal_chain

payload = {"decision_id": "dec_101", "direction": "upstream", "max_depth": 3}
response = handle_get_causal_chain(payload)

# response -> {"causal_chain": ["dec_099", "dec_100"], "status": "ok"}

```

This endpoint is exercised in [`tests/test_mcp_decisions_causal_chain.py`](https://github.com/semantica-agi/semantica/blob/main/tests/test_mcp_decisions_causal_chain.py), which covers both the LLM-enabled path and the pure-graph fallback.

## Summary

- **Store causality in `ContextGraph`** using `add_causal_relationship()` and `add_decision()` inside [`semantica/context/context_graph.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py).
- **Traverse chains** with `ContextGraph.get_causal_chain()`, specifying `direction` and `max_depth` to control scope.
- **Enable LLM reasoning** by instantiating `CausalChainAnalyzer` from [`semantica/context/causal_analyzer.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/context/causal_analyzer.py) without changing the traversal API.
- **Analyze impact** by inspecting downstream chains, or use `trace_decision_causality()` for full path reporting.
- **Expose the logic** through `handle_get_causal_chain` in [`semantica/mcp/tools/decisions.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/mcp/tools/decisions.py) for MCP-compatible requests.

## Frequently Asked Questions

### What storage backends does Semantica support for causal graphs?

Semantica abstracts the vector store behind `ContextGraph`, so you can use SQLite, PG-Vector, Pinecone, FAISS, or other compatible backends. The causal-chain query logic in `get_causal_chain()` remains identical regardless of which storage layer you choose, letting you swap backends without touching analysis code.

### How does Semantica handle missing decisions during chain traversal?

The pure-graph traversal in `ContextGraph.get_causal_chain()` gracefully handles absent nodes. The integration tests in [`tests/test_030_context_graph_realworld_extended.py`](https://github.com/semantica-agi/semantica/blob/main/tests/test_030_context_graph_realworld_extended.py) explicitly verify traversal behavior when nodes in the requested path do not exist.

### Can I use causal decision chain analysis without an LLM?

Yes. The `CausalChainAnalyzer` is optional. If it is not configured or its call fails, the MCP endpoint and other consumers automatically fall back to `ContextGraph.get_causal_chain()`, which performs fast, deterministic graph traversal without LLM calls.

### What is the difference between `get_causal_chain()` and `trace_decision_causality()`?

`ContextGraph.get_causal_chain()` returns a flat list of decision IDs reachable from a starting node, while `trace_decision_causality()` returns a list of full causal paths. Use the former for simple enumeration and the latter for detailed impact visualization or branch-point analysis.