Most agent stacks can tell you what happened.
Prompts, tool calls, tokens, latency, traces, even the retrieved chunks behind a given answer, all inspectable.
But six months later, when someone asks the harder question “why did the agent make this decision**?”,** the answer is a reconstruction exercise.
You search logs, replay prompts, inspect vector-store hits, and hope the underlying data has not changed since.
That is a bad architecture for an AI system making consequential decisions.
This is the problem Semantica is trying to solve, and the interesting part is the data model.
Semantica turns agent context, i.e. facts, relationships, decisions, provenance, rules and causal links into a graph you can query later.
A decision becomes a first-class object.

That changes what you can ask:
- What facts were available when this decision was made?
- Which earlier decision caused or influenced it?
- Where did those facts come from, and have they changed since?
- Have we made a similar decision before?
- What downstream decisions depended on this one?
- Did it pass a deterministic policy check?
For agents, that is a more useful primitive than memory as it is a decision graph.
The missing layer in most agent stacks
A typical production stack runs user event → agent framework → LLM → tools and APIs → vector DB → logs and traces.
It works well until the agent starts making critical decisions.
Vector DBs or tracking systems are not designed to answer: what did the system believe, what did it decide, what caused that decision, and what happened because of it?

Semantica inserts a graph-native layer into the stack:
Sources
↓ Ingest → Parse → Normalize → Split → Extract
↓ Conflict detection → Deduplication
↓ Knowledge graph
↓ Ontology + Reasoning + Provenance + Decisions
↓ Enriched context graph
↓ Vector store / Graph store / RDF store
↓ REST / MCP / CLI / Explorer / your agentThe repository ships separate modules for ingestion, extraction, graph construction, reasoning, provenance, decision intelligence, ontology management, vector search, temporal queries, export, and visualizatio.
The idea is to promote agent state to structured data.
Context graph is not better RAG
It is tempting to file Semantica under GraphRAG but that undersells it.
The core abstraction is the context graph, where entities, relationships, facts, decisions, causal links, and temporal state live in one queryable structure, with a vector store next to it for semantic recall.
You stop choosing between embeddings and graphs.
Each layer answers a different question:
- Vector retrieval: “What looks similar?”
- Context graph: “What is connected?”
- Provenance: “Where did this come from?”
- Decision intelligence: “What did we decide, and why?”
- Causal graph: “What influenced what?”
- Deterministic rules: “Which policies imply this outcome?”
- Temporal graph: “What was true at that point in time?”

Semantica makes the infrastructure around the LLM inspectable and reproducible.
Editor’s note: If you want to dive deep into Local LLMs and Agentic Stack, you can join our Agent Foundry program for hands-on, in-depth trainings.
Setup and a version caveat
pip install semantica semantica doctor
# everything, including optional integrations
pip install "semantica[all]"One caveat: this project moves fast.
Pin the version you validated and if you need unreleased behavior, install from a source checkout and pin the commit.
Quick start: turn a decision into data
from semantica.context import ContextGraph
ctx = ContextGraph(advanced_analytics=True)
decision_id = ctx.record_decision(
category="vendor_selection",
scenario="Choose a model provider for a regulated workflow",
reasoning="Provider B supports required deployment controls and data residency",
outcome="selected_provider_b",
confidence=0.92,
)
chain = ctx.trace_decision_chain(decision_id)
precedents = ctx.find_similar_decisions("regulated model-provider selection", max_results=5)
impact = ctx.analyze_decision_impact(decision_id)It looks almost too simple.
The point is what record_decision() means architecturally: you stop dumping free-form reasoning into a log line and hoping your observability backend stays the canonical record forever.
You explicitly model the category, scenario, rationale, outcome, confidence, and links to other decisions.
One warning: Do not use the reasoning field to persist hidden model chain-of-thought, use it for the rationale your application is prepared to defend: evidence considered, policy applied, threshold crossed, human override.
That is more useful in production anyway.
Causal decision chains
One decision is interesting but a chain is infrastructure.
Take an agentic procurement workflow: a security agent scores a vendor, a compliance agent checks residency, a sourcing agent selects, a finance agent approves the contract.
Most systems store four separate traces.
Semantica makes the relationships explicit:
security_id = ctx.record_decision(
category="security_review",
scenario="Evaluate Vendor B for production AI workload",
reasoning="SOC 2 controls verified; private networking available",
outcome="security_approved",
confidence=0.95,
)
selection_id = ctx.record_decision(
category="vendor_selection",
scenario="Choose provider after security and compliance review",
reasoning="Vendor B passed required controls and residency constraints",
outcome="selected_vendor_b",
confidence=0.91,
)
contract_id = ctx.record_decision(
category="contract_approval",
scenario="Approve annual Vendor B platform agreement",
reasoning="Selected vendor is approved; budget within threshold",
outcome="contract_approved",
confidence=0.97,
)
ctx.add_causal_relationship(security_id, selection_id, relationship_type="CAUSED")
ctx.add_causal_relationship(selection_id, contract_id, relationship_type="INFLUENCED")
why_contract = ctx.trace_decision_chain(contract_id)
blast_radius = ctx.analyze_decision_impact(selection_id)The API currently supports three relationship types: CAUSED, INFLUENCED, and PRECEDENT_FOR.
Now imagine Vendor B fails a security review next quarter.
Instead of “which traces mentioned Vendor B?”, you ask: which later decisions were influenced by the original selection?

That is blast-radius analysis for decisions, exactly the operation agents need as they move from copilots to systems that approve, route, buy, deploy, and reject on their own.
Build the graph from real data
Decision records get more valuable when they attach to a real knowledge graph instead of handwritten facts.
Semantica ships ingestors for files, web content, databases, streams, Git repositories, email, Parquet, Snowflake, and Databricks:
from semantica.ingest import FileIngestorfrom semantica.kg import GraphBuilder
sources = FileIngestor().ingest_directory("./contracts/", recursive=True)
kg = GraphBuilder(merge_entities=True, enable_temporal=True).build(sources)The pipeline normalizes, splits, extracts entities and relations, flags conflicting facts, deduplicates, and builds the graph.

Provenance is where why becomes defensible
A causal chain tells you Decision B depended on Decision A but you still need to know what evidence fed Decision A.
Semantica’s provenance module is built on W3C PROV-O, the standard ontology for representing provenance:
from semantica.provenance import ProvenanceManager
prov = ProvenanceManager(storage_path="./provenance.db")prov.track_entity(
entity_id="vendor_b",
source="security/vendor_b_assessment_2026.pdf",
metadata={"page": 12, "extractor": "NamedEntityRecognizer", "confidence": 0.98},
)
lineage = prov.get_lineage("vendor_b")Causality explains dependency and provenance explains origin.
You need both to reconstruct a decision without guessing.
Provenance entries are now hash-chained, each carries a sequence ID and a checksum link to the previous entry, and verify_chain() detects breaks in that history.
Facts can be invalidated instead of hard-deleted:
integrity = prov.verify_chain()
prov.invalidate( "vendor_b",
agent_id="human_security_reviewer",
reason="Certificate expired; prior approval no longer valid",
)A mutable approved=false row tells you the current truth.

An audit ledger also tells you the approval used to exist, who revoked it, and why.
That is a different requirement, and the right one for high-stakes agent state.
Deterministic reasoning: keep policy out of the prompt
Semantica ships forward chaining, Rete, Datalog, and SPARQL engines.
The point is: do not ask an LLM to improvise rules your system already knows.
from semantica.reasoning import ReteEngine, Rule, Fact, RuleType
engine = ReteEngine()engine.build_network([
Rule(
rule_id="manual_review",
name="Escalate high-value restricted transactions",
conditions=[
{"field": "amount", "operator": ">", "value": 10000},
{"field": "risk_tier", "operator": "in", "value": ["high", "critical"]},
],
conclusion="require_manual_review",
rule_type=RuleType.IMPLICATION,
)
])
engine.add_fact(Fact("tx_001", "transaction", [{"amount": 25000, "risk_tier": "high"}]))
matches = engine.match_patterns()If a policy decision came from a deterministic rule, you record the rule ID in the decision metadata and can reproduce the result later.

The LLM still extracts facts and proposes actions, the policy gate stops being prompt-shaped English.
One caveat: the Rete condition matcher is intentionally simple and you should validate match_patterns() against your real rule set before wiring it into a production compliance gate.
Do not turn a demo rule engine into a regulatory control without tests.
Standards outlive frameworks
Semantica leans on W3C PROV-O for provenance, RDF for representation, SPARQL for querying, SHACL for graph constraints, and OWL for ontologies.
That looks unfashionable next to the latest agent SDK, which is exactly why it is useful.
Agent frameworks churn but audit requirements do not.
Your regulator does not care which agent loop produced the decision.
Open standards keep the record decoupled from the model provider and framework of the month.
MCP turns the graph into agent tooling
Semantica exposes everything through a Model Context Protocol server:
python -m semantica.mcp_server
# or
semantica-mcp{ "mcpServers": { "semantica": { "command": "python", "args": ["-m", "semantica.mcp_server"] } }
}The server exposes entity and relation extraction, decision recording and queries, precedent search, causal chains, graph edits, reasoning, analytics, and export.
Your agent calls a standardized tool to record or inspect state.
Where it sits in your stack
Semantica positions itself underneath as the persistent context and accountability layer: agent runtime on top, and decisions, causal links, provenance, reasoning, and constraints in the middle, and graph and vector stores below.

While LLM stays probabilistic, the state around it stops being ephemeral.
Observability is not enough
You still need traces, metrics, evals, and token accounting but observability is execution-centric: it tells you what the software did during one run.
A decision graph is domain-centric: it records what the system decided as part of the state of the business.

Consider an underwriting agent.
A trace shows the model called a credit API and returned approved.
A decision graph represents:
Applicant ├── income → $85k ├── DTI → 31% └── credit_history → clean_36_months
Decision: proceed_to_underwriting ├── based_on → applicant facts ├── sourced_from → application + credit report └── CAUSED → underwriting decision
Decision: approved ├── governed_by → lending policy └── INFLUENCED → interest-rate decision
You can inspect that months later without replaying the original model conversation.
Enterprises already treat orders, transactions, approvals, and accounting events as durable domain entities.
AI decisions should join them.
Concluding thoughts
The next problem is making agents accountable over time rather than explainable.
Accountable as architecture: decision → causal parents → evidence → provenance → policy evaluation → downstream effects → later corrections.
Semantica is one of the more complete open-source attempts at packaging those primitives into one layer.