How the Semantica Decision Tracking API Records, Traces, and Audits Agent Decisions

The Semantica decision tracking API captures agent decisions via an MCP tool endpoint, persists them as embedded vectors with full provenance metadata, and provides audit primitives including precedent search, causal chain analysis, and impact assessment.

The decision tracking subsystem in the open-source semantica-agi/semantica repository implements a two-layer architecture that bridges command-line interfaces with persistent vector storage. This system ensures every agent decision is recorded with complete contextual metadata, enabling full traceability and deterministic audit trails across the knowledge graph.

Recording Decisions via the MCP Tool Layer

When an agent or user initiates a decision recording, the MCP dispatcher routes the request to handle_record_decision in mcp/tools/decisions.py. This handler serves as the primary entry point for the decision tracking API, validating required fields before persisting data.

The function enforces a strict schema requiring five mandatory fields:

  • category – the decision classification
  • scenario – the situational context
  • reasoning – the logical justification
  • outcome – the resulting action or state
  • confidence – a numerical certainty score

After validation, the handler retrieves the active knowledge-graph instance via get_graph() and delegates to graph.record_decision.


# mcp/tools/decisions.py – recording entry point

# Lines 21-40

def handle_record_decision(args: dict) -> dict:
    """Record a decision with full context into the knowledge graph."""
    required = ["category", "scenario", "reasoning", "outcome", "confidence"]
    ...
    graph = get_graph()
    decision_id = graph.record_decision(
        category=str(args["category"]),
        scenario=str(args["scenario"]),
        reasoning=str(args["reasoning"]),
        outcome=str(args["outcome"]),
        confidence=float(args["confidence"]),
        entities=args.get("entities", []),
        decision_maker=args.get("decision_maker", "mcp_client"),
        ...
    )
    ...

Source ↗

Persisting Decisions in the Vector Store

The graph.record_decision method forwards the payload to the vector-store implementation in semantica/vector_store/vector_store.py. Here, the store_decision method manages the actual persistence logic, generating embeddings and assigning immutable identifiers.

If a DecisionEmbeddingPipeline is configured, the pipeline generates dual embeddings: a semantic embedding derived from textual fields (scenario, reasoning, outcome) and a structural embedding representing the graph context. The method stores the complete metadata payload alongside these vectors and returns a unique vector ID that serves as the canonical decision identifier for all subsequent audit operations.


# semantica/vector_store/vector_store.py – core storage routine

# Lines 75-99

def store_decision(
    self,
    scenario: str,
    reasoning: Optional[str] = None,
    outcome: Optional[str] = None,
    confidence: Optional[float] = None,
    entities: Optional[List[str]] = None,
    category: Optional[str] = None,
    **additional_metadata
) -> str:
    ...
    decision_data = {
        "scenario": scenario,
        "reasoning": reasoning or "",
        "outcome": outcome or "unknown",
        "confidence": confidence or 0.5,
        "entities": entities or [],
        "category": category or "general",
        **additional_metadata
    }
    if self.decision_pipeline:
        result = self.decision_pipeline.process_decision(decision_data)
        return result["vector_id"]
    ...

Source ↗

Auditing and Tracing Decision Lineage

The decision tracking API provides several query primitives that enable agents to explore decision provenance and causal relationships. All audit operations reference the single source of truth stored in the vector store, ensuring deterministic reproducibility.

Finding Precedents and Similar Decisions

The find_precedents and query_decisions methods retrieve historically similar decisions by computing hybrid similarity scores. These functions feed the query through the same DecisionEmbeddingPipeline used during storage, comparing semantic and structural embeddings against the archived decision vectors.

Explaining Decision Rationale

The explain_decision primitive assembles human-readable explanations by retrieving the stored reasoning paths and confidence scores. Implemented in the vector store layer, this method walks the embedding graph to reconstruct the contextual basis for any recorded choice.

Causal Chain Analysis

For tracking upstream dependencies or downstream effects, the get_causal_chain method utilizes the CausalChainAnalyzer (located in semantica/context/causal_analyzer.py) to traverse decision relationships. If the analyzer is unavailable, the system falls back to graph.get_causal_chain.

Impact Analysis

The analyze_decision_impact method (also aliased as analyze_decision_influence) quantifies how a specific decision affected the knowledge graph, reporting metrics such as affected entities and policy modifications triggered by the outcome.

End-to-End Decision Flow

The complete lifecycle of a tracked decision follows this deterministic path:

  1. CLI or API invocation – The handle_record_decision function validates input parameters
  2. Graph layer processing – graph.record_decision prepares the payload and selects the storage backend
  3. Vector embedding – store_decision generates embeddings, persists metadata, and returns the vector ID
  4. Audit retrieval – Subsequent calls to find_precedents, explain_decision, or get_causal_chain retrieve vectors by ID and execute hybrid similarity or causal analysis

Because the vector ID is immutable and indexed, every audit operation can reproduce the exact state of the knowledge graph at the moment of the original decision, providing complete traceability of who, what, why, and when.

Code Examples

Record a decision via the command-line interface:


# Record a decision via the CLI

$ semantica decision record \
    --title "Approve loan extension" \
    --category finance \
    --scenario "Customer requests 6-month extension" \
    --reasoning "Credit score > 750, low utilization" \
    --outcome approved \
    --confidence 0.93

Record a decision programmatically using the convenience wrapper:


# Record a decision programmatically (quick helper)

from semantica.vector_store.decision_vector_methods import quick_decision

decision_id = quick_decision(
    scenario="Approve loan extension",
    outcome="approved",
    reasoning="Credit score > 750, low utilization",
    confidence=0.93,
    category="finance"
)
print(decision_id)   # → "vec_7f3c2a..."

Retrieve semantically similar past decisions:


# Find precedents (similar past decisions)

from semantica.vector_store.decision_vector_methods import find_precedents

precedents = find_precedents(
    query="Approve loan extension",
    limit=5,
    category="finance"
)
print(precedents)    # List of decision dicts with similarity scores

Generate a human-readable explanation:


# Explain a recorded decision

from semantica.vector_store.decision_vector_methods import explain

explanation = explain(decision_id)
print(explanation["reasoning"])
print(explanation["confidence"])

Trace causal dependencies:


# Retrieve the causal chain of a decision

from semantica.mcp.tools.decisions import handle_get_causal_chain

chain = handle_get_causal_chain({"decision_id": decision_id, "direction": "downstream"})
print(chain["chain"])

Summary

  • The decision tracking API in Semantica uses a two-layer architecture combining MCP tools with vector storage
  • Recording occurs through handle_record_decision in mcp/tools/decisions.py, which validates required fields (category, scenario, reasoning, outcome, confidence) before delegating to the graph layer
  • Persistence happens in semantica/vector_store/vector_store.py via store_decision, which generates dual semantic and structural embeddings and returns an immutable vector ID
  • Auditing capabilities include precedent search (find_precedents), explanation generation (explain_decision), causal chain traversal (get_causal_chain via CausalChainAnalyzer), and impact analysis (analyze_decision_impact)
  • All audit operations reference the same vector-store instance, ensuring deterministic traceability from a single source of truth

Frequently Asked Questions

What fields are required when recording a decision?

The decision tracking API requires five mandatory fields: category (classification), scenario (context), reasoning (justification), outcome (result), and confidence (numerical score). The handle_record_decision function in mcp/tools/decisions.py validates these fields before processing, rejecting any request missing required parameters.

How does the API ensure decision traceability?

Every decision receives an immutable vector ID upon storage in semantica/vector_store/vector_store.py. This ID serves as the canonical reference for all subsequent audit operations, including causal chain analysis and impact assessment. Because the vector store maintains both embeddings and complete metadata, the system can deterministically reproduce the knowledge graph state at the moment of decision recording.

Can decisions be queried by semantic similarity?

Yes. The find_precedents and query_decisions methods compute hybrid similarity scores by feeding queries through the DecisionEmbeddingPipeline. This pipeline generates embeddings using the same algorithm applied during initial storage, enabling retrieval of historically similar decisions based on semantic content and structural graph context rather than exact keyword matching.

What is the role of the DecisionEmbeddingPipeline?

The DecisionEmbeddingPipeline generates dual embeddings for each decision: a semantic embedding derived from textual fields (scenario, reasoning, outcome) and a structural embedding representing the decision's position within the knowledge graph. Configured in the vector store layer, this pipeline ensures that both meaning and context are preserved for similarity search and causal analysis operations.

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 →