Data Access Wrappers — Engine Map
This document inventories every way the OntoBricks platform reads (or asks the backend to read) data, and pins each user-facing feature to the underlying…
This document inventories every way the OntoBricks platform reads (or asks the backend to read) data, and pins each user-facing feature to the underlying query engine(s) it ends up using.
The goal is to answer, for any feature in the UI, the MCP server, or the Graph Chat assistant: "when I click this, which engine actually runs?"
1. The five access wrappers
OntoBricks exposes data through five layered wrappers. Three are user-facing languages, two are engine-facing dialects the platform translates down to.
| Wrapper | Layer | Implementation | Where the bytes finally land |
|---|---|---|---|
| REST | user-facing | api/external_app.py, api/routers/..., api/routers/internal/dtwin.py |
Calls into Python services (DigitalTwin, DomainQueryService, registry, …) |
| GraphQL | user-facing | back/core/graphql/GraphQLSchemaBuilder.py, ResolverFactory.py, back/fastapi/graphql_routes.py |
Resolvers internally call SPARQL / triples-find → Spark SQL |
| SPARQL | user-facing (read-only in chat) | back/core/w3c/sparql/SparqlTranslator.py, SparqlQueryRunner.py, DomainQueryService.py |
Translated to Spark SQL via R2RML mappings |
| Spark SQL | engine-facing | back/core/graphdb/delta/DeltaFlatStore.py |
Native execution on Databricks SQL Warehouse against Delta views in Unity Catalog |
| Cypher (reserved for future engines) | engine-facing | back/core/graphdb/GraphDBBackend.py + concrete engines under back/core/graphdb/<engine>/ (supports_cypher = True, query_dialect = "cypher") |
None of the currently shipped engines speaks Cypher — Lakebase Postgres is SQL-only. The capability flags are kept as a seam for plugging in Cypher / Gremlin / SPARQL-store engines. |
Supporting W3C standards (not query languages)
These layers shape queries but don't run them — they are mappings, constraints, and rule definitions:
| Standard | Role | Where |
|---|---|---|
| R2RML | Maps relational tables → RDF; consumed by SparqlTranslator to lift SPARQL to Spark SQL |
back/core/w3c/r2rml/ |
| SHACL | Constraint validation over RDF (data quality) | back/core/w3c/shacl/SHACLService.py |
| OWL / RDFS | Schema definition + entailment (OWLRLReasoner materializes derived triples) |
back/core/w3c/owl/, back/core/reasoning/OWLRLReasoner.py |
| SWRL | Rule language; compiled to SQL via SWRLSQLTranslator (Spark SQL on Delta, Postgres SQL on Lakebase). The query_dialect flag on GraphDBBackend reserves a slot for a future Cypher translator. |
back/core/reasoning/SWRL*.py |
2. Storage backends — which engine speaks which language
Which engine actually runs your query depends on the domain's configured triple-store backend (GraphDBFactory.create(...)):
| Layer | Storage | Native engine | SPARQL path | Cypher path |
|---|---|---|---|---|
Delta engine (DeltaFlatStore) |
Delta view in Unity Catalog | Spark SQL (Databricks SQL Warehouse) | SPARQL → Spark SQL via R2RML | n/a |
Lakebase engine (LakebaseFlatStore) |
Lakebase Postgres flat table | Postgres SQL | SPARQL → engine SQL | Reserved for future Cypher engines |
The selection is made in back/core/graphdb/GraphDBFactory.py. Both engines share the single GraphDBBackend contract: the Delta view is the governance-controlled snapshot, and the Lakebase engine is the queryable mirror used by the Knowledge Graph, reasoning and BFS / cohort helpers. The user-facing wrappers (REST / GraphQL / SPARQL) don't change when the engine is swapped.
GraphDB engines.
GraphDBBackendis the abstract base class; concrete engines live underback/core/graphdb/<engine>/. The currently shipped engine is Lakebase Postgres (back/core/graphdb/lakebase/); additional engines (e.g. KuzuDB, Neo4j, Memgraph) can be plugged in viaGraphDBFactoryusing the_starter_kit/ExampleStore.pytemplate, without changing any of the user-facing wrappers above.
3. Decision tree — which wrapper fires for what?
"I want to ..."
│
┌─────────┴──────────────────────────────────────┐
│ │
"... explore / browse / mutate" "... read graph data"
the registry, ontology, │
mapping, permissions │
│ ┌────────────┼────────────────┐
│ │ │ │
REST SPARQL GraphQL Cypher
(/api/v1/* or /dtwin/*) (free-form (typed, (graph traversal,
triples, nested, SWRL rules)
aggregates, schema-driven) │
analytics) │
Internal only
(GraphDB engine
+ reasoning)
4. UI features — engine map
Pages live under src/front/templates/ and src/front/static/<page>/js/.... Each row maps a UI feature to the wire protocol it speaks (column Wrapper) and the engine that ultimately runs (column Engine).
4.1 Registry & Domain
| UI Feature | Page / JS file | Endpoint(s) | Wrapper | Engine |
|---|---|---|---|---|
| Browse / open / create / save domain | Registry modal (partials/layout/registry_modal.html), templates/domain.html |
GET/POST /api/v1/domain/..., /settings/registry/..., /domain/... |
REST | Python services (DomainService, RegistryService); files on UC Volumes |
| Schedule (background actions) | settings (Automation → Scheduler) |
/settings/schedules, /settings/cohort-schedules |
REST | Python BuildScheduler + Databricks Jobs SDK |
| Cockpit / readiness | domain-validation |
GET /api/v1/domain/design-status |
REST | Python aggregator over OWL / R2RML / metadata |
| Data Sources (UC tables preview) | domain-metadata |
Internal REST → databricks-sql-connector |
REST → Spark SQL | Spark SQL on UC tables (sample queries) |
| Data source deletion guard | domain-metadata |
POST /domain/metadata/removal-impact |
REST | Mapping.find_mappings_referencing over the session assignment (no warehouse call) |
| Metadata refresh diff preview | domain-metadata |
POST /domain/metadata/update-async → GET /tasks/{id} |
REST → Spark SQL | compute_column_diff over the pre-merge snapshot; applied only after the user confirms |
| Versions | domain-versions |
/api/v1/domain/versions |
REST | UC Volume listing |
4.2 Ontology Designer
| UI Feature | JS file | Endpoint(s) | Wrapper | Engine |
|---|---|---|---|---|
Visual ontology editor (Model, Entities, Relationships, Groups, Business Views) |
ontology-design.js, ontology-shared-panels.js, ontology-groups.js |
Internal REST /ontology/... |
REST | Python ontology object model |
| OWL viewer / generator | ontology-owl.js, agent OWLGenerator |
/ontology/owl/..., /agents/owl-generator/run |
REST | OntologyParser, OntologyGenerator (rdflib) |
| Import (OWL, FIBO, CDISC, IOF) | ontology-import.js |
/ontology/import/* |
REST | rdflib parsers |
| Generate (Wizard) | ontology-wizard.js |
LLM endpoint via agent_owl_generator |
REST → LLM | Databricks Foundation Model API + tool-calling |
| Data Quality rules editor | ontology-dataquality.js |
/ontology/dataquality/... |
REST | SHACL (SHACLService) on the in-memory ontology |
| Business Rules (SWRL) editor | ontology-business-rules.js |
/ontology/swrl/... |
REST | SWRLParser, validated against ontology |
| Expressions & Axioms | ontology-axioms.js |
/ontology/axioms/... |
REST | OWL axiom storage |
4.3 Mapping (R2RML)
| UI Feature | JS file | Endpoint(s) | Wrapper | Engine |
|---|---|---|---|---|
| Mapping designer / manual mapping | mapping-design.js, mapping-manual.js |
/mapping/... |
REST | R2RMLGenerator |
| Auto-Map (LLM) | mapping-autoassign.js, agent AutoAssignment |
/agents/auto-assignment/run |
REST → LLM | Databricks FM API; agent samples UC tables via Spark SQL through databricks-sql-connector |
| Diagnostics | mapping-diagnostics.js |
/mapping/diagnostics/* |
REST | Python validator |
| Source schema drift | mapping-design.js, mapping-diagnostics.js |
GET /mapping/schema-drift |
REST | One DESCRIBE per distinct source table via UnityCatalog.get_table_columns |
| R2RML view | mapping-r2rml.js |
/mapping/r2rml/raw |
REST | rdflib serializer |
| Spark SQL preview | mapping-sparksql.js |
POST /dtwin/translate |
REST → SPARQL translation only | SparqlTranslator (no execution; shows the generated SQL) |
4.4 Knowledge Graph (the core read surface)
This is where users actually query the graph viewer. Graph Viewer, GraphQL, and Graph Chat all sit under the Knowledge Graph menu; they hit different wrappers but eventually share the same Delta / GraphDB storage.
| UI Feature | JS file | Endpoint(s) | Wrapper | Engine |
|---|---|---|---|---|
| Insight / Overview | query-sync.js (stats panel), query.js |
GET /dtwin/sync/stats, GET /dtwin/sync/status |
REST | Spark SQL aggregates on the Delta view, or Postgres SQL aggregates on the Lakebase Graph DB |
| Graph Viewer (Sigma.js viz) | query-sigmagraph.js, query-d3graph.js |
GET /dtwin/groups, POST /dtwin/sync/filter, GET /dtwin/sync/stats?refresh=true, POST /dtwin/clusters/detect, GET /dtwin/reasoning/inferred |
REST | Each /sync/filter call is a SPARQL under the hood, translated to Spark SQL (Delta) or Postgres SQL (Lakebase Graph DB) |
| Graph Viewer → SPARQL panel | query-execute.js |
POST /dtwin/execute |
SPARQL | SparqlQueryRunner → Spark SQL on the SQL Warehouse (Delta view) |
| GraphQL | query-graphql.js |
GET /graphql/{domain}/schema, POST /graphql/{domain}, GET /graphql/settings/depth |
GraphQL | Schema generated from OWL; resolvers call DomainQueryService → SPARQL → Spark SQL |
| Graph Chat | query-chat.js, agent agent_dtwin_chat |
POST /dtwin/assistant/chat, GET/DELETE /dtwin/assistant/history |
REST → LLM tool-calling | LLM calls REST + GraphQL + SPARQL tools (see §6) |
| Build (materialize triple store) | query-sync.js |
POST /dtwin/sync/start, POST /dtwin/sync/load |
REST | _BuildPipeline runs the R2RML SQL on the Warehouse (Delta CREATE OR REPLACE VIEW) and streams the rows into the active Graph DB engine via bulk_insert_iter (COPY FROM STDIN on Lakebase) |
| Data Quality (SHACL execution) | query-dataquality.js |
POST /dtwin/dataquality/start, POST /dtwin/dataquality/execute |
REST | SHACLService translates shapes to SQL SELECTs that find violations |
| Inference (Reasoning) | query-reasoning.js, query-purge-inferences.js |
POST /dtwin/reasoning/start, POST /dtwin/reasoning/materialize, GET/DELETE /dtwin/reasoning/inferred |
REST | ReasoningService: OWL-RL closure (rdflib) + SWRL rules compiled to SQL (Spark SQL on Delta, Postgres SQL on Lakebase) or SPARQLRuleEngine; GET counts the generated companion shared by reasoning and cohorts, while DELETE truncates only that companion |
| Cockpit → Knowledge Graph | domain-validation.js |
GET /validate/detailed, GET /dtwin/reasoning/inferred |
REST | Displays mapped graph health plus the live combined materialized reasoning-and-cohort count; unsupported source-indistinguishable backends return the count as unavailable |
GET /dtwin/reasoning/inferred is a lightweight status call: it returns graph_name, materialized_inference_count, and purge_supported without serializing inferred triples. The nested reasoning.inferred_count and empty reasoning.inferred_triples fields remain for compatibility.
4.5 Settings / Teams / Help
| UI Feature | Endpoint(s) | Wrapper | Engine |
|---|---|---|---|
| Settings (warehouse, profile) | /settings/* |
REST | Python config service |
| Teams (domain roles) | /settings/teams |
REST | PermissionService + App ACL principals |
| Help / docs modal | static templates | n/a | n/a |
5. MCP server (src/mcp-server) — engine map
The MCP server is a thin proxy over the OntoBricks public REST + GraphQL surface (/api/v1/... and /graphql/...). It runs as its own Databricks App, authenticates with an M2M OAuth token, and uses httpx.AsyncClient. It never speaks SPARQL or Cypher directly.
| MCP Tool | Endpoint hit | Wrapper | Engine |
|---|---|---|---|
list_domains |
GET /api/v1/domains |
REST | UC Volume listing |
list_domain_versions |
GET /api/v1/domain/versions |
REST | UC Volume listing |
get_design_status |
GET /api/v1/domain/design-status |
REST | Python aggregator |
describe_ontology |
GET /api/v1/domain/ontology + GET /api/v1/domain/classes |
REST | Ontology schema only (no graph): structured class summary + raw OWL/Turtle |
select_domain |
GET /api/v1/digitaltwin/status + GET /api/v1/domain/classes |
REST | DeltaFlatStore status (Spark SQL) or GraphDB status; class attachments cached for [Context] blocks |
list_entity_types |
GET /api/v1/digitaltwin/stats |
REST | Spark SQL GROUP BY on the triple view (Delta) or GraphDB MATCH counts |
describe_entity |
GET /api/v1/digitaltwin/triples/find |
REST | SPARQL-style BFS internally → Spark SQL (Delta) or Cypher (GraphDB) |
get_entity_context |
GET /api/v1/digitaltwin/nodes/context |
REST | Class resolution + optional Spark SQL dataset read and bridge traversal |
compute_virtual_attributes |
GET /api/v1/digitaltwin/nodes/virtual-attributes |
REST | Unity Catalog function call for declared virtual attributes |
invoke_entity_action |
POST /api/v1/digitaltwin/nodes/action |
REST | Unity Catalog function call via SQL warehouse |
get_status |
GET /api/v1/digitaltwin/status |
REST | Same as select_domain |
get_graphql_schema |
GET /graphql/{domain}/schema |
GraphQL | GraphQLSchemaBuilder (no DB hit; SDL only) |
query_graphql |
POST /graphql/{domain} |
GraphQL | Resolvers → SPARQL → Spark SQL |
ontobricks://* resources |
various | REST / GraphQL | Same as the equivalent tools |
Per-domain policy. The first three tools are registry-level and always available. The rest are domain-scoped: a domain can hide any of them from Domain → Information → MCP, and can set its dataset / bridges / actions attachments to disabled. Because the MCP server is a proxy, the disabling is enforced at the endpoints above, not in the proxy —
nodes/contextanddomain/classesomit the element, andnodes/actionrefuses. Hiding a tool is presentation on top of that, so a stale client that calls a hidden tool anyway gets a refusal instead of data. See Per-domain MCP policy.
Ontology-only domains. A domain can be published with an ontology but no Knowledge Graph build (no mapping, no graph).
GET /api/v1/domainsflags it withhas_graph: false; onselect_domainthe MCP server hides every graph tool and exposesdescribe_ontologyalone (plus the four registry-level tools).describe_ontologyneeds no graph — it serves the ontology schema — so it is always available and the call-time guard refuses the graph tools for such a domain even if a stale client calls them.
Note. MCP and the external REST/GraphQL API only see versions whose lifecycle status is PUBLISHED — they default to the numeric-latest PUBLISHED version and reject explicit requests for
DRAFT/IN-REVIEWversions. A version becomes servable by transitioning it DRAFT → IN-REVIEW → PUBLISHED from Registry → Browse (this replaces the former "Active"/mcp_enabledtoggle). To query an unsaved working session, use the Graph Chat (next section), which talks to the session-aware/dtwin/...internal routes instead.
6. Graph Chat (src/agents/agent_dtwin_chat) — engine map
The Graph Chat agent runs inside the OntoBricks process, talks to loopback (http://localhost:8000), forwards user session cookies + the Databricks Apps X-Forwarded-* headers, and targets the internal session-aware /dtwin/... routes. This means it works on unsaved domains and (uniquely) speaks SPARQL.
| Chat Tool | Endpoint hit | Wrapper | Engine |
|---|---|---|---|
list_entity_types |
GET /dtwin/sync/stats |
REST | Spark SQL stats (Delta) or GraphDB stats |
get_status |
GET /dtwin/sync/status |
REST | Triple store status |
describe_entity |
GET /dtwin/triples/find |
REST | Bounded BFS → Spark SQL (Delta) or Cypher (GraphDB) |
get_graphql_schema |
GET /dtwin/graphql/schema |
GraphQL | Schema built from in-session ontology (no DB) |
query_graphql |
POST /dtwin/graphql/execute |
GraphQL | Resolvers → SPARQL → Spark SQL |
run_sparql |
POST /dtwin/execute |
SPARQL (read-only — DROP/DELETE/INSERT/CREATE/CLEAR/LOAD/COPY/MOVE/ADD blocked by regex) | SparqlQueryRunner → Spark SQL on the SQL Warehouse |
The system prompt steers the LLM's protocol choice:
- "Tell me about X" →
describe_entity(REST/triples) - "How many / group by / aggregate" →
run_sparql(SPARQL → Spark SQL) - "Customer + orders + products in one payload" →
get_graphql_schemathenquery_graphql
7. Other LLM agents — engine map
These agents do not query the triple store at runtime; they operate on the design-time ontology / metadata.
| Agent | Purpose | Tools call | Wrapper | Engine |
|---|---|---|---|---|
agent_owl_generator |
Build an OWL ontology from metadata + documents | metadata.list_tables, metadata.preview_table, documents.read, ontology.write_owl |
REST + Spark SQL (samples) | databricks-sql-connector against UC tables, plus rdflib write |
agent_auto_assignment |
Map ontology entities to Spark SQL queries | tables.list, tables.sample, mapping.write |
REST + Spark SQL (samples) | Same as above; output stored as R2RML |
agent_auto_icon_assign |
Pick emojis for entities | Inspects ontology + metadata | REST | None — generation only |
agent_ontology_assistant |
Conversational ontology editing | Dozens of tools mutating the in-session ontology | REST | Python ontology object model |
agent_dtwin_chat |
Conversational graph querying | See §6 | REST + GraphQL + SPARQL | Spark SQL + Cypher (engine-side) |
Document reading (documents.read / read_document)
Both agent_owl_generator and agent_business_rules_generator read uploaded domain documents from the UC Volume via read_document:
- Plain text (
.txt,.md,.json,.csv,.xml) is fetched through the Files API and decoded as UTF-8. - Binary documents (
.pdf,.docx,.pptx, images) are converted to markdown on the fly using the Databricksai_parse_documentSQL function (output schema pinned to v2.0):SELECT to_json(ai_parse_document(content, map('version', '2.0'))) FROM READ_FILES(<volume path>, format => 'binaryFile'). This runs on the configured SQL warehouse, so the warehouse identity (app service principal or user) must haveREAD VOLUMEon the documents volume. The function returns aVARIANT(output schema v2.0, verified live): text is read fromdocument.elements[].content(figures expose an AI-generateddescription);document.pages[]only carriesid/image_uri. The extractor prefers elements and keeps page-content / markdown-blob fallbacks for other schema versions. The extraction engine is a generic, reusable class —back.core.databricks.DocumentExtractor(src/back/core/databricks/DocumentExtractor.py, exposingsupports()/is_available()/extract()/extract_text_from_parsed()) — so it can be used outside the agents and swapped for a different parser without changing callers. - When no SQL warehouse is configured, binary documents are skipped (the tool returns an explanatory message) and generation proceeds from metadata + text documents only. Parsed text is cached per file for the duration of an agent run and truncated to the per-document character cap.
8. Reasoning engine — engine map
The reasoning pipeline (back/core/reasoning/) chooses a translation target based on the active triple-store backend's query_dialect.
| Component | Input | Compiled to | Engine |
|---|---|---|---|
OWLRLReasoner |
OWL 2 RL fragment + facts | RDF graph operations (rdflib) | Python in-memory; results materialized to triple store via Spark SQL or GraphDB bulk insert |
SWRLEngine + SWRLSQLTranslator |
SWRL rules | SQL | Databricks SQL Warehouse on the Delta view, and the Lakebase Postgres Graph DB engine. Future Cypher / Gremlin engines can plug in their own SWRL*Translator. |
SPARQLRuleEngine |
SPARQL CONSTRUCT rules |
SPARQL → Spark SQL | Same as SPARQL execution path |
DecisionTableEngine |
Decision tables | Spark SQL | Databricks SQL Warehouse |
AggregateRuleEngine |
Aggregate rules | Spark SQL | Databricks SQL Warehouse |
9. Three end-to-end query flows
9.1 User clicks Graph Chat → "How many Customers per Country?"
Browser ──POST /dtwin/assistant/chat──▶ api/routers/internal/dtwin.py
│
▼
agent_dtwin_chat.engine.run_agent
│
│ tool_call: run_sparql
▼
POST /dtwin/execute (loopback HTTP, session cookies)
│
▼
SparqlTranslator (SPARQL → Spark SQL via R2RML)
│
▼
Databricks SQL Warehouse on Delta view
│
▼
rows → markdown table → reply
Wrappers in play: REST → SPARQL → Spark SQL.
9.2 External LLM (Cursor) calls MCP query_graphql
Cursor (stdio) ──FastMCP──▶ src/mcp-server/server/app.py
│
▼
POST /graphql/{domain} (httpx, M2M OAuth bearer)
│
▼
back/fastapi/graphql_routes.py → ResolverFactory
│
▼
DomainQueryService (SPARQL)
│
▼
Databricks SQL Warehouse on Delta view
Wrappers in play: REST (transport) → GraphQL (query) → SPARQL → Spark SQL.
9.3 User opens Graph Viewer tab and applies a filter
Browser ──POST /dtwin/sync/filter──▶ api/routers/internal/dtwin.py
│
▼
DigitalTwin.filter()
│
│ backend = "view" backend = "graph"
▼ ▼
SparqlTranslator GraphDBBackend.query(...)
(SPARQL → Spark SQL) (e.g. Lakebase Postgres)
│ │
▼ ▼
Databricks SQL Warehouse Lakebase flat table
(Postgres SQL)
│ │
└──────► triples ◀───────────┘
│
▼
Sigma.js renders the graph
Wrappers in play: REST → (SPARQL → Spark SQL on Delta) and Postgres SQL on the Lakebase Graph DB.
10. TL;DR matrix — what each surface exposes
| Surface | REST | GraphQL | SPARQL | Spark SQL (Delta) | Postgres SQL (Lakebase) |
|---|---|---|---|---|---|
| UI — Registry / Domain / Ontology / Mapping | ✓ | sample-only | |||
| UI — Graph Viewer (Sigma) | ✓ | (via filter) | ✓ | ✓ | |
| UI — SPARQL panel | ✓ | ✓ | |||
| UI — GraphQL tab | ✓ | (under) | ✓ | ||
| UI — Graph Chat | ✓ | ✓ | ✓ | ✓ | ✓ |
| UI — Inference | ✓ | (SPARQLRuleEngine) |
✓ | ✓ | |
| UI — Data Quality (SHACL) | ✓ | ✓ | ✓ | ||
| MCP server | ✓ | ✓ | ✓ | ✓ | |
| Graph Chat agent | ✓ | ✓ | ✓ | ✓ | ✓ |
| Other agents (OWL gen, auto-map, …) | ✓ | ✓ (sampling UC) |
User-visible query languages today: REST, GraphQL, SPARQL. Engine-side dialects the platform compiles down to: Spark SQL on the Delta view and Postgres SQL on the Lakebase Graph DB. The
query_dialectflag onGraphDBBackendreserves a slot for plugging in a future Cypher / Gremlin engine.
11. Source-code anchors (quick links)
- REST routes —
src/api/routers/internal/dtwin.py,src/api/routers/v1.py,src/api/external_app.py - GraphQL —
src/back/fastapi/graphql_routes.py,src/back/core/graphql/{GraphQLSchemaBuilder,ResolverFactory,SchemaMetadata}.py - SPARQL —
src/back/core/w3c/sparql/{SparqlTranslator,SparqlQueryRunner,DomainQueryService}.py - Graph DB factory —
src/back/core/graphdb/GraphDBFactory.py - GraphDB backend —
src/back/core/graphdb/GraphDBBackend.py - Delta engine —
src/back/core/graphdb/delta/DeltaFlatStore.py - GraphDB engine (Lakebase Postgres) —
src/back/core/graphdb/lakebase/{LakebaseBase,LakebaseFlatStore,SyncedTableManager}.py - Reasoning —
src/back/core/reasoning/{OWLRLReasoner,SWRLSQLTranslator,SPARQLRuleEngine,DecisionTableEngine,AggregateRuleEngine}.py - MCP server —
src/mcp-server/server/app.py,src/mcp-server/mcp_server.py - Graph Chat —
src/agents/agent_dtwin_chat/{engine,tools}.py