Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Ontology Term Resolution

ASecurity

Resolve free-text scientific labels to ontology term IDs and validate existing CURIEs against the EBI Ontology Lookup Service (OLS4). 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 ...

9 stars
0 votes
0 copies
0 views
Added 9/23/2026
developmentpythonrustgobashgitapi

Works with

api

Security Analysis

A100/100

Scanned 9/23/2026

Install to Claude Code

$npx -y skills add stanfish06/skillquarium --skill ontology-term-resolution --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ontology Term Resolution?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Ontology Term Resolution
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/stanfish06-ontology-term-resolution/badge)](https://www.skillsdirectory.com/skills/stanfish06-ontology-term-resolution)

More formats (shields.io, HTML) on the badges page.

Download with Pro
Files
SKILL.md
---
name: ontology-term-resolution
description: Resolve free-text scientific labels to ontology term IDs and validate existing CURIEs against the EBI Ontology Lookup Service (OLS4). 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 mapping between ontologies. Triggers include "ontology term", "ontology ID", "CURIE", "controlled vocabulary", "UBERON", "CL:", "MONDO", "HPO", "EFO", "ChEBI", "NCBITaxon", "GO term", "PATO", "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 (public, no API key).
allowed-tools: Read Write Edit Bash
metadata:
  version: "1.0"
  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.

Every ID this skill emits comes from a live OLS lookup. Every ID it is handed gets verified.

## Two directions

| Direction | Script | Question answered |
| --- | --- | --- |
| text → ID | `scripts/resolve_terms.py` | What is the term for "left ventricle"? |
| ID → verdict | `scripts/validate_terms.py` | Is `EFO:0001067` real, current, and labelled what this file claims? |

Both take single values or files, emit TSV or JSON, and need no packages beyond the standard
library.

## Resolve text to terms

```bash
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           label  ontology  match_type   strategy  defining_ontology
liver   1     UBERON:0002107  liver  uberon    exact_label  exact     true
```

```bash
# 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 anything, reporting which one fired. `--exact-only` disables the ladder.
`--branch UBERON:0000465` restricts candidates to descendants of a term.

**Read `match_type` before using a result.** `exact_label` and `exact_synonym` are safe;
`partial` means OLS returned its best guess for a string that does not exist as written, and
needs a human decision. `unresolved` is a legitimate output — see `references/curation-rules.md`
for the normalisations worth retrying first.

## Validate existing IDs

```bash
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:

```bash
# 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 \
    --branch UBERON:0000465 --expect-ontology uberon
```

| Status | Meaning | Verdict |
| --- | --- | --- |
| `ok` | Exists, current, consistent with everything asserted | pass |
| `matched_synonym` | Claimed label is a synonym; primary label differs | warn |
| `imported_only` | Home ontology no longer asserts this ID | warn |
| `not_a_class` | Term is a property or individual | warn |
| `not_found` | No such term | fail |
| `obsolete` | Obsoleted; `replacement` gives the successor when one exists | fail |
| `label_mismatch` | ID and claimed label describe different things | fail |
| `wrong_ontology` | Right kind of ID, wrong ontology for this column | fail |
| `wrong_branch` | Not a descendant of the required root | fail |
| `malformed_curie` | Not of the form `PREFIX:local` | fail |

`--strict` promotes warnings to failures.

## API behaviour that will mislead you

These are verified against the live service and are the reason this skill ships scripts rather
than a recipe. Full detail in `references/ols4-api.md`.

| Trap | Consequence |
| --- | --- |
| `exact=true` is exact **token** matching | `liver` returns 161 hits in UBERON; adding `queryFields=label` returns 1 |
| `/search` never returns `is_obsolete` or `term_replaced_by` | Named in `fieldList` they are dropped silently; only term detail can answer "is this ID still current" |
| `ontology=efo` returns MONDO and CL hits | Ontologies import each other; filter on the CURIE prefix yourself |
| The same term appears once per importing ontology | Deduplicate on `obo_id`, keep `is_defining_ontology: true` |
| The `obo_id` index has holes | `MONDO:0000001` is live but unindexed by `obo_id`; an IRI fallback is required to avoid a false `not_found` |
| IRIs are not all OBO PURLs | EFO and Orphanet use their own namespaces — resolve IRIs, do not template them |
| OxO is retired | Returns HTML with HTTP 200; use term cross-references or SSSOM instead |
| A branch check does not exclude cell types from anatomy | CARO puts `cell` under `anatomical structure`; constrain the prefix too |

## Choosing the ontology

MONDO for disease, HP for phenotype, UBERON for tissue, CL for cell type, EFO for assay, ChEBI for
compounds, NCBITaxon for organism, PATO for sex and for `normal`. Prefix-to-OLS-id mappings (`HP`
is served as `hp`, `Orphanet` as `ordo`), branch roots for `--branch`, and the overlapping-ontology
judgement calls are in `references/ontology-registry.md`.

## Reporting results

Give the ID **and** the label, and say how each was matched. A table of bare IDs cannot be
reviewed. State unresolved terms explicitly rather than filling them with the nearest hit.

## References

- `references/ols4-api.md` — endpoints, parameters, response fields, and every verified trap.
- `references/ontology-registry.md` — prefix/ontology-id table, branch roots, which ontology owns
  which concept.
- `references/curation-rules.md` — candidate-selection procedure, normalisations to retry,
  auditing an existing table, obsolete terms, cross-ontology mapping.

Attribution

stanfish06stanfish06
View sourceMore from stanfish06 →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284722 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →