Skip to content
Security
Skill

/mapping-to-snomed

Maps clinical concept spans extracted by OpenMed to SNOMED CT concepts through a USER-SUPPLIED terminology server (the user's own Ontoserver, Snowstorm, or UMLS/UTS), never a bundled vocabulary. Use when the user wants to code findings, disorders, procedures, body structures, or

BOOST
From plugin
openmed
5.7k74 skills
Install
$ npx -y skills add maziyarpanahi/openmed --skill mapping-to-snomed --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/mapping-to-snomed

Context preview

The summary Claude sees to decide when to auto-load this skill.

Maps clinical concept spans extracted by OpenMed to SNOMED CT concepts through a USER-SUPPLIED terminology server (the user's own Ontoserver, Snowstorm, or UMLS/UTS), never a bundled vocabulary. Use when the user wants to code findings, disorders, procedures, body structures, or

SKILL.md

mapping-to-snomed.SKILL.md
name: mapping-to-snomed
description: "Maps clinical concept spans extracted by OpenMed to SNOMED CT concepts through a USER-SUPPLIED terminology server (the user's own Ontoserver, Snowstorm, or UMLS/UTS), never a bundled vocabulary. Use when the user wants to code findings, disorders, procedures, body structures, or substances to SNOMED CT, run an ECL query, translate via a ConceptMap, or resolve a span to a concept id with FHIR $lookup/$translate/$validate-code. Trigger keywords: SNOMED CT, SNOMED concept id, ECL, ConceptMap, $translate, $lookup, Ontoserver, Snowstorm, SCTID, post-coordination, terminology server. Pairs after OpenMed NER: consume Disease/Anatomy/Pharmaceutical entities from openmed.analyze_text and map each span out-of-process. SNOMED CT is license-restricted — it is NEVER bundled; the user calls their own affiliate-licensed server."
license: Apache-2.0
metadata:
  project: OpenMed
  category: terminology-coding
  pairs: after
  version: "1.0"

Mapping OpenMed spans to SNOMED CT

Ground clinical concept spans that OpenMed extracts — disorders, findings, procedures, body structures, substances — to **SNOMED CT**, the comprehensive clinical reference terminology. The atom is the **SCTID** (a SNOMED CT concept identifier), organized into a description-logic hierarchy you can query with **ECL** (Expression Constraint Language).

> **Hard licensing boundary — read first.** SNOMED CT is **license-restricted**. > OpenMed and this skill **never bundle, ship, cache, or redistribute** any > SNOMED CT content. All mapping happens **out-of-process against a terminology > server the user supplies and is licensed for** — their own **Ontoserver**, > **Snowstorm**, the NLM's **UTS/UMLS** FHIR endpoint, or a national release > server. SNOMED International requires an Affiliate License (free in member > territories like the US via the NLM; check your country). Your code receives a > **base URL + credentials from the user**; it must work with *any* compliant > FHIR terminology server and store nothing but the returned codes.

When to use

  • You need rich, hierarchy-aware clinical codes (more granular than ICD-10) for

problems, procedures, or body sites.

  • You want to **translate** an existing code (ICD-10-CM, local code) to SNOMED CT

via a `ConceptMap`/`$translate`.

  • You need subsumption/ECL queries ("is this a descendant of *Diabetes

mellitus*?") for cohorting or decision support.

For billing codes use `coding-icd10`; for drugs `normalizing-rxnorm`; for labs `mapping-loinc`. SNOMED CT is the clinical-meaning layer.

Quick start (user-supplied FHIR terminology server)

Configuration is injected, never hardcoded. The operations are standard FHIR R4.

import os, requests

# Provided by the USER — their licensed server. Nothing bundled.
TX = os.environ["FHIR_TX_URL"]              # e.g. https://snowstorm.example.org/fhir
TOKEN = os.environ.get("FHIR_TX_TOKEN")     # if the server requires auth
SNOMED = "http://snomed.info/sct"
HDRS = {"Accept": "application/fhir+json"}
if TOKEN:
    HDRS["Authorization"] = f"Bearer {TOKEN}"

def lookup(code: str) -> dict:
    """$lookup: fully specified name + properties for an SCTID."""
    r = requests.get(f"{TX}/CodeSystem/$lookup",
                     params={"system": SNOMED, "code": code},
                     headers=HDRS, timeout=15)
    r.raise_for_status()
    return r.json()

def find_concepts(text: str, ecl: str = "<<404684003", count: int = 10):
    """Text search constrained by ECL (default: descendants of Clinical finding)."""
    vs = f"{SNOMED}?fhir_vs=ecl/{ecl}"
    r = requests.get(f"{TX}/ValueSet/$expand",
                     params={"url": vs, "filter": text, "count": count},
                     headers=HDRS, timeout=20)
    r.raise_for_status()
    return r.json().get("expansion", {}).get("contains", [])

def translate(code: str, source_system: str, conceptmap_url: str):
    """$translate an existing code to SNOMED CT via a ConceptMap."""
    r = requests.get(f"{TX}/ConceptMap/$translate",
                     params={"url": conceptmap_url, "system": source_system,
                             "code": code, "targetsystem": SNOMED},
                     headers=HDRS, timeout=20)
    r.raise_for_status()
    return r.json()

# ECL examples: 64572001=disease, 71388002=procedure, 123037004=body structure
print(find_concepts("type 2 diabetes", ecl="<<64572001"))

Workflow

1. **Extract** spans with OpenMed (Disease, Anatomy, Pharmaceutical models). 2. **Pick a semantic constraint (ECL)** from the OpenMed label so you search the right hierarchy: disorder span → `<<64572001`; anatomy span → `<<123037004`; substance/drug → `<<105590001`; procedure → `<<71388002`. 3. **Search** with `ValueSet/$expand?filter=<span>` under that ECL. 4. **Rank & disambiguate** by display match and confidence; prefer the most specific concept whose meaning is fully entailed by the text (do not over-code). 5. **Validate** with `$validate-code`; `$lookup` to capture the FSN and any needed properties. 6. **Translate** instead of searching when you already hold an ICD-10/local code and the user's server has the relevant `ConceptMap`. 7. **Emit** `{system: "http://snomed.info/sct", code, display}` — the SCTID plus the OpenMed source offsets for traceability.

Hand-off from OpenMed

`openmed.analyze_text(..., output_format="dict")` returns `entities`, each a dict with `text`, `label`, `confidence`, `start`, `end`. Route each label to an ECL hierarchy and map out-of-process:

import openmed

note = "Assessment: type 2 diabetes mellitus with diabetic nephropathy."
result = openmed.analyze_text(
    note,
    model_name="disease_detection_superclinical",   # Disease category
    output_format="dict",
)

ECL_FOR_LABEL = {
    "DISEASE":   "<<64572001",     # | Disease |
    "CONDITION": "<<64572001",
    "PATHOLOGY": "<<64572001",
    "ANATOMY":   "<<123037004",    # | Body structure |
    "ORGAN":
Read more
Ships withopenmed

Local-first healthcare AI: clinical NER and HIPAA PII de-identification on hardware you control. 2,200+ medical models, 35 model-backed PII languages, and Python, MLX, Android and browser runtimes. Apache-2.0 SDK.

Get the whole plugin

Other skills on openmed.