Skip to content

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)

  1. Promote — stable LPG nodes/edges become OWL individuals/assertions.
  2. Reason — the engine's OWL-RL rules (sourced from the loaded TBox) infer new triples (transitive closure, inverses, subclass, domain/range, property chains).
  3. 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 (transitive grounded_in, grounded_insupports).
  • 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 — the Loop long-running-objective unit + submit_loop/active_loops/mark_loop_status (KG-2.78).
  • knowledge_graph/research/loop_controller.py — the one LoopController advancing all Loop kinds (research stages + develop act→validate + skill execution).
  • gateway/research_api.py — granular {prefix}/research/* typed routes (single SoT); graph_loops MCP tool — the single entrypoint for long-running objectives.
  • knowledge_graph/backends/owl/ — local owlready2 backend + Stardog.
  • knowledge_graph/backends/sparql/jena_fuseki_backend.py — optional Fuseki tier.
  • gateway/graph_api.py{prefix}/sparql route + cached bridge.
  • core/graph_compute.py::get_triples() — bulk RDF export (engine GetTriples).
  • epistemic-graph/src/reasoning.rs, src/server.rs (GetTriples) — Rust substrate.
  • core/ontology_publisher.py — bundled-ontology collection + optional Fuseki push.