How to Record and Audit AI Decisions Using Semantica's ContextGraph

Semantica stores every AI decision as a first-class node in its ContextGraph, enabling tamper-evident audit trails through the record_decision API and the provenance audit CLI command.

The semantica-agi/semantica repository provides a governance-first framework for AI systems that treats decisions as graph-native entities. By implementing a dual-layer recording and provenance system, Semantica ensures that every automated choice—from loan approvals to content moderation—can be reconstructed, validated, and audited for regulatory compliance.

Understanding the Decision Recording Architecture

At the core of Semantica's audit capability is the ContextGraph, a persistent graph structure that treats decisions as nodes with full lineage tracking. When you invoke record_decision on a ContextGraph instance (or its specialized subclass AgentContext), the system performs a multi-stage validation and indexing process defined in semantica/context/context_graph.py.

The method transforms high-level decision metadata into immutable provenance records, storing them in both the graph structure and an optimized internal index. This dual-storage approach—graph nodes for relationship traversal and dictionary indexing for fast category-based lookup—enables sub-second retrieval even with millions of historical decisions.

Recording Decisions with record_decision

The primary interface for capturing AI decisions is the ContextGraph.record_decision method. According to the source code in semantica/context/context_graph.py (lines 4330–4446), this method orchestrates validation, normalization, and persistence.

Method Signature and Validation

The record_decision method accepts rich metadata that captures the full context of automated decision-making:

  • Categorical data: category (e.g., "loan_approval"), scenario (human-readable description), outcome (the decision result), and reasoning (chain-of-thought or logic)
  • Quantitative metrics: confidence (float between 0 and 1), temporal bounds (valid_from and valid_until)
  • Entity linking: entities (list of affected entity IDs), decision_maker (model or system identifier)
  • Extensible metadata: metadata dictionary for domain-specific key-value pairs

The validation block (lines 4356–4444) enforces strict type checking and length limits before any persistence occurs. Invalid inputs raise immediate exceptions, preventing corrupted audit trails from entering the system.

The Recording Pipeline

Once validation passes, the method executes a four-stage pipeline:

  1. UUID Generation: Creates a deterministic unique identifier for the decision
  2. Timestamp Normalization: Converts temporal inputs to ISO-8601 UTC strings
  3. Graph Insertion: Calls _add_decision_to_graph to create the provenance-tracked node
  4. Index Updates: Stores the decision in self._decisions and builds reverse indices by category, entity, and time range

The method returns the generated decision ID, which serves as the anchor for future audits or decision chaining.

from semantica.context import ContextGraph

# Initialize context (can be persistent or in-memory)

ctx = ContextGraph()

# Record a complex business decision

decision_id = ctx.record_decision(
    category="loan_approval",
    scenario="Applicant requests $10k small business loan",
    reasoning="Credit score 720, debt-to-income ratio 30%, 5-year payment history clean",
    outcome="approved",
    confidence=0.93,
    entities=["applicant_123", "loan_product_A", "underwriting_bot_v2"],
    decision_maker="risk_engine_v2",
    metadata={"loan_amount": 10_000, "currency": "USD", "risk_tier": "low"},
    valid_from="2026-01-01T00:00:00Z",
    valid_until="2026-12-31T23:59:59Z"
)

print(f"Decision recorded with tamper-evident ID: {decision_id}")

Building the Audit Trail Through Provenance

While recording captures decisions, the Provenance subsystem enables retrospective analysis. Implemented across semantica/cli.py and semantica/provenance/manager.py, this system aggregates decision nodes into human-readable audit logs.

CLI Auditing with semantica provenance audit

The command-line interface in semantica/cli.py (lines 2825–2892) exposes the provenance audit command, which instantiates a ProvenanceManager and invokes audit_log. This command supports three critical filtering and export options:

  • Temporal filtering: --since parameter accepts ISO dates to limit scope (e.g., --since 2026-08-01)
  • Format flexibility: --format accepts json (machine-parseable), csv (spreadsheet analysis), or table (human-readable terminal output)
  • Export persistence: --output writes results to disk for regulatory submission

# Display recent decisions in terminal-friendly table format

semantica provenance audit --since 2026-08-01 --format table

# Export CSV for compliance reporting

semantica provenance audit --since 2026-08-01 --format csv --output q3_audit_trail.csv

# Generate JSON for downstream SIEM integration

semantica provenance audit --since 2026-01-01 --format json --output annual_audit.json

Programmatic Access via ProvenanceManager

For application-embedded auditing, import the ProvenanceManager directly from semantica/provenance. The audit_log method returns a serializable list of decision records containing timestamps, entity IDs, operation types, and stored metadata.

from semantica.provenance import ProvenanceManager

# Initialize manager (inherits configuration from CLIContext when available)

pm = ProvenanceManager()

# Retrieve audit trail programmatically

log = pm.audit_log(since="2026-08-01", format="json")

# Process individual decision records

for entry in log:
    print(f"{entry['timestamp']} | {entry['category']} | "
          f"Confidence: {entry.get('confidence', 'N/A')} | "
          f"Outcome: {entry['outcome']}")

Implementation Best Practices

When deploying Semantica for governance-critical systems, structure your decision categories hierarchically using dot-notation (e.g., finance.loan.retail) to leverage the built-in category indexing. Always provide explicit valid_until timestamps for time-bounded decisions, allowing the system to automatically archive obsolete records.

For high-throughput applications, batch multiple decisions into a single context instance rather than instantiating ContextGraph per decision, as the internal _decisions dictionary maintains memory-resident indices that optimize category-based lookups.

Summary

  • Semantica's ContextGraph stores AI decisions as first-class nodes with full provenance tracking in semantica/context/context_graph.py
  • The record_decision method validates rich metadata (confidence, entities, temporal bounds) and returns a UUID for future reference
  • The _add_decision_to_graph internal method creates tamper-evident links while self._decisions enables fast indexed retrieval
  • The semantica provenance audit CLI (defined in semantica/cli.py) exports audit trails in JSON, CSV, or table formats with temporal filtering
  • ProvenanceManager provides programmatic access to audit logs for integration with external compliance systems

Frequently Asked Questions

How does Semantica ensure decision records cannot be altered after creation?

Once record_decision completes the pipeline in semantica/context/context_graph.py, the decision node is integrated into the graph via _add_decision_to_graph, which establishes cryptographic provenance links to previous state. The internal self._decisions dictionary stores references to these immutable nodes, and the validation layer (lines 4356–4444) rejects any attempts to overwrite existing decision IDs, creating an append-only audit trail.

What is the maximum size for metadata when recording a decision?

The validation block in semantica/context/context_graph.py enforces length limits on string fields and recursion depth on dictionary metadata, though exact byte limits depend on the underlying graph storage backend. For production deployments, keep individual metadata values under 1MB to ensure the _add_decision_to_graph serialization remains performant during high-volume ingestion.

Can I record decisions for a specific time range in the past or future?

Yes. The record_decision method accepts valid_from and valid_until parameters that accept ISO-8601 formatted strings. These temporal bounds are normalized to UTC during the recording pipeline (lines 4330–4446) and indexed separately from the physical recording timestamp, allowing you to query decisions by their logical validity period using the ProvenanceManager temporal filters.

How do I export audit logs for regulatory compliance requirements?

Use the semantica provenance audit command with --format csv and --output flags as implemented in semantica/cli.py (lines 2825–2892). The CSV export includes all mandatory fields (decision ID, timestamp, category, outcome, confidence) plus serialized metadata columns. For GDPR or CCPA compliance, filter exports using --since to limit data to specific reporting periods, reducing exposure of historical personal data.

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 →