This article is published in English.
Ontology-based context engineering when vector RAG is not enough
When meaning spans systems of record, embeddings alone miss joins. Ontology-based context engineering validates typed facts, provenance, and neighborhood tools for grounded LLM answers.
One business rule is often scattered across code and documents. An ontology turns those fragments into a navigable path for context engineering.
Large legacy estates—millions of lines of C and C++, PHP MVC, PL/SQL, and hundreds of versioned unstructured documents—defeat vector-only retrieval because meaning is relational and release-scoped. Ontology-based context engineering addresses that gap: compare it with RAG and GraphRAG, survey RDF/OWL/SKOS/SHACL and related standards, choose a pragmatic stack, and apply it to a real multi-million-line system.
1. The problem: the meaning is never in one place
Modern greenfield apps with tidy docs may not feel this pain. Legacy systems do. Meaning of a single concept is split:
- C/C++ shows how values are computed, rarely why
- PL/SQL packages hide critical rules inside thousands of procedures
- PHP Smarty templates encode how users interact with data
- Specifications, release notes, and migration guides explain why, across many releases that often contradict one another
- Much knowledge lives only with people who have already left
Ask what happens to an invoice when a client changes contract mid-month. The answer is not one file; it spans a C module, PL/SQL packages, a table, a 2017 specification, and a 2021 correction note. No single text chunk holds it. The answer exists as a path among artifacts and must be modeled before an LLM can be trusted with it.
2. What is ontology-based context engineering?
Context engineering prepares what the model may see. Ontology-based context engineering uses an explicit graph of types and relations—modules, packages, tables, documents, releases, deprecations—to select artifacts before similarity search ranks paragraphs inside them. The graph answers which objects and versions are in scope; embeddings then pick wording inside that scope.
What about embeddings?
Embeddings capture similarity; ontologies capture meaning. A vector store notices paragraphs that “look alike.” An ontology can record typed edges: which package persists which table, which engine invokes that package, which specification edition documents the rule, and which release marks the package deprecated. Those are facts. The techniques combine with a fixed order: facts decide what the model may look at; similarity decides which paragraph inside that selection answers. That order is the design.
3. The landscape: RAG, GraphRAG and ontologies
Before committing to ontologies, most teams try simpler feeds. Vector RAG shines for single-hop questions and is cheaper to stand up. It fails when relationships and versions are the meaning: which release’s spec supersedes which, which package implements which rule, which document still applies. GraphRAG adds graph structure over chunks but may still under-model release policy and typed relations unless the schema is deliberate. Ontologies make types, predicates, and constraints first-class so queries can filter by release and relation rather than hoping proximity encodes them.
Vector RAG is not “bad.” It is incomplete when legacy meaning lives in links and versions.
4. The standards: RDF, OWL and friends
Semantic Web names sound heavy; the ideas are manageable.
- RDF: triples
subject → predicate → objectas the data model (:BillingEngine :calls :PKG_INVOICE). - RDFS: light schema—classes, subclasses, domains, ranges—often enough for simple ontologies.
- OWL: richer description-logic constructs for inference (disjointness, cardinality, transitivity, equivalence).
- OWL 2 DL: decidable fragment targeted by reasoners such as HermiT; expressive with a learning curve.
- OWL 2 EL: profile for large ontologies and scalable reasoning (e.g. ELK), trading some expressiveness.
- OWL 2 QL: profile aimed at query answering over large relational data.
- SKOS: vocabularies, synonyms, taxonomies for business glossaries.
- SHACL: shapes that validate RDF graphs against constraints.
- SPARQL: query language for RDF.
- R2RML / OBDA: map relational schemas into virtual knowledge graphs.
So, which is better?
Wrong question. Standards layer. A realistic legacy stack is: RDF for facts, RDFS for light hierarchy, SKOS for business terms, SHACL for validation, SPARQL for queries, R2RML to expose the database, and OWL only where inference earns its keep (impact analysis, derived links, deprecation rules). OWL everywhere makes projects brittle; layered pragmatism keeps them alive.
How to choose: decision criteria
- Need automatic inference? Use RDF/RDFS for most facts; reserve OWL for the narrow slices that benefit from automated classification.
- Need quality guarantees with many contributors? Adopt SHACL from day one and validate continuously.
- Where does truth live? Relational (Oracle + PL/SQL) → R2RML/OBDA as a virtual knowledge graph. Documents → load RDF (optionally with OWL) or a property graph; nothing to virtualize.
- Need a business glossary? Legacy synonym soup fits SKOS.
- Interop vs traversal productivity? Long-lived shared graphs favor the W3C stack; internal tooling that needs graph algorithms may add a property-graph projection synced from the semantic source of truth.
Where the standards live
Artifacts are text. OWL, SKOS, SHACL, and R2RML can live as Turtle files in git. An ontology/ tree declares what exists—classes, relations, hierarchy, metadata—often with limited OWL beyond declarations and careful rdfs:range use. Remember: a range is not a constraint. Emitting :writesTable to a non-table may cause the reasoner to infer the target is a :DbTable rather than reject it. Actual membership checks belong to SHACL. Profile choice belongs to the consuming engine, not magically to the file alone.
5. Experience on a massive legacy codebase
The concrete system exceeded two million lines of C/C++, a large PHP layer, vast PL/SQL holding much business logic, and hundreds of unstructured documents across releases. Some docs describe dead behavior; some apply only between release X and Y; nothing labels “true today.”
What was tried first (and why it was not enough)
Vector RAG on chunked code and docs answered simple questions and collapsed on cross-artifact, version-sensitive ones—mixing SPEC v2 and v3 without policy. Naive GraphRAG without typed release semantics still retrieved conflicting passages. Manual curated prompts did not scale. The failure mode was consistent: similarity without governed relations and releases.
The ontology approach
Model modules, packages, tables, documents, releases, calls, writes, implements, supersedes, applies-to-release, and deprecations. Collect facts from analyzers and dictionaries, validate with SHACL, store per-release named graphs, expose SPARQL (and MCP tools) through a context service that filters by the user’s release before any embedding step.
The twelve classes: finding them
Classes emerged from walking artifact families—not from dumping every noun. Typical cores include modules, functions, packages, tables, columns, documents, sections, releases, batch jobs, APIs, UI screens, and business terms (SKOS concepts). Relations were mined from call graphs, ALL_DEPENDENCIES / PL/Scope, PHP routes, and document metadata. Domain workshops named synonyms that SKOS then formalized.
What the repository builds
The ontology repo holds Turtle for ontology, shapes, SKOS, queries, and mappings. CI validates PRs with SHACL samples, reasoner consistency, and profile checks. Collectors emit candidate facts into staging; shapes quarantine violations with reports. A fact store accumulates accepted facts and human decisions on quarantine—the one artifact a rebuild cannot recreate. The triple store is a build output from repo + fact store + reasoning. Source systems remain authoritative for raw truth; the repo is authoritative for representation and validation.
Virtual halves via R2RML attach per Oracle schema (each schema a release), writing into the same named graphs as collected facts so the context service merges by release without extra bookkeeping. Retired releases keep collected facts without a live virtual half.
How the graph gets initialized
Before collectors, decide which standard represents each family—the contract for every extractor. Then scan C/C++ (calls, table access), Oracle dictionaries for PL/SQL, PHP routing, and document repos. Attach origin, dates, and detectable releases. Map to ontology terms, merge duplicates via SKOS, optionally let an LLM propose document classifications into a human queue. SHACL gates load. Ambiguous parses (dynamic SQL, function pointers) carry confidence marks and stay less trusted.
How the graph gets updated
Deltas follow software governance: proposal → PR on Turtle → automated SHACL/reasoner/profile checks → review → merge → rebuild affected graphs. Collectors rerun each release; new facts enter staging; quarantine triage splits into collector bugs, overly strict shapes/ontology fixes, or false facts that stay out. Early baselines needed many passes—on the order of ten collect/fix cycles over weeks—with an LLM used only to cluster violation families, never to accept facts. Documents remain the exception where models propose content for human review.
How the LLM uses it
At question time: entity linking → graph traversal → context assembly. Map the question to entities via SKOS labels/synonyms; run SPARQL filtered by the user’s release named graph plus shared graphs (documents filtered on :appliesToRelease); then hand connected facts and exact sections to the LLM. Vector search still finds paragraphs inside allowed documents. The graph decides which documents and code artifacts are on the table so versions do not mix.
The difference is stark for questions like which specification governs pro-rata billing on release 2022.2. Vectors returned SPEC_INV_V2 and V3 without validity; the graph selects V3 because it applies to 2022.2 and supersedes v2 under policy, and it names PKG_INVOICE as implementer. Answers carry a traceable path: module → package → table → document → release—verifiable by developers, unlike a pile of similar chunks.
Pipeline overview
- Analyzing. Decide standards per artifact family; produce a core ontology and decision table as collector contracts.
- Collecting. Static analysis, data dictionary mining, PHP routes, document repos—each fact with origin, date, release when known.
- Transforming. Map to ontology terms, merge synonyms, human-validate LLM proposals, SHACL quarantine, load or expose via OBDA.
- Versioning. Rerun collectors each release; maintain named graphs; keep mappings aligned to live schemas.
- Serving. Context service resolves entities, runs curated queries, packages small contexts; expose as MCP tools.
- Generating. LLM answers from packaged context; vectors optional inside selected docs.
Stages 1–4 are data engineering (stage 1 a decision; 2–4 CI each release). Stages 5–6 are context engineering. The ontology is the contract between them.
Cost and sequencing
Upfront modeling costs time but less than endless RAG retuning that cannot encode releases. Value lives in pipelines that keep the graph current, not in a static Turtle file. Start with one subsystem; prove value in weeks; grow coverage.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix : <https://example.com/legacy#> .
<https://example.com/legacy> a owl:Ontology ;
owl:versionInfo "1.4.0" .
:CModule a owl:Class ; rdfs:label "C module" .
:PlsqlPackage a owl:Class ; rdfs:label "PL/SQL package" .
:BusinessRule a owl:Class ; rdfs:label "Business rule" .
:DbTable a owl:Class ; rdfs:label "Database table" .
:calls a owl:ObjectProperty . # no range on purpose: a call crosses PHP, C and PL/SQL
:writesTable a owl:ObjectProperty ; rdfs:range :DbTable .
:implementsRule a owl:ObjectProperty ; rdfs:range :BusinessRule .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <https://example.com/legacy#> .
# a module that calls a package implementing a rule reaches that rule
:reachesRule a owl:ObjectProperty ;
owl:propertyChainAxiom ( :calls :implementsRule ) .
:implementsRule rdfs:subPropertyOf :reachesRule .
# a specification that supersedes a superseded one supersedes it as well
:supersedes a owl:ObjectProperty , owl:TransitiveProperty .
@prefix : <https://example.com/legacy#> .
@prefix g: <https://example.com/legacy/graph/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
# structural facts, as collected from the sources of release 2022.2
g:R2022_2 {
:BillingEngine a :CModule ;
rdfs:label "Billing engine (C)" ;
:calls :PKG_INVOICE ;
:readsTable :T_CONTRACT .
:PKG_INVOICE a :PlsqlPackage ;
rdfs:label "PKG_INVOICE" ;
:hasProcedure :CALC_PRORATA ;
:writesTable :T_INVOICE ;
:implementsRule :ProRataRule ;
:describedBy :SPEC_INV_V3 .
:CALC_PRORATA a :PlsqlProcedure ;
rdfs:label "CALC_PRORATA" ;
:implementsRule :ProRataRule .
}
# facts that span releases: documents, business rules, lifecycle
g:shared {
:PKG_INVOICE
:deprecatedInRelease :R2024_1 ;
:replacedBy :PKG_INVOICE_V2 .
:SPEC_INV_V3 a :SpecificationDocument ;
:appliesToRelease :R2021_1, :R2022_2 ;
:supersedes :SPEC_INV_V2 .
:ProRataRule a :BusinessRule ;
rdfs:label "Mid-month contract change is invoiced pro rata" .
}
6. Conclusion
- RAG is not dead. It is insufficient when meaning splits across code, database, documents, and releases.
- Ontologies are practical. RDF + RDFS + SKOS + SHACL form a workable stack; keep OWL only where classification rules earn their complexity.
- Typed graphs supply the meaning layer assistants need. Language models stay strong at wording; the ontology gates which facts enter the prompt, for which release, with an auditable path.
- Across a multi-million-line legacy estate, typed collectors plus shapes were the first retrieval design that survived the real constraints.
This map stops before the full territory of extraction engineering—reliable graphs from C/C++, PL/SQL, and decades of documents, served without operational chaos—which deserves dedicated deep dives.
Practical tips that survive contact with production
Name graphs after releases consistently in collectors and R2RML (rr:graph). Never let unconstrained LLM output write triples. Keep quarantine readable: node, shape, constraint. Backup the fact store obsessively. Treat reasoner profiles as deployment choices tested in CI. Document supersession policy in the ontology so “latest applicable spec” is queryable, not tribal. Measure answer quality with release-scoped golden questions that vector RAG previously failed.
When stakeholders ask for “just embeddings,” show a mixed-version failure side by side with a graph path. Adoption follows verifiability. When engineers fear OWL complexity, show the layered stack with OWL optional. When ops fear another database, remind them the triple store is rebuildable; the fact store and git ontology are the crown jewels.
Ontology-based context engineering is less about exotic AI and more about telling the truth about where meaning lives—and encoding that truth so models cannot quietly blend incompatible eras of a system.
Deeper notes on collectors and confidence
Static analysis of C and C++ yields call edges and some table touch points; runtime-built SQL and indirect calls through function pointers remain incomplete. Attaching confidence scores prevents overconfident graphs. PL/SQL extraction via Oracle dictionaries is denser for dependencies but still needs human review when dynamic SQL dominates. PHP routing maps user-visible entry points to backend symbols so questions about screens can walk into packages.
Document collectors that only embed PDFs without release tagging recreate the original failure. Prefer pipelines that detect “applies to release” ranges—heuristically proposed, human confirmed—before linking sections to packages.
Quarantine as a product feature
Quarantine volume early is a signal, not a scandal. Collector bugs, harsh shapes, and false extractions each demand different owners. Routing LLM assistance to sort violation families accelerates triage without granting write authority. After the baseline stabilizes, quarantine should trend down; spikes after a new release flag either new language constructs or drifted shapes.
Why named graphs matter
Without named graphs, triples from release 2019 and 2024 coexist without labels and queries cannot scope. With them, the context service adds a graph pattern or FROM NAMED discipline tied to the user’s working release plus shared immortal facts. That single mechanism prevents the SPEC v2/v3 confusion more effectively than prompt warnings.
MCP and developer experience
Exposing curated SPARQL wrappers as MCP tools lets coding agents ask “what calls this package on 2022.2?” without inventing SQL against production. Keep tools read-only and release-parameterized. Log tool arguments for audit when answers influence production changes.
Relationship to BMAD and living specifications
Ontology context complements process frameworks that keep AI-written code correct: the graph supplies grounded, versioned facts those processes can cite. Living specifications become nodes linked to implementing packages rather than orphan wiki pages.
Anti-patterns to avoid
- Embedding entire ontologies into prompts instead of querying them.
- Skipping SHACL because “the collectors are trusted.”
- Using OWL cardinality everywhere on day one.
- Building a property graph only, then needing OWL-level semantics later without a sync story.
- Letting vector search run unfiltered across all releases “just in case.”
Avoid those and the architecture stays explainable to both architects and developers who must verify paths.
Worked example: mid-month contract change
Return to the invoice question. In the graph, the billing engine node links to packages that compute pro-rata charges; those packages write invoice tables; documents that :appliesToRelease the user’s release and :describes those packages are selected; superseded editions are excluded by policy. The context package might include the PL/SQL procedure names, the table columns touched, and two paragraphs from the governing specification—not five conflicting PDFs. The LLM then explains behavior with citations that map to graph edges developers can click.
Without the graph, retrieval returns whichever PDF chunk embeds closest to “invoice contract change,” often an obsolete note. The model sounds confident; the path is unverifiable.
Collector design patterns
C/C++: parse translation units for calls and for SQL string literals where feasible; record file and symbol provenance; mark unresolved indirect calls. PL/SQL: lean on dictionary views and PL/Scope for dependencies; capture package/procedure granularity. PHP: map routes and controllers to backend entry symbols. Documents: extract sections, titles, and candidate release tags; never auto-commit speculative links.
Emit provenance triples alongside facts: who collected, when, from which path, at which git tag of the source. When quarantine fires, provenance tells you which collector to open.
SHACL shape examples in prose
Shapes might require every :writesTable edge to target a :DbTable, every document to carry at least one :appliesToRelease, and every package to have a non-empty label. Violations name the focus node and constraint. Teams iterate shapes as they learn corpus oddities—temporary relaxations go through the same PR review as ontology classes so history remains auditable.
Reasoner usage without dogma
Run consistency checks on PRs to catch disjointness violations early. Use materialization of transitive calls carefully; huge closures can explode stores. Prefer query-time property paths for some traversals. Profile (EL vs DL) should be a CI matrix entry: what validates in ELK may differ from HermiT expectations—pin the engine version.
Property-graph projection
If algorithms like community detection help cluster tightly coupled packages, project a labeled property graph periodically. Keep RDF as source of truth; treat LPG as a derived index. Document sync lag so nobody troubleshoots ontology bugs in a stale projection.
Human review queues
Document classification proposals appear as queue items: suggested package links, release ranges, section types. Reviewers accept, edit, or reject; decisions land in the fact store. Metrics on accept rates guide whether prompts or heuristics need work. Never bypass the queue for “obvious” cases—those are how silent errors enter.
Serving layer details
The context service authenticates the user, resolves their working release, performs entity linking (string match, SKOS altLabels, maybe light embedding over labels only), selects SPARQL templates from queries/, executes against the right named graphs, assembles a bounded token package, and returns it with path metadata. Hard caps on triples and section characters prevent prompt floods. Cache assembled contexts briefly keyed by (release, entity set, query template) to absorb repeated IDE questions.
MCP tool catalog sketches
Examples: lookup_symbol, list_writers_of_table, governing_specs_for_package, impact_of_deprecating. Each tool declares release as required. Responses include URIs and human labels. Agents chain tools; the server still enforces read-only SPARQL.
Comparison table in narrative form
Vector RAG: cheap, weak on versions. GraphRAG-lite: better structure, easy to under-specify releases. Full ontology+SHACL+named graphs: higher build cost, verifiable paths, release-safe context. Hybrid: ontology gate + vector inside documents—usually the production winner for legacy.
Governance calendar
Each release train: run collectors, triage quarantine, merge ontology PRs, rebuild triple store, smoke-test golden questions, publish MCP schema if tools changed. Assign owners for shapes vs collectors vs document queues. Without a calendar the graph rots like the wiki it replaced.
Security and access
Some packages or documents are confidential. Encode clearance in the graph or filter in the context service using the user’s roles. Do not dump unrestricted subgraphs into prompts for users who could not read the source files.
Failure drills
Delete the triple store in staging and rebuild from repo+fact store to prove recoverability. Restore fact-store backups regularly. Simulate a bad collector deploy and ensure quarantine catches it before load. These drills convert architecture slides into operational muscle.
Onboarding a second subsystem
Copy the decision table, add classes only when collectors need them, reuse SHACL patterns, keep SKOS concept schemes separate per domain if labels collide. Resist a single mega-ontology that slows every PR; modular imports with a thin upper vocabulary scale better.
Metrics that matter
- Golden-question accuracy by release
- Quarantine rate per collector
- Median context package size
- Share of answers with complete paths
- Time from release tag to graph freshness
- Human review lag on document queues
Watch those instead of raw triple counts. A large unclean graph is worse than a small trusted one.
Expanding the mid-article standards map
SKOS ConceptSchemes group business terms per domain (billing, care, provisioning). AltLabels capture the three legacy names everyone still types. ExactMatch links across schemes when integration projects demand it. SHACL can require Concept labels in two languages if the organization is bilingual—legacy Europe often is.
R2RML mappings should be reviewed like SQL views: a wrong rr:class pollutes type inferences. Keep mappings next to schema migrations so DBAs see them. When a column retires, mappings and ontology deprecation axioms should land in the same release train.
SPARQL query libraries in queries/ are product code. Parameterize release and entity URIs. Code-review them. Add ASK queries for health checks (“does this release graph exist?”) used by the context service on startup.
Why order of techniques keeps getting restated
Teams repeatedly try to “add a graph” after embeddings without changing the retrieve-then-read order. If vectors still choose documents across all releases first, the graph becomes decoration. Invert the funnel: scope by graph, then read. Write that sentence in the architecture README until it sticks.
Closing bridge to extraction deep dives
Collectors for C macros, generated code, and multi-byte encodings deserve their own manuals. So do OCR’d PDFs and scanned release notes. The ontology map above assumes those extractors exist or will; without them the cleanest OWL file cannot invent facts. Invest proportionally: modeling clarity plus extractor realism plus validation gates.
Expanding the problem statement with operational symptoms
When meaning is scattered, support tickets sound the same: the UI shows one status, the batch job another, and the warehouse a third. Engineers open three repositories and still cannot say which artifact is authoritative for a given business day. Vector search over those repositories returns sentences that look relevant because they share vocabulary with the ticket, yet the retrieved paragraphs describe deprecated flows. The ontology approach does not magically unify repositories; it forces an explicit map of which class owns which facts and which collector is allowed to assert them.
Scattered meaning also shows up in onboarding time. New hires spend weeks learning tribal maps that live only in chat history. A typed graph with SHACL constraints becomes a navigable map: start at Contract, follow hasParty to Counterparty, follow governedBy to PolicyVersion, and land on the code module that enforces the policy. That path is auditable. A similarity score is not.
Embeddings revisited with failure modes
Embeddings compress local co-occurrence. They excel when the answer is a paragraph that already states the fact. They fail when the answer is a join across systems: which policy version applied to which contract on which date while a migration flag was half-rolled out. Graph edges encode those joins. Embeddings can still rank candidate nodes or explainers after the graph narrows the set. Treating embeddings as the only retrieval tool is why many RAG demos impress on FAQ corpora and stall on legacy platforms.
Dimensionality and chunk size interact with this failure. Short chunks raise recall of buzzwords and lower recall of multi-sentence procedures. Long chunks dilute the vector with boilerplate. Neither setting invents a foreign key that was never in the text. Ontology collectors invent—or rather declare—those keys from parsers, config maps, and migration tables.
GraphRAG compared without slogans
GraphRAG-style pipelines extract entities and relations from text into a graph, then retrieve subgraphs for prompting. That helps when the corpus is the system of record. In legacy estates the system of record is often code plus databases plus runbooks. Text extraction alone will miss silent defaults in configuration. Ontology-based context engineering starts from schema intent: define the twelve classes first, then write collectors that know where each predicate lives. Extraction from prose is a fallback for soft knowledge, not the backbone for hard constraints.
Hybrid designs are valid: use GraphRAG on documentation islands, use ontology collectors on transactional cores, and union both into named graphs with provenance. The serving layer must label which triples came from which method so the model can prefer high-confidence collector facts over extracted guesses.
Standards choice expanded
RDF shines when you need global identifiers, SPARQL, and interchange. Property graphs shine when traversal UX and developer familiarity dominate. OWL adds vocabulary for constraints and inferred types; use a profile your reasoner actually supports. JSON-LD is a practical bridge for APIs. SHACL validates instance data without requiring full OWL reasoning. Pick the thinnest stack that answers: can we validate weekly, query subgraphs for prompts, and export for auditors?
Decision criteria in practice:
- Team skill: who can write SPARQL versus Cypher versus custom traversal?
- Interop: must partners consume RDF dumps?
- Validation cadence: nightly SHACL is enough for many estates.
- Inference needs: closed-world checks often beat open-world OWL surprise.
- Tooling: does the MCP server already speak your store?
Where standards live matters less than versioning them in-repo beside collectors. Drift between ontology files and collector code is a silent outage.
Twelve classes: elicitation workshop script
Run a half-day workshop with domain leads. Ask for nouns that appear in incident reports, release checklists, and regulatory questionnaires. Cluster duplicates. For each surviving class, ask: what uniquely identifies an instance, who can create it, what predicates must always exist, and which systems mutate it. Twelve is not magic; it is a size that fits working memory. If you discover thirty, group into bounded contexts and federate graphs rather than flattening everything into one soup.
Document each class with: preferred label, alternate labels, identifier policy, lifecycle states, and collector ownership. Without ownership, the graph rots.
Repository layout that stays maintainable
Separate ontology modules, collector packages, validation jobs, serving API, and prompt templates. Keep generated triples out of git; keep shapes and fixtures in git. CI should fail when SHACL breaks on golden fixtures. Tag ontology releases semver-style even if triples are ephemeral, because prompt templates pin predicate names.
Initialization deep dive
Bootstrap order: load TBox (classes and properties), load reference individuals that never come from collectors (for example canonical environment names), run collectors for slow-changing masters, then collectors for fast transactional slices, then SHACL, then publish a named graph snapshot id. The LLM never reads a moving HEAD without a snapshot pin; reproducibility beats freshness theater.
Update deep dive
Prefer incremental collectors keyed by watermarks. On schema change, migrate shapes first, then collectors, then backfill. Quarantine triples that fail shapes instead of deleting silently. Emit metrics: triples added, quarantined, shape violations by class. Page humans when quarantine rate spikes after a deploy.
LLM usage deep dive
Retrieval plan: resolve entities from user text with constrained NER against known IRIs, expand neighborhood with hop limits and predicate allowlists, serialize to a compact Turtle or markdown table, attach provenance and confidence, then call the model with tools that can fetch one more hop on demand. Forbid free-form SPARQL from the model in production until a review gate exists; offer parameterized tools instead.
Pipeline steps spelled out
- Ingest event or schedule tick.
- Collector fetches and normalizes.
- Mapper emits candidate triples with provenance.
- SHACL validates; failures go to quarantine graph.
- Merger updates snapshot with idempotent keys.
- Indexer updates serving projections.
- Evaluator runs golden questions offline.
- MCP tools expose typed reads to assistants.
- Telemetry closes the loop.
Skip any step and you rebuild a brittle RAG demo.
Cost sequencing realism
People cost dominates. Start with three classes that hurt support the most. Automate their collectors. Measure ticket deflection and wrong-answer rates. Expand class coverage only when serving latency and validation stay green. GPU spend for embeddings is usually smaller than engineer weeks spent arguing about synonyms without a vocabulary file.
Practical tips for production survival
Pin snapshot ids in prompts during incidents. Log the subgraph hash with every model answer. Provide a "why this context" panel for internal users. Treat ontology PRs like API PRs: reviewers, compatibility notes, and deprecation windows for retired predicates.
Collectors and confidence scoring
Confidence is not a vibe. Derive it from source precedence (primary DB > secondary cache > wiki), freshness, and parse certainty. Multiply scores carefully; do not average away a single fatal low signal. Surface confidence to the model as structured metadata, not as adjective soup in the prompt.
Quarantine UX
Quarantine is a product. Show pending triples, failing shapes, suggested owners, and one-click ack or fix links. Without UX, quarantine becomes a junk drawer and trust collapses.
Named graphs as contracts
Each collector writes to its named graph. The merge view is a graph of graphs with explicit policies. Rollback means dropping a named graph version, not archaeology in a monolithic triple store dump.
MCP ergonomics
Tools should mirror classes: getContract, listPoliciesForContract, getDeploymentAffecting. Arguments are IRIs or business keys resolvable to IRIs. Responses include only allowlisted predicates. Timeouts and byte caps protect the context window.
Living specifications
Ontology classes should align with ADRs and living specs. When a spec changes a rule, the shape and the collector tests change in the same pull request. Assistants that read both graph and spec reduce "doc vs code" fights.
Anti-patterns expanded
- One giant class "Thing" with free properties.
- Embedding-only retrieval for compliance questions.
- Letting the model invent IRIs.
- Silent drop of invalid triples.
- Prompting with entire ontology dumps.
- Skipping golden-question evaluation.
- Mixing environments in one graph without namespacing.
Worked example narrative
Mid-month, a contract’s payment terms change. The collector for contracts sees a new version row. Shapes require effectiveFrom and approvedBy. The update lands in the contracts named graph. A support question asks which terms apply tomorrow. Entity resolve hits the contract IRI, neighborhood fetch returns both versions with dates, the prompt includes only the applicable version plus the change provenance, and the answer cites the approval id. Vector RAG alone might retrieve the old PDF chunk still sitting in the wiki.
Collector patterns
Watermarked JDBC pulls, Git tree walkers for config, OpenAPI walkers for service maps, runtime metric label harvesters, and human CSV uploads for exceptions. Each pattern needs idempotent keys and dead-letter handling.
SHACL in operational language
Shapes say: every Contract must have exactly one current status from an enum; every PolicyVersion must point to a byte hash; every Deployment must reference a Service. Violations are actionable tickets, not log noise.
Reasoners
Use classification where it removes duplicate manual tagging. Avoid heavy open-world inference that invents individuals. Prefer SPARQL rules or SHACL-SPARQL for closed-world housekeeping if OWL surprises your operators.
Property graph projection
If developers think in paths, project RDF to a property graph nightly for exploration, while keeping RDF as the exchange and validation source. Document which predicates become edges versus properties.
Human review queues
Some predicates always need a human: legal interpretation tags, exception flags, and merges of duplicate parties. Build queues with SLAs. The graph is not complete until those queues drain or explicitly waive.
Serving layer
Cache neighborhood serializations by (iri, snapshot, hop, allowlist hash). Compress for prompts. Strip unused prefixes. Offer both verbose debug and compact production profiles.
Tool catalog sketches
- resolve_entity(text, class_hint)
- get_neighborhood(iri, hops, predicates)
- diff_snapshots(id_a, id_b, class)
- list_quarantine(class, since)
- explain_triple(subject, predicate, object)
Each tool returns JSON with provenance.
Narrative comparison of options
Pure vector RAG: fast to demo, weak on joins. Document GraphRAG: better entity glue in prose-heavy domains. Ontology collectors: best when systems of record are structured and meaning is cross-cutting. Most mature teams run a blend with clear precedence.
Governance calendar
Weekly shape triage, monthly vocabulary review, quarterly class workshop, and release notes for ontology semver. Put dates on a calendar owned by a named steward role.
Security
Triple stores hold sensitive business relationships. Apply ACLs per named graph, redact in serving profiles, and never paste secrets into prompts. Audit tool calls.
Failure drills
Break a collector on purpose in staging. Verify quarantine grows, serving stays on last good snapshot, and alerts fire. Practice restore. If the drill is scary, production will be worse.
Second subsystem onboarding
Copy the collector template, register a new named graph, add shapes, add three golden questions, and shadow-write for a week before cutting assistants over. Do not big-bang multiple subsystems.
Metrics that actually steer
Wrong-answer rate on golden set, median hops fetched, quarantine rate, collector lag, snapshot age at answer time, and human override rate. Vanity metrics like triple count mislead.
Closing synthesis without slogans
Ontology-based context engineering is disciplined context assembly: typed entities, validated facts, provenance, and tools that fetch just enough neighborhood for a grounded answer. Embeddings remain useful inside that discipline. They are not a substitute for knowing which system owns which meaning.