Maps chronic conditions extracted by OpenMed to CMS-HCC V28 risk-adjustment categories and estimates a RAF (Risk Adjustment Factor) score as decision support. Use when the user wants to surface risk-adjustable diagnoses from notes, map ICD-10-CM codes to HCC categories, estimate or reconcile a patient/panel RAF, find suspected-but-undocumented HCCs, or check MEAT documentation support. Trigger keywords: HCC, CMS-HCC, V28, RAF score, risk adjustment, Medicare Advantage, hierarchical condition category, MEAT, recapture, suspect HCC, RADV. Pairs after OpenMed NER + ICD-10 coding: consume Disease/Pathology entities from openmed.analyze_text, code them (see coding-icd10), then roll up to HCCs. CMS-HCC mappings and weights are public from CMS. This is a coding-support aid for human review, never autonomous risk-adjustment coding.
72
87%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Surface and risk-adjust the chronic conditions OpenMed extracts by mapping them to CMS-HCC categories (the V28 model, phasing in for payment years 2024–2026) and estimating a RAF (Risk Adjustment Factor) score. CMS pays Medicare Advantage plans based on RAF, so accurate, documented capture of chronic disease matters — and much of that signal lives in the narrative note, exactly what OpenMed reads.
This is decision support for coders/clinicians, not autonomous coding. The output is "candidate HCCs + estimated RAF + the documentation that supports (or fails to support) each one," for human validation.
CMS-HCC crosswalks (ICD-10-CM → HCC) and the category coefficients are public — CMS publishes them annually. Nothing restricted is bundled.
Pairs with coding-icd10 (you need ICD-10-CM codes first) and may consume
mapping-to-snomed output upstream.
CMS publishes the V28 ICD-10-CM→HCC mapping and the model coefficients. Load them locally (public files) and apply the model:
import csv
# 1) ICD-10-CM -> HCC (V28) crosswalk from the CMS Risk Adjustment files.
icd_to_hcc = {} # "E1122" -> "HCC38" (Diabetes w/ complication)
with open("cms_hcc_v28_icd_map.csv") as fh:
for row in csv.DictReader(fh):
icd_to_hcc[row["icd10cm"].replace(".", "")] = row["hcc_v28"]
# 2) HCC -> RAF coefficient for the relevant model segment (e.g. CNA community).
hcc_weight = {} # "HCC38" -> 0.166 (illustrative)
with open("cms_hcc_v28_coefficients.csv") as fh:
for row in csv.DictReader(fh):
hcc_weight[row["hcc"]] = float(row["coefficient"])
# 3) Apply the HCC hierarchy: a more severe HCC in a family suppresses milder
# ones (e.g. acute MI suppresses angina). Load the hierarchy from CMS.
hierarchy = { # parent HCC -> HCCs it zeroes out
# "HCC37": {"HCC38"}, # illustrative; use the official V28 hierarchy file
}
def apply_hierarchy(hccs: set[str]) -> set[str]:
kept = set(hccs)
for parent in hccs:
kept -= hierarchy.get(parent, set())
return kept
def estimate_raf(icd_codes: list[str], demo_factor: float = 0.0) -> dict:
hccs = {icd_to_hcc[c] for c in icd_codes if c in icd_to_hcc}
hccs = apply_hierarchy(hccs)
disease_raf = sum(hcc_weight.get(h, 0.0) for h in hccs)
return {"hccs": sorted(hccs),
"disease_raf": round(disease_raf, 3),
"estimated_raf": round(disease_raf + demo_factor, 3)}The demo_factor (age/sex, dual/disability, institutional status) comes from the
CMS demographic tables — add it for a full RAF; omit for the disease component.
coding-icd10) — HCCs key off ICD-10-CM.openmed.analyze_text(..., output_format="dict") returns entities, each a dict
with text, label, confidence, start, end. Use the offsets to pull MEAT
evidence sentences:
import openmed
note = ("Problem list: type 2 diabetes with diabetic nephropathy; COPD. "
"Plan: continue metformin, ordered HbA1c, refer nephrology.")
result = openmed.analyze_text(
note,
model_name="disease_detection_superclinical", # Disease category
output_format="dict",
)
DX_LABELS = {"DISEASE", "CONDITION", "PATHOLOGY"}
suspects = []
for ent in result["entities"]:
if ent["label"] in DX_LABELS:
# 1) code to ICD-10-CM (coding-icd10) -> e.g. "E1122"
icd = map_to_icd10cm(ent["text"]) # your coding step
hcc = icd_to_hcc.get(icd)
if hcc:
# MEAT: capture the sentence around the span for the reviewer
sent = note[max(0, ent["start"] - 60): ent["end"] + 80]
suspects.append({"condition": ent["text"], "icd10cm": icd,
"hcc": hcc, "span": (ent["start"], ent["end"]),
"meat_context": sent})
raf = estimate_raf([s["icd10cm"] for s in suspects])
print(raf, suspects) # candidates + estimate, for coder validationCarry OpenMed's start/end offsets so every suspect HCC links to the exact
documentation; this is what makes the suggestion auditable for RADV. Store codes,
HCCs, and offsets — not the raw note.
coding-icd10 (codes feed HCCs), mapping-to-snomed.80da98c
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.