OWL/RDF Layer — always-on, local, fast (CONCEPT:KG-2.7)¶
OWL/RDF is a core, always-on layer, not an enterprise add-on. It works identically over any configured LPG storage backend (epistemic-graph, LadybugDB, pg-age/AGE, Neo4j, FalkorDB): it consumes the bundled ontologies, infers new relationships, back-feeds them durably into the LPG store, validates writes with SHACL, and answers SPARQL from a local endpoint with zero external dependencies. Apache Jena Fuseki / Stardog are an optional enterprise scale-out (federation, a durable triplestore) — never required, and never on the critical path for the zero-dep "tiny" / Raspberry-Pi profile.
Why local-first¶
The fast/light inference substrate already exists: the Rust epistemic-graph
engine ships a native OWL-RL reasoner (reasoning.rs / RunDatalogReasoning:
subclass, subproperty, transitive, symmetric, inverse, domain/range,
property-chains) plus VF2 pattern matching and a bulk GetTriples RDF-export op.
So inference and SPARQL materialization run in-process over UDS/MessagePack —
no triplestore deployment, no network hop.
Architecture¶
graph TB
ING["Ingest / write path"] --> SH["SHACL gate\n(governance + value-type shapes)\nCONCEPT:KG-2.39"]
SH --> LPG["LPG store\n(epistemic_graph | ladybug | pg-age/AGE | neo4j | falkordb)"]
subgraph "OWL/RDF layer — always-on, local"
TBOX["Bundled ontologies (TBox)\n30× ontology*.ttl\nloaded at startup"]
REASON["epistemic-graph reasoner\nRunDatalogReasoning (OWL-RL)\nCONCEPT:KG-2.17"]
BRIDGE["OWLBridge\npromote → reason → downfeed"]
SPARQL["Local SPARQL endpoint\nGET/POST {gateway}/api/sparql"]
end
LPG --> BRIDGE
TBOX --> REASON
BRIDGE --> REASON
REASON -->|inferred triples| BACKFEED["Durable back-feed\nlink_nodes(inferred=true)"]
BACKFEED --> LPG
LPG -->|GetTriples bulk export\n(fast path)| MAT["rdflib materialization"]
MAT --> SPARQL
BRIDGE -. optional .-> FUSEKI["Jena Fuseki / Stardog\n(enterprise scale-out)"]
The cycle (OWLBridge)¶
- Promote — stable LPG nodes/edges become OWL individuals/assertions.
- Reason — the engine's OWL-RL rules (sourced from the loaded TBox) infer new triples (transitive closure, inverses, subclass, domain/range, property chains).
- Downfeed (durable) — inferred edges are written back into the LPG store
via the active engine's
link_nodes, provenance-tagged (inferred=true,inferred_from=owl_reasoner,inference_type). This is synchronous and idempotent (it previously used an asyncio queue that silently no-op'd without a running event loop, so inferred triples never persisted).
Local SPARQL¶
{gateway}/api/sparql (GET ?query= or POST {"query": …}) is served by
OWLBridge.query_sparql and returns W3C SPARQL-JSON. Materialization uses a
fast path: the engine's GetTriples op exports the whole graph as
[subject, predicate, object] triples in one call (edges → (s, rel, o),
node type → (id, rdf:type, label), scalar props → (id, prop, literal)), which
feeds rdflib's mature SPARQL engine — rather than reimplementing SPARQL in Rust or
making per-node round-trips. It falls back to per-node iteration on engines without
GetTriples, and works without owlready2 (the rdflib path needs only rdflib).
SHACL validation¶
The pre-commit SHACL gate (pipeline/phases/shacl_gate.py, on by default) validates
materialized writes against the bundled governance.shapes.ttl and value-type
generated shapes (ValueType.to_shacl(), CONCEPT:KG-2.39) — so value-type
constraints (EmailAddress, Percentage, …) are enforced alongside governance rules.
Violating nodes are quarantined, not silently dropped.
Deployment posture¶
| Profile | OWL reasoning | SPARQL | Triplestore |
|---|---|---|---|
| tiny (Pi-3, zero-dep) | ✅ local (engine OWL-RL) | ✅ local /api/sparql |
none |
| single-node prod | ✅ local | ✅ local | optional |
| enterprise | ✅ local | ✅ local | + Jena Fuseki / Stardog (federation), KG_FUSEKI_PUBLISH=1 |
Reasoning as the research engine — one ontology over the whole ecosystem¶
agent-utilities maps the entire ecosystem — agent-packages/agents/* + services/* +
enterprise systems + research papers — into ONE ontology-driven knowledge graph
(the canonical ArchiMate upper ontology, KG-2.9; ecosystem_topology; Egeria SoR).
OWL/RDF reasoning is not a post-processing add-on here: it is the engine of research
and workflow execution. Its value is extrapolating relationships that did not exist
before reasoning — transitive/symmetric/inverse/domain-range/property-chain closures and
subClassOf/equivalentClass — across the whole ecosystem at once, so a research concept
can be inferred to relate to a deployed service or an agent capability, not siloed.
Every long-running objective is a Loop (KG-2.78) — kind research, develop, or
skill — and the one LoopController (formerly the "golden loop") advances every
active Loop through a single hot path: research loops acquire sources + reason, develop
loops run act→validate (their validation_cmd), skill loops execute their skill /
skill-workflow. There is no separate goal-runner or research-runner — the goal system is a
thin adapter onto LoopController.run_loop. The single entrypoint is the graph_loops
MCP tool (submit / list / run / drive / cancel); submit_loop is the shared
creation path for goals, research topics, failure gaps and skill executions.
One persistence model. Goal state is not a separate SQLite/Postgres goals table —
it was collapsed onto the KG Loop node (a develop Concept): status, owner, totals and
the full iteration record are node properties, so the KG (the durable backend) is the
single source of truth. /goals REST, graph_goals, the dispatch worker's claim, and
restart rehydration all read/write that one node; a running claim is excluded from the
daemon's active_loops intake so a goal is never double-driven.
Durable checkpointing is cross-cutting, not goal-specific. LoopController.run_loop
drives one Loop of any kind to completion durably: it resumes from the last checkpoint
(DurableExecutionManager, backend-selected SQLite/Postgres via state_store, OS-5.16),
runs each iteration under an idempotency key (at-least-once retries, exactly-once effect),
and honors corrigible interruption (a fleet pause/kill signal → checkpoint and yield,
SAFE-1.5). The same durable engine that runs autonomous goals therefore resumes a
research or skill Loop after a crash.
The research path runs the OntologyReasoningDriver (KG-2.79) each cycle: it promotes
the loop's working set + the surrounding ecosystem subgraph, runs OWLBridge.run_cycle
(promote → reason → downfeed), and harvests the newly-inferred cross-domain relationships
back as fresh research topics — a closed extrapolation loop. This replaced the old
one-shot enrichment that ran reasoning and never consumed the inferences.
Agent-Native Research Artifacts (ARA, KG-2.80) are the OWL-native output: a 4-layer
artifact (/logic claims, /src code specs, /trace exploration DAG with dead-ends and
pivots, /evidence raw outputs) whose layers are first-class ontology classes + typed
object-properties (research_artifact/claim/code_spec/evidence/exploration_node;
contains/grounded_in/implemented_by). grounded_in is transitive with a supports
inverse, so reasoning chains a claim → evidence → ecosystem code/service automatically —
which is why we extrapolate cross-domain links from the first compiled artifact rather
than only "at critical mass". The ARA Compiler grounds each claim to the ecosystem it
touches; the ARA Seal verifies it (L1 = SHACL + interface conformance + OWL consistency,
L2 = rigor, L3 = exec-reproducibility with /evidence withheld via markings, KG-2.46) and
emits a signed seal_certificate. Both surfaces are exposed identically — the
research_artifact MCP tool and POST {prefix}/research/* REST — over one shared service.
Key modules¶
knowledge_graph/core/owl_bridge.py— promote/reason/downfeed +query_sparql; ARA forensic-edge characteristics (transitivegrounded_in,grounded_in↔supports).knowledge_graph/research/ara/—reasoning_driver(reasoning-as-engine, KG-2.79),artifact/compiler/seal/exploration/live_manager/service(ARA, KG-2.80).knowledge_graph/research/loops.py— theLooplong-running-objective unit +submit_loop/active_loops/mark_loop_status(KG-2.78).knowledge_graph/research/loop_controller.py— the oneLoopControlleradvancing all Loop kinds (research stages + develop act→validate + skill execution).gateway/research_api.py— granular{prefix}/research/*typed routes (single SoT);graph_loopsMCP tool — the single entrypoint for long-running objectives.knowledge_graph/backends/owl/— localowlready2backend + Stardog.knowledge_graph/backends/sparql/jena_fuseki_backend.py— optional Fuseki tier.gateway/graph_api.py—{prefix}/sparqlroute + cached bridge.core/graph_compute.py::get_triples()— bulk RDF export (engineGetTriples).epistemic-graph/src/reasoning.rs,src/server.rs(GetTriples) — Rust substrate.core/ontology_publisher.py— bundled-ontology collection + optional Fuseki push.