Ontology discovery
Skill VincentK1991/present-at-hand/skills/ontology-discovery
Use this skill to teach an LLM how to discover, validate, and iteratively improve an ontology and SPARQL inference rules from unstructured text using a user-in-the-loop workflow and measurable quality gates.From its SKILL.md
npx -y skills add VincentK1991/present-at-hand --skill ontology-discoveryAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.6 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
ontology-discovery
Agent-oriented ontology discovery loop:
- Read unstructured content.
- Ask domain/subdomain questions with user in the loop.
- Draft ontology
.ttland rule set (rules/, one.rqfile per rule). - Run ontology-guided extraction.
- Run forward-chaining inference.
- Run quality metrics.
- Improve ontology/rules and repeat until user approval.
This skill is decision-oriented and iterative: the goal is not just to run scripts, but to produce a high-quality ontology and inference rules that satisfy the user.
Deep Reference Library (Table of Contents)
Use these references for detailed decision-making, examples, tradeoffs, and design rationale.
| Loop Step | Deep Reference |
|---|---|
| Step 1: Read unstructured content | 01-reading-unstructured-corpus.md |
| Step 2: User-in-the-loop domain interview | 02-domain-interview-and-competency-questions.md |
| Step 3: Ontology design and TTL authoring | 03-ontology-design-and-ttl-authoring.md |
| Step 3: Rule design (one file per rule) | 04-rule-design-and-sparql-construct.md |
| Step 4: Extraction execution and diagnostics | 05-extraction-with-extract-to-ttl.md |
| Step 5: Inference execution and diagnostics | 06-inference-with-infer-to-ttl.md |
| Step 6: Metrics interpretation and quality diagnostics | 07-metrics-and-quality-diagnostics.md |
| Step 7: Iterative optimization playbook | 08-iterative-improvement-research-playbook.md |
| End-to-end example | 09-end-to-end-worked-example.md |
Research-Rigor Expectations
The agent should behave like an ontology researcher, not a script runner:
- justify modeling decisions with evidence from corpus + user intent
- make tradeoffs explicit (precision vs recall, simplicity vs expressivity)
- run controlled iterations and compare metric deltas
- avoid broad changes without a clear hypothesis
- present assumptions, risks, and alternatives before finalizing ontology/rules
When to Use
Use when the user asks to:
- discover or design an ontology from text
- build rule-based inference for KG enrichment
- validate ontology/rule quality with repeatable metrics
- iteratively improve ontology + inference performance
Do not use when the user only wants one-off extraction without ontology/rule refinement.
Prerequisites
- Apache Jena CLI available (
riot,arq,shacl) - Node.js ≥ 20
ANTHROPIC_API_KEYset for extraction
First-time setup after gh skill install
After installing with gh skill install vincentk1991/present-at-hand ontology-discovery,
the skill lands in ~/.claude/skills/ontology-discovery/. Run once:
cd ~/.claude/skills/ontology-discovery
npm install
cp .env.example .env # then fill in ANTHROPIC_API_KEY
Portable Packaging and Use
This skill is portable as a standalone folder.
From the skill root:
npm install
cp .env.example .env
Run commands from the skill root using ./scripts/....
Quick checks:
riot --version
arq --version
shacl --version
npm run test:infer:smoke
Required Artifacts and Conventions
- Ontology file:
*.ttl - Rules directory:
rules/ - Rule format: one SPARQL
CONSTRUCTrule per file,.rqextension - Rule naming:
NN-name.rqfor deterministic order (10-...,20-...) - Extraction output: asserted triples
.ttl - Inference output: inferred-only
.ttl(optional closure.ttl) - Metrics output:
jsonormdreport frommetrics.mjs
Rule file contract:
- exactly one
CONSTRUCT { ... } WHERE { ... }per.rqfile - include required prefixes at top
- keep rule intent narrow and testable
Canonical Discovery Loop (Agent Protocol)
Run these steps in order for every cycle.
Step 1: Read and Segment Unstructured Content
Objective: build a candidate concept/relation inventory before writing ontology terms.
Deep dive: 01-reading-unstructured-corpus.md
Actions:
- read input corpus/document(s)
- identify recurring entities, relations, attributes, units, temporal markers
- detect ambiguity, synonym clusters, and overloaded terms
- produce a short candidate vocabulary draft for user review
Step 2: Domain/Subdomain Interview (User in the Loop)
Objective: lock scope and modeling intent before drafting ontology.
Deep dive: 02-domain-interview-and-competency-questions.md
Ask adaptive questions covering:
- primary domain and subdomain
- core entities and boundaries (in-scope vs out-of-scope)
- critical relations (what must be inferable)
- key literal attributes and expected datatypes
- temporal/granularity expectations
- competency questions (what queries should be answerable)
- precision vs recall preference for extraction/inference
Agent rules:
- summarize assumptions back to user
- do not proceed to ontology rewrite until assumptions are confirmed
- if conflicts appear, ask follow-up questions immediately
Step 3: Draft / Revise Ontology and Rules
Objective: produce ontology + rules aligned to confirmed domain intent.
Deep dives:
Ontology drafting rules:
- keep class hierarchy meaningful (not flat, not arbitrarily deep)
- define
rdfs:domain/rdfs:rangefor high-value properties - use explicit labels and clear names
- avoid catch-all classes/properties when a specific type exists
Rule drafting rules:
- one rule per file in
rules/ - start with high-precision rules before broad/general rules
- encode inverses, type propagation, and transitive logic only when domain-justified
- avoid broad patterns that create noisy triples
Step 4: Run Ontology-Guided Extraction
Deep dive: 05-extraction-with-extract-to-ttl.md
Required: extract from at least two sources per cycle. Single-source extraction hides ontology gaps: a clean run on one document does not prove the vocabulary covers the corpus. Pick sources that exercise different parts of the ontology (e.g. different subclasses, different indicator families, different report series) so dead-rule and coverage metrics reflect the whole ontology, not one document's idiosyncrasies.
Per-source command:
node ./scripts/extract-to-ttl.mjs \
--text <path/to/source.txt> \
--ontology <path/to/ontology.ttl> \
--output <path/to/asserted-<source>.ttl> \
--base-iri <https://example.org/resource/> \
--mode create \
--output-format ttl
Run this for each selected source, writing a distinct asserted-<source>.ttl per run. Downstream scripts (infer-to-ttl.mjs, metrics.mjs) each take a single triples/asserted path, so combine the per-source files into one union file before inference:
cat <path/to/asserted-sourceA.ttl> <path/to/asserted-sourceB.ttl> \
| riot --syntax=ttl --output=ttl - > <path/to/asserted-union.ttl>
riot --validate <path/to/asserted-union.ttl>
Pass asserted-union.ttl to inference and metrics.
Validation gate — run on every asserted file:
riot --validate <path/to/asserted-<source>.ttl>
Step 5: Run Inference
Deep dive: 06-inference-with-infer-to-ttl.md
Use:
node ./scripts/infer-to-ttl.mjs \
--ontology <path/to/ontology.ttl> \
--triples <path/to/asserted.ttl> \
--rules <path/to/rules> \
--output <path/to/inferred.ttl> \
--output-format ttl \
--iterate true \
--max-iterations 10
Debug mode (recommended when quality is low):
node ./scripts/infer-to-ttl.mjs \
--ontology <path/to/ontology.ttl> \
--triples <path/to/asserted.ttl> \
--rules <path/to/rules> \
--output <path/to/inferred.ttl> \
--strict-rule-order true \
--write-closure <path/to/closure.ttl> \
--snapshot-dir /tmp/onto-infer-snapshots
Validation gate:
riot --validate <path/to/inferred.ttl>
Step 6: Measure Quality with Metrics
Deep dive: 07-metrics-and-quality-diagnostics.md
Use:
node ./scripts/metrics.mjs \
--ontology <path/to/ontology.ttl> \
--asserted <path/to/asserted.ttl> \
--inferred <path/to/inferred.ttl> \
--rules <path/to/rules> \
--format md \
--output <path/to/metrics.md>
Or:
npm run metrics -- --ontology <path/to/ontology.ttl> --format json
Step 7: Improve and Repeat
Objective: use metrics + user feedback to revise ontology/rules and re-run steps 1-6.
Deep dive: 08-iterative-improvement-research-playbook.md
Prioritization policy: balance ontology structure quality and inference quality together.
Stop criterion: loop ends only after explicit user approval.
Worked end-to-end example: 09-end-to-end-worked-example.md
Quality Interpretation Guide (How to Improve)
Use this decision table each cycle.
flat_hierarchyor very high leaf ratio:- add meaningful subclass structure
- split overloaded classes
- low domain/range coverage:
- add
rdfs:domain/rdfs:rangefor frequent properties
- add
- low typed-subject coverage:
- improve class definitions and typing rules
- tighten extraction prompts through ontology vocabulary clarity
- high dead-rule count:
- remove, merge, or rewrite rules whose WHERE conditions never activate
- high inference gain with low precision:
- tighten WHERE patterns and add type constraints
- move broad rules later or remove them
- SHACL violations present:
- align ontology constraints with actual data and rule outputs
Cycle Output Contract (What the Agent Must Report Each Iteration)
At the end of each cycle, report:
- domain/subdomain assumptions confirmed with user
- ontology changes summary
- rule changes summary (added/updated/removed
.rq) - extraction command and result summary
- inference command and result summary
- metrics highlights and quality flags
- concrete next improvements for next cycle
- explicit question: approve or continue another refinement loop
Validation and Safety Gates
Must pass each cycle:
riot --validate <ontology.ttl>
riot --validate <asserted.ttl>
riot --validate <inferred.ttl>
Recommended checks:
riot --count <asserted.ttl>
riot --count <inferred.ttl>
npm run test:infer:smoke
If any gate fails, fix ontology/rules and re-run before presenting results.
Tool Summary
scripts/extract-to-ttl.mjs: ontology-guided structured extractionscripts/infer-to-ttl.mjs: SPARQL CONSTRUCT fixpoint inferencescripts/metrics.mjs: grouped quality metrics and flagsscripts/test-infer-smoke.mjs: deterministic inference regression smoke test
Limitations
- No named graph semantics in current pipeline output.
- No automatic semantic conflict resolution between competing ontology designs.
- Rule quality is only as good as rule specificity and validated user intent.
What ships with it: 26 files
113.5 KB alongside SKILL.md, 11 of them executable
references/
- 01-reading-unstructured-corpus.md4.1 KB
- 02-domain-interview-and-competency-questions.md4.0 KB
- 03-ontology-design-and-ttl-authoring.md4.0 KB
- 04-rule-design-and-sparql-construct.md3.4 KB
- 05-extraction-with-extract-to-ttl.md6.1 KB
- 06-inference-with-infer-to-ttl.md3.2 KB
- 07-metrics-and-quality-diagnostics.md3.4 KB
- 08-iterative-improvement-research-playbook.md4.1 KB
- 09-end-to-end-worked-example.md3.1 KB
scripts/
- extract/anthropic.mjsruns4.9 KB
- extract/chunking.mjsruns1.1 KB
- extract/cli.mjsruns4.8 KB
- extract/io.mjsruns2.4 KB
- extract/pipeline.mjsruns6.4 KB
- extract/rdf.mjsruns10.6 KB
- extract/shell.mjsruns751 B
- extract-to-ttl.mjsruns4.3 KB
- infer-to-ttl.mjsruns11.6 KB
- metrics.mjsruns26.6 KB
- test-infer-smoke.mjsruns3.5 KB
tests/
- .env.example184 B
- package.json529 B