How to Implement Decision Intelligence with Full Audit Trails and Causal Chain Tracking in Semantica-AGI

Implement decision intelligence with immutable audit trails and causal chain tracking by combining DecisionRecorder for persisting decisions, ProvenanceManager for hash-chained audit logs, and CausalChainAnalyzer for upstream/downstream impact analysis—all orchestrated through MCP tools in the Semantica-AGI framework.

Decision intelligence requires more than logging choices; it demands traceable provenance, queryable precedents, and analyzable causal relationships. The open-source Semantica-AGI repository (semantica-agi/semantica) provides production-ready Python components that bind these capabilities together through a knowledge-graph-backed architecture. This guide covers the complete implementation: recording decisions, validating schemas, traversing causal chains, and exporting tamper-evident audit logs.


Core Components for Decision Intelligence

Semantica-AGI's decision intelligence stack consists of five tightly-coupled modules:

Capability Core Module Primary API Purpose
Decision recording semantica/context/decision_methods.py record_decision() / capture_decision_trace() Persists decisions with metadata and creates immutable trace events in the knowledge graph
Decision querying semantica/context/decision_methods.py find_precedents() / query_decisions() Retrieves past decisions by semantic similarity or explicit filters
Causal-chain analysis semantica/context/causal_analyzer.py CausalChainAnalyzer.get_causal_chain() Walks upstream/downstream relationships to surface root causes and downstream impacts
Audit-trail storage semantica/provenance/manager.py ProvenanceManager.track_entity(), audit_log() Stores PROV-O-compatible entries with hash-chained checksums, exportable in multiple formats
Schema validation semantica/mcp/schemas.py RECORD_DECISION JSON schema Enforces required fields: category, scenario, reasoning, outcome, confidence

The Decision Lifecycle: From Recording to Immutable Audit

Understanding how a decision flows through the system is essential for proper integration. The lifecycle follows five stages:

  1. Client builds payload — conforming to the RECORD_DECISION schema defined in mcp/schemas.py
  2. MCP tool invocation — record_decision handler in mcp/tools/decisions.py receives the payload
  3. DecisionRecorder persistence — creates a Decision dataclass and writes to the graph store
  4. Trace event emission — DECISION_RECORDED event triggers supplemental captures
  5. Immutable chain creation — _append_immutable_trace_events() generates hash-chained DecisionTraceEvent nodes

In mcp/tools/decisions.py, the tool handler directly invokes:


# https://github.com/semantica-agi/semantica/blob/main/mcp/tools/decisions.py

DECISION_TOOLS[0]["_handler"](args)

This delegates to the convenience wrapper record_decision() in semantica/context/decision_methods.py, which orchestrates both graph persistence and audit trail generation.


Recording Decisions with Full Provenance

The record_decision() function in semantica/context/decision_methods.py provides the primary interface. It accepts structured decision metadata and automatically initiates audit capture.

from semantica.context.decision_methods import record_decision

decision_id = record_decision(
    graph_store=my_graph_store,
    category="risk_assessment",
    scenario="Evaluate credit risk for applicant #12345",
    reasoning="FICO 680, recent delinquency flagged in 2023-Q2",
    outcome="high_risk",
    confidence=0.87,
    entities=["applicant_12345", "credit_report_67890"],
    decision_maker="risk_engine_v3",
)
print("Decision recorded:", decision_id)

Key parameters include:

  • category — taxonomic classifier for decision types (e.g., loan_approval, deployment)
  • scenario — natural-language description of the decision context
  • reasoning — explicit rationale (often LLM-generated or rule-derived)
  • outcome — the resulting action or classification
  • confidence — numeric certainty score (0.0–1.0)
  • entities — linked knowledge-graph nodes that influenced this decision
  • decision_maker — identifier for the responsible agent or system

The function returns a UUID that serves as the anchor for all subsequent audit and causal queries.


Building Immutable Audit Trails with Hash Chaining

The ProvenanceManager in semantica/provenance/manager.py guarantees tamper-evidence through cryptographic chaining. Each audit entry includes the SHA-256 hash of the previous entry, forming an append-only sequence that detects any modification.

from semantica.provenance.manager import ProvenanceManager

# Initialize with persistent SQLite backend

prov_mgr = ProvenanceManager(storage_path="audit.db")

# Export full audit trail in multiple formats

json_log = prov_mgr.audit_log(format="json")
csv_log = prov_mgr.audit_log(format="csv")
table_log = prov_mgr.audit_log(format="table")

The internal _save_entry() method computes:


# Conceptual flow within ProvenanceManager._save_entry()

current_hash = sha256(previous_hash + entry_content)

This hash chain ensures that even a single-character alteration anywhere in the history invalidates all subsequent entries—a critical property for compliance and forensic analysis.


Querying Precedents and Decision History

Decisions become intelligence when compared against historical patterns. The find_precedents() function supports semantic similarity search over past decision scenarios.

from semantica.context.decision_methods import find_precedents

precedents = find_precedents(
    graph_store=my_graph_store,
    scenario="Credit risk evaluation for self-employed applicant",
    limit=5,
)
for decision in precedents:
    print(f"{decision.decision_id}: {decision.outcome} (confidence: {decision.confidence})")

The match is performed via natural-language embedding similarity on the scenario field, optionally filtered by category, outcome, or date range through query_decisions().


Causal Chain Analysis: Upstream and Downstream Traversal

The CausalChainAnalyzer in semantica/context/causal_analyzer.py enables forensic investigation of how decisions propagate through systems. It supports three traversal directions:

  • Upstream — identify root causes by following derived_from_id and used_entities edges
  • Downstream — measure impact by following has_trace_event and used_entities edges
  • Both — full bidirectional exploration
from semantica.context.decision_methods import get_causal_chain

# Investigate what led to a critical decision

upstream_chain = get_causal_chain(
    graph_store=my_graph_store,
    decision_id=decision_id,
    direction="upstream",
    max_depth=3,
)

# Assess what this decision subsequently affected

downstream_chain = get_causal_chain(
    graph_store=my_graph_store,
    decision_id=decision_id,
    direction="downstream",
    max_depth=5,
)

# Full bidirectional analysis

full_chain = get_causal_chain(
    graph_store=my_graph_store,
    decision_id=decision_id,
    direction="both",
    max_depth=4,
)

for step in full_chain:
    print(f"{step.decision_id}: {step.scenario} (impact score: {step.impact_score})")

The analyzer computes impact scores via analyze_decision_impact(), weighting downstream nodes by graph distance and outcome severity.


Automatic Integration via AgentContext

When decision_tracking is enabled in configuration, AgentContext (semantica/context/agent_context.py) automatically wires all decision intelligence services:


# https://github.com/semantica-agi/semantica/blob/main/semantica/context/agent_context.py

if self.config.get("decision_tracking"):
    self._decision_recorder = DecisionRecorder(self.graph_store)
    self._decision_query    = DecisionQuery(self.graph_store)
    self._causal_analyzer   = CausalChainAnalyzer(self.graph_store)
    self._policy_engine     = PolicyEngine(self.graph_store)

This injection pattern allows any LLM-driven agent to access decision capabilities without manual service initialization:


# Within an AgentContext-enabled workflow

decision_id = record_decision(
    graph_store=ctx.graph_store,
    category="deployment",
    scenario="Deploy v2.3 of the recommendation engine",
    reasoning="Tests passed, p99 latency < 50ms, no critical errors in staging",
    outcome="deployed",
    confidence=0.99,
)

# Immediate causal analysis

chain = get_causal_chain(
    graph_store=ctx.graph_store,
    decision_id=decision_id,
    direction="downstream",
    max_depth=5,
)

Complete End-to-End Implementation

The following runnable example demonstrates all capabilities in sequence:

from semantica.context.decision_methods import (
    record_decision,
    find_precedents,
    get_causal_chain,
    analyze_decision_impact,
)
from semantica.provenance.manager import ProvenanceManager

# 1. Initialize provenance with persistent SQLite store

prov_mgr = ProvenanceManager(storage_path="audit.db")

# 2. Record a deployment decision with full metadata

decision_id = record_decision(
    graph_store=prov_mgr.storage.graph_store,
    category="deployment",
    scenario="Deploy v2.3 of the recommendation engine to production",
    reasoning="Integration tests passed; canary metrics healthy for 4 hours; rollback window confirmed with SRE",
    outcome="deployed",
    confidence=0.94,
    entities=["service_recommendation_v2.3", "deployment_pipeline_prod"],
    decision_maker="ci_cd_orchestrator",
)

# 3. Find similar past deployment decisions

similar_deployments = find_precedents(
    graph_store=prov_mgr.storage.graph_store,
    scenario="Deploy recommendation engine",
    limit=3,
)
print(f"Found {len(similar_deployments)} precedents")

# 4. Get full causal chain (upstream dependencies + downstream effects)

full_chain = get_causal_chain(
    graph_store=prov_mgr.storage.graph_store,
    decision_id=decision_id,
    direction="both",
    max_depth=4,
)

# 5. Compute quantitative impact score

impact = analyze_decision_impact(
    graph_store=prov_mgr.storage.graph_store,
    decision_id=decision_id,
)
print(f"Downstream impact score: {impact.score}")

# 6. Export immutable audit log for compliance

audit_json = prov_mgr.audit_log(format="json")
with open("deployment_audit.json", "w") as f:
    f.write(audit_json)

Key Source Files Reference

File Role URL
mcp/tools/decisions.py MCP tool definitions: record_decision, query_decisions, get_causal_chain https://github.com/semantica-agi/semantica/blob/main/mcp/tools/decisions.py
semantica/context/decision_methods.py High-level orchestration: recording, querying, causal analysis, audit creation https://github.com/semantica-agi/semantica/blob/main/semantica/context/decision_methods.py
semantica/context/causal_analyzer.py CausalChainAnalyzer implementation for graph traversal https://github.com/semantica-agi/semantica/blob/main/semantica/context/causal_analyzer.py
semantica/provenance/manager.py Hash-chained provenance with export utilities https://github.com/semantica-agi/semantica/blob/main/semantica/provenance/manager.py
mcp/schemas.py JSON Schema validation including RECORD_DECISION https://github.com/semantica-agi/semantica/blob/main/mcp/schemas.py
semantica/context/agent_context.py Service injection for agent runtimes https://github.com/semantica-agi/semantica/blob/main/semantica/context/agent_context.py

Summary

  • record_decision() persists decisions to the knowledge graph and initiates immutable audit capture via hash-chained trace events
  • ProvenanceManager provides tamper-evident storage with SHA-256 checksums and multi-format export (JSON/CSV/table)
  • find_precedents() enables semantic similarity search over historical decisions for pattern recognition
  • get_causal_chain() traverses upstream (derived_from_id) and downstream (has_trace_event) relationships to surface root causes and impacts
  • AgentContext automatically injects all services when decision_tracking is enabled, requiring zero boilerplate for LLM agents
  • Schema enforcement via RECORD_DECISION in mcp/schemas.py guarantees data integrity at ingestion

Frequently Asked Questions

How does Semantica-AGI ensure audit logs cannot be tampered with?

The ProvenanceManager in semantica/provenance/manager.py computes a SHA-256 checksum for each audit entry that incorporates the previous entry's hash. This creates a cryptographic chain where modifying any historical entry invalidates all subsequent hashes, making tampering immediately detectable.

What graph relationships does CausalChainAnalyzer traverse?

CausalChainAnalyzer.get_causal_chain() follows derived_from_id and used_entities edges for upstream traversal (root cause analysis), and has_trace_event with used_entities for downstream traversal (impact analysis). These relationships are stored as labeled edges in the underlying knowledge graph.

Can decision schemas be customized for domain-specific requirements?

The base RECORD_DECISION schema in mcp/schemas.py enforces core fields (category, scenario, reasoning, outcome, confidence), but the Decision dataclass and DecisionRecorder accept arbitrary additional fields through the entities list and extensible metadata dictionaries. Domain extensions should subclass the schema validator while preserving required fields.

What storage backends support the audit trail?

ProvenanceManager supports both in-memory storage (for testing) and persistent SQLite via storage_path="audit.db". The ProvenanceStorage abstraction in semantica/provenance/manager.py can be extended for PostgreSQL, Neo4j, or other backends by implementing the _save_entry() and query interface contracts.

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 →