Skip to content
Data
Skill

/ontology-term-resolution

Resolves free-text scientific labels to ontology term IDs and validates existing CURIEs against the EBI Ontology Lookup Service (OLS4). Also looks up prefixes in Bioregistry, resolves compact identifiers via Identifiers.org, maps lab shorthand with ZOOMA, and builds Ontobee term

From plugin
scientific-agent-skills
56k177 skills

Claude Code

$ npx -y skills add K-Dense-AI/scientific-agent-skills --skill ontology-term-resolution --agent claude-code

SKILL.md

ontology-term-resolution.SKILL.md
name: ontology-term-resolution
description: Resolves free-text scientific labels to ontology term IDs and validates existing CURIEs against the EBI Ontology Lookup Service (OLS4). Also looks up prefixes in Bioregistry, resolves compact identifiers via Identifiers.org, maps lab shorthand with ZOOMA, and builds Ontobee term pages. Use whenever an ontology identifier must be produced or checked - annotating tissue, cell type, disease, phenotype, assay, chemical, organism, sex, or developmental stage fields; preparing metadata for GEO, ENA, BioSamples, CELLxGENE, HCA, or ISA-Tab submission; auditing a metadata table of term IDs; checking whether a term is obsolete and what replaced it; or deciding HPO vs HP. Triggers include "ontology term", "ontology ID", "CURIE", "controlled vocabulary", "UBERON", "CL:", "MONDO", "HPO", "EFO", "ChEBI", "NCBITaxon", "GO term", "PATO", "Zooma", "Bioregistry", "Identifiers.org", "Ontobee", "annotate this tissue/cell type/disease", and any request to emit or verify an identifier shaped like PREFIX:0001234.
license: MIT
compatibility: Requires Python 3.11+. Scripts use only the standard library - no third-party packages. Needs network access to https://www.ebi.ac.uk/ols4, https://bioregistry.io, https://resolver.api.identifiers.org, and https://www.ebi.ac.uk/spot/zooma (all public, no API key).
allowed-tools: Read Write Edit Bash
metadata:
  version: "1.4"
  last-reviewed: "2026-10-01"
  skill-author: K-Dense Inc.

Ontology Term Resolution

When to use

Any time an ontology identifier is about to be written down or trusted: annotating a metadata column, filling a submission template, auditing a table someone else produced, or checking whether an ID in an old file is still current.

The rule

**Never write an ontology ID from memory, and never accept one without checking it.**

Ontology IDs are memorable in form and arbitrary in detail. A plausible-looking `UBERON:0002108` is a real term (small intestine) that is not the liver, and nothing downstream will catch the substitution โ€” the ID is well-formed, the ontology is right, and the metadata is silently wrong. Reviewers cannot spot it either, which is why these errors persist into published datasets.

OLS search and ZOOMA emit **candidates**. Validate each selected ID with OLS term detail, then check its definition against the sample and the target schema before accepting it. Bioregistry, Identifiers.org, ZOOMA, and Ontobee answer prefix, landing-page, and shorthand questions โ€” they do not replace that OLS check.

Which service

| Question | Script | Authority | | --- | --- | --- | | What is the term for "left ventricle"? | `scripts/resolve_terms.py` | OLS | | OLS missed lab shorthand (`PBMC`, `WT`) | `scripts/map_terms.py`, then `validate_terms.py` | ZOOMA proposes; OLS validates the term | | Is `EFO:0001067` real, current, correctly labelled? | `scripts/validate_terms.py` | OLS | | Is `HPO` a real prefix? Does `HP:notanid` match the pattern? | `scripts/lookup_prefix.py` | Bioregistry | | Which landing page should this CURIE open? | `scripts/lookup_prefix.py` | Identifiers.org + Ontobee URLs |

All four scripts take single values or files, emit TSV or JSON, and need no packages beyond the standard library. Full traps for the non-OLS services are in `references/companion-apis.md`.

Resolve text to terms

cd skills/ontology-term-resolution/scripts

# one string, constrained to the ontology that should define it
python3 resolve_terms.py "liver" --ontology uberon
query   rank  curie           iri                                               label  ontology  match_type   strategy  defining_ontology
liver   1     UBERON:0002107  http://purl.obolibrary.org/obo/UBERON_0002107       liver  uberon    exact_label  exact     true
# a column of tissue names; anything not an exact hit is reported, not guessed
python3 resolve_terms.py --input tissues.txt --ontology uberon \
    --exact-only --format tsv -o resolved.tsv

# accept fuzzy fallbacks, then review the partial hits by hand
python3 resolve_terms.py "left ventrical of heart" --ontology uberon --top 3

The search escalates `exact` (label and synonym) โ†’ `token` โ†’ `fulltext` and stops at the first strategy that returns candidates, reporting which one fired. `--exact-only` disables the ladder and locally rejects partial, related, broad, narrow, and unscoped synonym matches. Searches are bounded candidate lists (`--top`), not exhaustive ambiguity checks. `--branch UBERON:0000465` uses OLS hierarchical ancestry, including part-of/develops-from.

**Read `match_type` before using a result.** `exact_label` and `exact_synonym` establish lexical agreement (the latter also requires an exact synonym annotation), not correct sample context. `related_synonym`, `broad_synonym`, `narrow_synonym`, `unspecified_synonym`, and `partial` require curation. Validate every selected ID; search does not expose obsolescence in its records. `unresolved` is a legitimate output. See `references/curation-rules.md` before normalising input.

Validate existing IDs

python3 validate_terms.py UBERON:0002107 EFO:0001067 UBERON:9999999
id              status     actual_label                  ontology  replacement     detail
UBERON:0002107  ok         liver                         uberon
EFO:0001067     obsolete   obsolete_parasitic infection  efo       MONDO:0005135   obsolete; replaced by MONDO:0005135
UBERON:9999999  not_found                                                          no such term in the ontology this prefix names

Exit code is 1 if anything failed, 0 otherwise, 2 on usage or network trouble โ€” so it works as a CI gate on a metadata file:

# id + label columns; catches IDs that exist but are labelled as something else
python3 validate_terms.py --input metadata.tsv --strict

# a tissue column must hold UBERON anatomical entities and nothing else
python3 validate_terms.py --input tissue_ids.tsv \
    --br
Read more
@k-dense-ai
Ships withscientific-agent-skills

๐Ÿ”” Claude Scientific Skills is now Scientific Agent Skills. Same skills, broader compatibility โ€” now works with any AI agent that supports the open Agent Skills standard, not just Claude.

Stars on GitHub

Momentum

stars in total
55.6k
Star history of K-Dense-AI/scientific-agent-skills on GitHub, a chart by star-history.com

Other skills on scientific-agent-skills.

aeon

aeon

This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting,โ€ฆ

More skills from other plugins.

paddleocr-doc-parsing

paddleocr-doc-parsing

Use this skill to extract structured Markdown/JSON from PDFs and document imagesโ€”tables with cell-level precision, formulas asโ€ฆ

@paddlepaddle@paddlepaddleInstall Skill
context-loader
Auto-invoked

context-loader

Search memories from earlier Pi sessions in this repository. Use it when earlier work may already explain the code, error,โ€ฆ

mem04d69k
@mem0ai@mem0aiInstall Skill
analyzing-ai-citations

analyzing-ai-citations

Answer AI citation and answer engine optimization (AEO) questions in PostHog: whether AI answer engines (ChatGPT, Claude, and anโ€ฆ

posthog10d41k
@posthog@posthogInstall Skill
qmd

qmd

Search local markdown knowledge bases, notes, docs, and wikis with QMD. Use when users ask to find notes, retrieve documents,โ€ฆ

qmd3w31k
@tobi@tobiInstall Skill

Questions about ontology-term-resolution.

Which coding agents can use ontology-term-resolution?
ontology-term-resolution installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.