Skip to content

Ontology-Guided Conversational Analysis — Asking the Knowledge Graph in Plain Language

A question asked in plain language passing through ontology-guided interpretation — OWL for meaning, SKOS for which concept a word denotes, SHACL for valid shapes — into generated SPARQL over an enterprise knowledge graph, returning a grounded answer with cited triples and full provenance

Bridging Architecture Silos ends on an admission: the graph answers cross-cutting questions, but only for someone who writes SPARQL. Every stakeholder the federation was built for — the analyst checking a capability, the on-call engineer tracing a failure, the reviewer looking for an unowned component — still has to go through a person who can express their question in a query language.

This article is about closing that distance without giving up the property that made the graph worth building. A question in plain language should reach the same dataset, and the answer should still be checkable: which query ran, against which dataset, resolved through which vocabulary, and what the result does not prove. That combination — conversation in front, ontology underneath, evidence attached — is what we call ontology-guided conversational analysis.


The last mile is the question, not the data

By the time a dataset exists, the hard integration work is done. Models have been converted into RDF against the published ontologies, kept in per-model named graphs, merged without being flattened, and validated against the shapes their metamodel names. The architecture is queryable.

What remains is a translation problem, and it runs in both directions. A question arrives in the vocabulary of the person asking — "our Claims capability", "the mainframe we are retiring", "who owns this" — and none of those phrases is an IRI. An answer has to come back in a form the asker can act on and a reviewer can challenge, which a result set alone is not.

Neither direction is solved by making the query language friendlier. It is solved by giving the interpreter something authoritative to interpret with.


Why bolting an LLM onto a graph is not enough

Point a general-purpose model at a SPARQL endpoint and it will write queries that execute. That is the problem. Two failure modes look identical to the person who asked, and both are silent:

  • An empty result reads as absence. "No capability is unrealized" and "no capability is modelled" are different statements about the architecture, and a query returning zero rows produces both.
  • A wrong vocabulary returns nothing, quietly. Scope a query to a named graph the dataset does not have, or to a predicate the converter never emitted, and it succeeds with no rows.

An architecture graph built the way this one is has four structural properties that walk straight into those failures, and none of them is visible in an ontology dump handed to a model as context:

Property What a guessed query does
Relationships are resources — an arch:QualifiedRelationship with arch:source and arch:target — with the direct predicate shortcut opt-in at conversion time Writes ?app am:realizes ?cap against a dataset that only holds the qualified form, and returns nothing
Everything lives in named graphs per model Omits the GRAPH clause and matches a default graph that converter TriG leaves empty
Ownership, lifecycle and cross-source identity are notation-specific or authored, not derivable Reports "no owner" for a notation that has no ownership predicate at all
Some IRIs denote a record about a thing — a LeanIX fact sheet is a document about an application, not the application Counts documents and calls them applications

Each one produces a query that runs and misleads. Fluency is not the missing ingredient; grounding is.


What "ontology-guided" actually means

The semantic layer is not documentation the agent reads for inspiration. Each part of a semantic set does a specific job in interpreting the question, which is the progression the headline diagram above shows:

OWL says what terms mean. The core ontology and the notation ontology define the classes and properties the dataset can legitimately use, and how they relate. This is what makes "application" a resolvable concept rather than a word to pattern-match.

SKOS says which concept a word denotes. Labels, alternative labels and taxonomy terms are the bridge from what somebody typed to what the graph calls it. "Claims", "Claims Handling" and "claims-handling" are a resolution problem with a correct answer, and resolution is a query — never a construction. An IRI assembled from a label is a guess wearing an identifier's clothes.

SHACL says what a valid shape is. The shapes that judge the model also tell an interpreter what a well-formed instance of it looks like, which constrains what a sensible query can ask for.

The arch:Metamodel manifest makes all of that discoverable from the data. A converted model declares conformance to a manifest that names its ontology, taxonomy and shapes, so an agent can find the vocabulary to query with and the shapes to check against without being told out of band. See DD-13.

The profile is where interpretation becomes checkable

An ontology says what terms can exist. It does not say what this dataset actually did — whether the converter emitted direct predicate triples, which graph holds the views, whether a reconciliation graph was authored, whether ownership is present at all.

The APM agent skills close that gap with a graph profile: a machine-readable binding from semantic roles to the concrete terms, prefixes, graph layout, capabilities and taxonomy terms a particular dataset uses. A profile can be derived from a converter type-mapping file or from a published arch:Metamodel manifest, so a custom ontology needs no code change. More importantly it can be verifiedla-profile verify probes the dataset and reports drift between what the profile claims and what is there.

That is the difference between an agent that has been told about your graph and an agent that has checked. Until a profile is verified, every result derived from it carries a caveat saying so.


The shape of a conversation

Setup happens once per dataset. Questions come after, and orientation is per session rather than per question:

la-connect datasets                                        # lists candidates, selects none
la-connect connect --data merged-graph.trig                # repeat --data to merge into one store
la-profile recommend --data merged-graph.trig
la-profile verify --profile linked-archi-default --data merged-graph.trig

la-connect datasets deliberately picks nothing. Answering from a file nobody chose is the one failure that cannot be detected afterwards — the result looks sound and cites the wrong architecture.

From there, every question follows the same ordered path, and the order is the point:

  1. Orient. Establish what is loaded — which models, which graphs, how many quads, which notations. A later absence can only be trusted if this step ran.
  2. Route. Match the question to an analysis pattern: impact and dependency, traceability, coverage and gaps, model contents, model quality, governance and decisions, lifecycle and portfolio, cross-notation, views and documentation. A question that matches no pattern is a real answer, not a failure.
  3. Resolve. Turn each name in the question into an IRI by querying for it.
  4. Run. Execute templates from the catalogue in the pattern's order, rather than composing SPARQL from scratch.
  5. Cite. Return the rows with the query, dataset and profile attached, plus what the result does not establish.

The catalogue mirrors that sequence — orientation, resolution and discovery templates before analysis, views and enrichment, with a quality stage for asking whether the model can be trusted to answer at all. Each template declares what it answers, what it does not prove, what it needs from the profile, and which templates to use instead when it cannot run.


A worked exchange

Take the question from the headline diagram, asked by a business analyst who has never written a line of SPARQL:

"Which applications realize our Claims capability, and what breaks if we retire Mainframe-B?"

Routing. Two questions, two patterns: traceability for the first, impact-and-dependency for the second. They run in that order, because the impact question is only meaningful over elements the first step has actually identified.

Resolution before anything else. "Claims capability" and "Mainframe-B" are labels. A resolution template looks them up:

core/resolve-element | TERM="Claims"
  https://example.org/acme/claims-handling    am:Capability          "Claims Handling"
  https://example.org/acme/claims-mgmt-app    am:ApplicationComponent "Claims Management"

Two candidates, two different classes. The analyst meant the capability; the agent confirms rather than assuming, because picking the wrong one produces a confident answer to a question nobody asked.

The query, generated from a template. With the IRI settled, the traceability template renders against the verified profile — qualified relationship form, graph-scoped, no predicate invented:

PREFIX arch: <https://meta.linked.archi/core#>
PREFIX am:   <https://meta.linked.archi/archimate3/onto#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

SELECT ?app ?appLabel ?model WHERE {
    GRAPH ?g {
        ?r a am:Realization ;
           arch:source ?app ;
           arch:target <https://example.org/acme/claims-handling> .
        ?app a am:ApplicationComponent ;
             skos:prefLabel ?appLabel ;
             arch:inModel ?model .
    }
}

The profile decided three things in that rendering that a guessed query gets wrong: that realization is reached through am:Realization with arch:source/arch:target rather than a direct predicate, that the match must be graph-scoped, and that model membership is available on the element via arch:inModel.

The refusal. The second half of the question asks what breaks. The dependency template that walks direct predicate triples cannot run against this dataset, and says so instead of returning nothing:

Template 'core/dependents-direct' cannot run against profile 'linked-archi-default':
  - capability 'direct_rel_triples' is False but this template needs True
Try instead: core/dependents-qualified, core/neighbours-qualified

This is a refusal, not an empty result: running it anyway would return no rows and
read as 'nothing exists'.

The qualified variant runs, and the answer comes back with its own boundary stated: these are the elements reachable from Mainframe-B in the graph as loaded. Reachability is not criticality, and nothing in the dataset ranks the two components it found.

The citation. Every result carries a footer:

core/realized-by | query 4ae81572f06e | dataset merged-graph.trig | profile linked-archi-default v2 | 2026-09-17T09:14:02.118374+00:00 | 3 row(s)

query 4ae81572f06e is a hash over the query with whitespace collapsed, so re-indenting a template does not change it while changing an IRI, a limit or a graph does. Two answers citing the same id ran the same question — which is what makes a conversational answer reviewable months later, by someone who was not in the conversation.


A refusal is an answer

The single most useful behaviour in the whole loop is the one that returns no data.

Architecture questions are mostly questions about absence: what has no owner, which capability nothing realizes, what is not covered by a decision. Absence is exactly where a query language is most dangerous, because "not modelled", "not converted", "not supported by this dataset" and "not true of the architecture" all render as zero rows.

One query returns zero rows, which is consistent with four different states of the world — the capability was never modelled, the converter emitted no graph for it, the dataset cannot support the query, or the architecture genuinely has none — with only the last being a finding

The same empty result, four incompatible readings. A refusal names which one applies; an empty result lets the reader choose.

So every template declares its prerequisites — profile roles, graph roles, capabilities, notation vocabulary — and when the dataset cannot support one, the answer names the reason and a viable alternative instead of running anyway. Exit codes carry that meaning through to automation: a refusal is a finding to read, not a crash to retry. A SHACL run that selected no focus node reports that it selected none, rather than the clean pass a namespace mismatch would otherwise produce.

The same discipline applies to interpretation, as explicit stop rules on every analysis pattern:

  • Reachability established is not criticality established.
  • A label match is not an identity — cross-source identity is authored and reviewed, never inferred from a name (DD-11).
  • A difference between two diagrams is not yet a difference in the architecture.
  • What a rule derived is not what somebody modelled — derived triples live in their own graph (DD-28) so the two remain separable questions.

What comes back is an evidence bundle, not a paragraph

A single question gets a cited result. An investigation gets something more structured: an ordered plan, each step executed as its own catalogued query, and the envelopes bundled into one artifact that keeps three things apart — what the graph asserts, what was inferred from it, and what remains unknown.

That separation is what makes the output usable as input to a decision. An impact assessment that mixes "the graph says these three components access this data object", "therefore the capability is at risk" and "ownership is not recorded for two of them" into one confident paragraph cannot be audited. Keeping them in three sections can.

The same assessment written two ways — as one paragraph in which asserted fact, drawn conclusion and missing data share a single voice, and as three separated sections carrying respectively a citation, a stop rule, and a statement that the dataset has nothing to say

Each section makes a different kind of claim, so each can be challenged on its own terms: the asserted rows by re-running the query, the conclusion by disputing the reasoning, the unknown by fixing the model.

Two further properties hold throughout, and both matter more in conversation than in a workbench:

  • Read-only is enforced, not requested. Update, insert, delete and load are rejected before any backend is touched — including queries arriving through an investigation plan. A conversation cannot quietly edit the architecture it is describing.
  • No skill chooses for you. Dataset selection, profile recommendations and identity assertions are surfaced, not applied. The agent does the work; the human keeps the decisions that cannot be undone silently.

What this changes, by audience

The federation article argued that each audience should model in the notation native to its concerns. The same argument applies to reading:

  • The analyst and the product owner ask in domain language and get a cited answer, without learning a query language or booking time with an architect.
  • The architect stops being a query service. The questions that arrive are the ones that need judgement, because the mechanical ones were answered from the catalogue.
  • The engineer on call traces what a failing service supports at the moment it matters, from the same dataset the architecture review used.
  • The reviewer and the auditor get the property no chat interface usually offers: the query, the dataset identity and the profile version, so a claim made in a conversation can be re-run and confirmed.

This is also the honest answer to the limitation the previous article closed on. SPARQL remains the query language of the graph; what changes is who has to write it.


Limits worth stating plainly

The graph has to exist, and be current. Conversation adds no facts. If a model changed and nobody re-ran the converter, the answer is a confident report about last quarter's architecture. Currency is a pipeline property, not a conversational one — see Enterprise Architecture Knowledge Pipeline for the return edge that keeps it current, and for where each kind of finding from an answer legitimately lands.

A question can only be answered from what was modelled. No amount of grounding recovers a capability nobody captured or an owner nobody recorded. The quality templates exist to make that distinction visible rather than to fix it.

Cross-source instance identity is still authored. Type-level federation is automatic; asserting that a Backstage component and an ArchiMate component are the same real system is reviewed human work, and a conversation that needs it will say the link is missing rather than infer it.

Pattern coverage is finite. A question with no matching pattern gets told so. That is preferable to an improvised traversal presented with the same confidence as a tested one, but it is a boundary.

The agent is an instrument, not an authority. It reports what the graph says. Whether the graph is right about the organization remains an architectural judgement, and the citation exists so that judgement has something to argue with.


Where next