reasonhub-valueset-properties

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ValueSet from Code System Properties

基于编码系统属性构建ValueSet

Overview

概述

Every code system loaded in ReasonHub exposes filter properties that let you define ValueSets declaratively — by clinical intent rather than by listing every code. This skill covers all five systems: what properties are available, which are most clinically useful, and how to combine them.
For deep SNOMED semantic queries, complement this skill with
snomed-semantic
. For starting from a non-SNOMED code, use
terminology-crossmap
first.

ReasonHub中加载的每个编码系统都提供过滤属性,让你可以通过临床意图而非枚举所有编码的方式来声明式定义ValueSet。本技能涵盖所有五个系统:可用的属性有哪些、哪些属性具有最高临床实用性,以及如何组合这些属性。
如需进行深度SNOMED语义查询,请结合
snomed-semantic
技能使用。如果从非SNOMED编码开始,请先使用
terminology-crossmap
技能。

Before You Start

开始之前

Always call this first to get the exact version string for your target system:
list_available_codesystem_versions()
Every
compose.include
block must include
"version"
. Omitting it will cause the expand to fail or use an unexpected default.
To see all supported filter properties for a specific system:
codesystem_filter_properties(system="<system_url>")
请始终先调用以下命令获取目标系统的精确版本字符串:
list_available_codesystem_versions()
每个
compose.include
必须包含
"version"
字段。省略该字段会导致扩展失败或使用意外的默认版本。
要查看特定系统支持的所有过滤属性:
codesystem_filter_properties(system="<system_url>")

⚠️ Calling
valueset_expand
— known pi limitation

⚠️ 调用
valueset_expand
——已知的pi限制

The
valueset
parameter is typed as a
$ref
schema object. In the pi agent, all
<parameter>
tag contents are serialized as strings
, so the MCP server always receives
valueset
as a JSON string rather than a JSON object. This causes the error:
valueset: must be object / must be null / must match a schema in anyOf
This error cannot be fixed by:
  • Reformatting the JSON (pretty-print vs compact)
  • Removing optional parameters like
    count
    or
    offset
  • Trying different quoting or escaping
  • Retrying the same call
All of these will produce the same error. Do not retry. Do not offer alternatives. Immediately run
reasonhub-skills expand
instead:
bash
echo '{ ... paste ValueSet JSON here ... }' | reasonhub-skills expand
Heredoc (
<< 'EOF'
) and
printf '%s\n' '...' |
do not work reliably
when called inside
exec
or
zsh -lc "..."
— stdin arrives empty and the CLI prints help text. Use
echo '...' |
instead.
If the CLI is not installed:
bash
curl -fsSL https://raw.githubusercontent.com/reason-healthcare/reasonhub-skills/main/bin/reasonhub-skills \
  -o ~/.local/bin/reasonhub-skills && chmod +x ~/.local/bin/reasonhub-skills
Then re-run the expand command above.
⛔ Do not read credentials yourself. Do not read
~/.reasonhub/config.toml
,
.reasonhub/config.toml
,
~/.pi/agent/mcp.json
, or any env var to extract a token and hand-roll a curl command. The
reasonhub-skills
CLI handles credentials internally. If you find yourself writing
curl ... -H "Authorization: Bearer ..."
with a token you read from a file, stop and use the CLI instead.

valueset
参数被定义为
$ref
schema对象。在pi agent中,所有
<parameter>
标签内容都被序列化为字符串
,因此MCP服务器始终将
valueset
视为JSON字符串而非JSON对象,这会导致以下错误:
valueset: must be object / must be null / must match a schema in anyOf
以下操作无法修复此错误:
  • 重新格式化JSON(美观打印 vs 紧凑格式)
  • 删除可选参数如
    count
    offset
  • 尝试不同的引号或转义方式
  • 重试相同调用
以上操作都会产生相同错误。请勿重试,请勿提供替代方案,请立即运行
reasonhub-skills expand
bash
echo '{ ... 在此粘贴ValueSet JSON ... }' | reasonhub-skills expand
注意:
exec
zsh -lc "..."
中调用时, heredoc(
<< 'EOF'
)和
printf '%s\n' '...' |
无法可靠工作——标准输入会为空,CLI会打印帮助文本。请改用
echo '...' |
如果未安装CLI:
bash
curl -fsSL https://raw.githubusercontent.com/reason-healthcare/reasonhub-skills/main/bin/reasonhub-skills \
  -o ~/.local/bin/reasonhub-skills && chmod +x ~/.local/bin/reasonhub-skills
然后重新运行上述扩展命令。
⛔ 请勿自行读取凭证。请勿读取
~/.reasonhub/config.toml
.reasonhub/config.toml
~/.pi/agent/mcp.json
或任何环境变量以提取令牌并手动编写curl命令。
reasonhub-skills
CLI会在内部处理凭证。如果您发现自己正在编写包含从文件读取的令牌的
curl ... -H "Authorization: Bearer ..."
命令,请停止并改用CLI。

SNOMED CT —
http://snomed.info/sct

SNOMED CT —
http://snomed.info/sct

SNOMED has two complementary filter mechanisms: hierarchy (IS-A traversal) and attribute equality (semantic relationship properties). The most powerful ValueSets combine both.
SNOMED有两种互补的过滤机制:层级结构(IS-A遍历)和属性相等(语义关系属性)。最强大的ValueSet会结合这两种机制。

Hierarchy filters

层级过滤器

property
op
Effect
concept
is-a
Concept + all descendants
concept
descendent-of
Strict descendants only (excludes named concept)
property
op
作用
concept
is-a
概念 + 所有子概念
concept
descendent-of
仅严格子概念(排除命名概念)

Property equality filters (most useful)

常用属性相等过滤器

property
MeaningTip
363698007
Finding siteBody structure concept ID as value
246075003
Causative agentOrganism or substance concept ID
116676008
Associated morphologyMorphologic abnormality concept ID
363704007
Procedure site - DirectBody structure concept ID
inactive
Inactive concept flagUse
"false"
to exclude retired codes
semanticTag
Semantic tag from FSN
"disorder"
,
"finding"
,
"procedure"
moduleId
SNOMED module
731000124108
= US Edition
property
含义提示
363698007
发现部位值为身体结构概念ID
246075003
致病因子值为生物体或物质概念ID
116676008
相关形态学值为形态异常概念ID
363704007
手术直接部位值为身体结构概念ID
inactive
非活跃概念标记使用
"false"
排除已停用编码
semanticTag
FSN中的语义标签例如
"disorder"
"finding"
"procedure"
moduleId
SNOMED模块
731000124108
= 美国版本

Combining filters (AND logic within one include)

组合过滤器(单个include块内为AND逻辑)

json
{
  "system": "http://snomed.info/sct",
  "version": "<version>",
  "filter": [
    { "property": "concept",   "op": "is-a", "value": "64572001" },
    { "property": "363698007", "op": "=",    "value": "80891009" },
    { "property": "inactive",  "op": "=",    "value": "false"    }
  ]
}
→ Active disorders whose finding site is the heart.
json
{
  "system": "http://snomed.info/sct",
  "version": "<version>",
  "filter": [
    { "property": "concept",   "op": "is-a", "value": "64572001" },
    { "property": "363698007", "op": "=",    "value": "80891009" },
    { "property": "inactive",  "op": "=",    "value": "false"    }
  ]
}
→ 发现部位为心脏的活跃疾病。

Multiple include blocks (OR logic between includes)

多个include块(include块间为OR逻辑)

json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "363698007", "op": "=", "value": "80891009" }]
      },
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "363698007", "op": "=", "value": "59652004" }]
      }
    ]
  }
}
→ Disorders of the heart OR atrium.
json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "363698007", "op": "=", "value": "80891009" }]
      },
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "363698007", "op": "=", "value": "59652004" }]
      }
    ]
  }
}
→ 心脏疾病或心房疾病。

Exclude blocks

Exclude块

json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "64572001" }]
      }
    ],
    "exclude": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "128139000" }]
      }
    ]
  }
}
→ All disorders EXCEPT musculoskeletal disorders.

json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "64572001" }]
      }
    ],
    "exclude": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "128139000" }]
      }
    ]
  }
}
→ 所有疾病,除了肌肉骨骼疾病。

LOINC —
http://loinc.org

LOINC —
http://loinc.org

LOINC's most useful filters are flat property equalities on
CLASS
,
CLASSTYPE
,
STATUS
, and
ORDER_OBS
. Hierarchy (
parent
,
panel-parent
) is available but less commonly needed.
LOINC最常用的过滤器是基于
CLASS
CLASSTYPE
STATUS
ORDER_OBS
的扁平属性相等过滤。层级结构过滤器(
parent
panel-parent
)可用,但不太常用。

Most useful property filters

常用属性过滤器

property
op
Key valuesUse for
CLASS
=
or
in
CHEM
,
HEM/BC
,
MICRO
,
RAD
,
CARD
,
UA
,
COAG
Discipline/panel type
CLASSTYPE
=
1
=Lab,
2
=Clinical,
3
=Claims,
4
=Survey
Broad category
STATUS
=
ACTIVE
,
DEPRECATED
,
DISCOURAGED
,
TRIAL
Lifecycle
ORDER_OBS
=
or
in
Order
,
Observation
,
Both
Ordering vs reporting
SCALE_TYP
=
LP7753-9
=Qn (quantitative),
LP7751-3
=Ord (ordinal)
Numeric vs categorical
property
op
关键值用途
CLASS
=
in
CHEM
HEM/BC
MICRO
RAD
CARD
UA
COAG
学科/面板类型
CLASSTYPE
=
1
=实验室、
2
=临床、
3
=理赔、
4
=调查
广泛分类
STATUS
=
ACTIVE
DEPRECATED
DISCOURAGED
TRIAL
生命周期
ORDER_OBS
=
in
Order
Observation
Both
开单 vs 报告
SCALE_TYP
=
LP7753-9
=定量(Qn)、
LP7751-3
=序数(Ord)
数值型 vs 分类型

Hierarchy filters

层级过滤器

property
op
value
Effect
parent
is-a
LOINC or LP codeCode + all descendants in component hierarchy
panel-parent
=
LOINC codeAll codes that are direct members of that panel
panel-parent
is exact match (
=
), not
is-a
.
Use
=
to get the direct members of a specific panel.
codesystem_lookup
on the panel code itself returns the panel’s own axes but NOT its members.
property
op
value
作用
parent
is-a
LOINC或LP编码编码 + 组件层级中的所有子编码
panel-parent
=
LOINC编码属于该面板的所有直接成员编码
注意:
panel-parent
是精确匹配(
=
),而非
is-a
。使用
=
获取特定面板的直接成员。对面板编码本身调用
codesystem_lookup
会返回面板自身的轴,但不会返回其成员。

Getting LP codes for COMPONENT and SYSTEM filters

获取COMPONENT和SYSTEM过滤器的LP编码

Always read LP codes from
codesystem_lookup
— never guess them.
codesystem_lookup("2345-7", "http://loinc.org")
请始终从
codesystem_lookup
读取LP编码——切勿猜测。
codesystem_lookup("2345-7", "http://loinc.org")

→ COMPONENT property → LP14635-4 (Glucose)

→ COMPONENT属性 → LP14635-4(葡萄糖)

→ SYSTEM property → LP7576-4 (Ser/Plas)

→ SYSTEM属性 → LP7576-4 (血清/血浆)


Using an incorrect LP code returns either 0 results or completely unrelated
codes (a wrong GFR LP code returned Babesia concepts in testing).

使用错误的LP编码会返回0条结果或完全无关的编码(测试中错误的GFR LP编码返回了巴贝斯虫相关概念)。

Common patterns

常见模式

All active quantitative lab chemistry tests (orderable):
json
{
  "system": "http://loinc.org",
  "version": "<version>",
  "filter": [
    { "property": "CLASS",     "op": "=", "value": "CHEM" },
    { "property": "CLASSTYPE", "op": "=", "value": "1" },
    { "property": "STATUS",    "op": "=", "value": "ACTIVE" },
    { "property": "ORDER_OBS", "op": "in","value": "Order,Both" },
    { "property": "SCALE_TYP", "op": "=", "value": "LP7753-9" }
  ]
}
All active hematology and chemistry tests:
json
{
  "filter": [
    { "property": "CLASS",  "op": "in", "value": "CHEM,HEM/BC" },
    { "property": "STATUS", "op": "=",  "value": "ACTIVE" }
  ]
}
All radiology observation codes:
json
{
  "filter": [
    { "property": "CLASS",     "op": "=", "value": "RAD" },
    { "property": "ORDER_OBS", "op": "=", "value": "Observation" }
  ]
}
Finding UCUM units: After expanding a LOINC ValueSet, call
codesystem_lookup
on any result code to get its
EXAMPLE_UCUM_UNITS
property for the recommended observation unit.

所有活跃的定量实验室化学测试(可开单):
json
{
  "system": "http://loinc.org",
  "version": "<version>",
  "filter": [
    { "property": "CLASS",     "op": "=", "value": "CHEM" },
    { "property": "CLASSTYPE", "op": "=", "value": "1" },
    { "property": "STATUS",    "op": "=", "value": "ACTIVE" },
    { "property": "ORDER_OBS", "op": "in","value": "Order,Both" },
    { "property": "SCALE_TYP", "op": "=", "value": "LP7753-9" }
  ]
}
所有活跃的血液学和化学测试:
json
{
  "filter": [
    { "property": "CLASS",  "op": "in", "value": "CHEM,HEM/BC" },
    { "property": "STATUS", "op": "=",  "value": "ACTIVE" }
  ]
}
所有放射学观察编码:
json
{
  "filter": [
    { "property": "CLASS",     "op": "=", "value": "RAD" },
    { "property": "ORDER_OBS", "op": "=", "value": "Observation" }
  ]
}
查找UCUM单位: 扩展LOINC ValueSet后,对任意结果编码调用
codesystem_lookup
以获取其
EXAMPLE_UCUM_UNITS
属性,即推荐的观察单位。

RxNorm —
http://www.nlm.nih.gov/research/umls/rxnorm

RxNorm —
http://www.nlm.nih.gov/research/umls/rxnorm

RxNorm's most powerful filter is
TTY
(term type). It defines what level of drug granularity you want. Relationship filters (
has_ingredient
,
tradename_of
, etc.) let you build ingredient-centric sets.
RxNorm最强大的过滤器是
TTY
(术语类型),它定义了你需要的药物粒度级别。关系过滤器(
has_ingredient
tradename_of
等)让你可以构建以成分为中心的集合。

TTY filter — choose your granularity

TTY过滤器——选择粒度

TTYMeaningWhen to use
IN
IngredientDrug class ValueSets, formulary by active substance
SCD
Semantic Clinical Drug (generic)Prescribing, order entry (no brand)
SBD
Semantic Branded DrugBrand-specific formulary
SCDF
Semantic Clinical Drug FormDose-form-level grouping
BN
Brand NameBrand lookups
GPCK
/
BPCK
Generic/Branded PackPackage-level
TTY含义使用场景
IN
成分药物类别ValueSet、基于活性物质的处方集
SCD
语义临床药物(通用)开处方、医嘱录入(无品牌)
SBD
语义品牌药物特定品牌的处方集
SCDF
语义临床药物剂型剂型级别分组
BN
品牌名称品牌查询
GPCK
/
BPCK
通用/品牌包装包装级别

Relationship filters (combine with TTY)

关系过滤器(与TTY组合使用)

property
MeaningValue type
has_ingredient
Drug contains this ingredientRxCUI of ingredient
tradename_of
Brand of this genericRxCUI of generic SCD
has_dose_form
Drug has this dose formRxCUI of dose form
has_doseformgroup
Drug has this dose form groupRxCUI of DFG
property
含义值类型
has_ingredient
药物包含该成分成分的RxCUI
tradename_of
该通用药物的品牌通用SCD的RxCUI
has_dose_form
药物具有该剂型剂型的RxCUI
has_doseformgroup
药物具有该剂型组DFG的RxCUI

Common patterns

常见模式

All generic oral solid clinical drugs:
json
{
  "filter": [
    { "property": "TTY",           "op": "=",  "value": "SCD" },
    { "property": "has_doseformgroup", "op": "=", "value": "316945" },
    { "property": "inactive",      "op": "=",  "value": "false" }
  ]
}
(316945 = Oral Solid Dosage Form Group)
All clinical drugs containing metformin (RxCUI 6809):
json
{
  "filter": [
    { "property": "TTY",           "op": "in", "value": "SCD,SCDF,SBD" },
    { "property": "has_ingredient", "op": "=", "value": "6809" }
  ]
}
All ingredients only (for drug class ValueSet):
json
{
  "filter": [
    { "property": "TTY",      "op": "=",   "value": "IN" },
    { "property": "inactive", "op": "=",   "value": "false" }
  ]
}
Tip: RxNorm hierarchy (via
parent is-a
) is sparse — IS-A traversal rarely returns what you want. Prefer
TTY
+ relationship filters.

所有口服固体通用临床药物:
json
{
  "filter": [
    { "property": "TTY",           "op": "=",  "value": "SCD" },
    { "property": "has_doseformgroup", "op": "=", "value": "316945" },
    { "property": "inactive",      "op": "=",  "value": "false" }
  ]
}
(316945 = 口服固体制剂组)
所有包含二甲双胍的临床药物(RxCUI 6809):
json
{
  "filter": [
    { "property": "TTY",           "op": "in", "value": "SCD,SCDF,SBD" },
    { "property": "has_ingredient", "op": "=", "value": "6809" }
  ]
}
仅成分(用于药物类别ValueSet):
json
{
  "filter": [
    { "property": "TTY",      "op": "=",   "value": "IN" },
    { "property": "inactive", "op": "=",   "value": "false" }
  ]
}
提示: RxNorm的层级结构(通过
parent is-a
)较为稀疏——IS-A遍历很少能返回你想要的结果。优先使用
TTY
+关系过滤器。

ICD-10-CM —
http://hl7.org/fhir/sid/icd-10-cm

ICD-10-CM —
http://hl7.org/fhir/sid/icd-10-cm

ICD-10-CM's primary filter mechanism is its tabular hierarchy via
parent
. Property equality filters exist but are mostly free-text and not useful for filtering.
ICD-10-CM的主要过滤机制是通过
parent
实现的表格层级结构。属性相等过滤器存在,但大多为自由文本,过滤实用性不高。

Hierarchy filters

层级过滤器

property
op
Effect
parent
is-a
Code + all child codes in the tabular classification
parent
descendent-of
Strict children only
property
op
作用
parent
is-a
编码 + 表格分类中的所有子编码
parent
descendent-of
仅严格子编码

Common patterns

常见模式

All diabetes codes:
json
{ "property": "parent", "op": "is-a", "value": "E11" }
All respiratory disease codes:
json
{ "property": "parent", "op": "is-a", "value": "J00-J99" }
Multiple chapters (OR, two includes):
json
{
  "compose": {
    "include": [
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "I00-I99" }]
      },
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "J00-J99" }]
      }
    ]
  }
}
→ All cardiovascular OR respiratory codes.
Tip: ICD-10-CM hierarchy is very shallow compared to SNOMED. For richer subsetting, crossmap to SNOMED first (see
terminology-crossmap
skill).

所有糖尿病编码:
json
{ "property": "parent", "op": "is-a", "value": "E11" }
所有呼吸系统疾病编码:
json
{ "property": "parent", "op": "is-a", "value": "J00-J99" }
多章节(OR逻辑,两个include块):
json
{
  "compose": {
    "include": [
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "I00-I99" }]
      },
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "J00-J99" }]
      }
    ]
  }
}
→ 所有心血管疾病或呼吸系统疾病编码。
提示: ICD-10-CM的层级结构比SNOMED浅得多。如需更丰富的子集划分,请先映射到SNOMED(参见
terminology-crossmap
技能)。

UCUM —
http://unitsofmeasure.org

UCUM —
http://unitsofmeasure.org

UCUM is compositional — compound expressions like
mg/dL
are not indexed. Filters operate only on the ~336 base and derived atom units.
UCUM是组合式的——像
mg/dL
这样的复合表达式不会被索引。过滤器仅对约336个基础和派生原子单位生效。

Most useful filters

常用过滤器

property
op
ValuesEffect
property
=
Physical quantity nameAll units measuring that quantity
CLASS
=
si
,
clinical
,
cgs
,
intcust
,
dimless
Units by class
isMetric
=
yes
/
no
Metric-prefixable units only
property
op
作用
property
=
物理量名称所有测量该物理量的单位
CLASS
=
si
clinical
cgs
intcust
dimless
按类别筛选单位
isMetric
=
yes
/
no
仅筛选可添加公制前缀的单位

Common patterns

常见模式

All mass units:
json
{ "property": "property", "op": "=", "value": "mass" }
All clinical concentration units:
json
{
  "filter": [
    { "property": "CLASS",    "op": "=", "value": "clinical" },
    { "property": "property", "op": "=", "value": "mass concentration" }
  ]
}
Validating a composed expression (mg/dL, mmol/L, etc.):
codesystem_verify_code(code="mg/dL", system="http://unitsofmeasure.org")
Use this instead of expand for composed expressions — they won't appear in an expansion but are valid UCUM codes.

所有质量单位:
json
{ "property": "property", "op": "=", "value": "mass" }
所有临床浓度单位:
json
{
  "filter": [
    { "property": "CLASS",    "op": "=", "value": "clinical" },
    { "property": "property", "op": "=", "value": "mass concentration" }
  ]
}
验证复合表达式(mg/dL、mmol/L等):
codesystem_verify_code(code="mg/dL", system="http://unitsofmeasure.org")
对于复合表达式,请使用此命令而非扩展——它们不会出现在扩展结果中,但属于有效的UCUM编码。

Cross-System ValueSets

跨系统ValueSet

ValueSets can mix multiple code systems in one compose:
json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "64572001" }]
      },
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "I00-I99" }]
      }
    ]
  }
}

ValueSet可以在一个compose中混合多个编码系统:
json
{
  "compose": {
    "include": [
      {
        "system": "http://snomed.info/sct",
        "version": "<version>",
        "filter": [{ "property": "concept", "op": "is-a", "value": "64572001" }]
      },
      {
        "system": "http://hl7.org/fhir/sid/icd-10-cm",
        "version": "<version>",
        "filter": [{ "property": "parent", "op": "is-a", "value": "I00-I99" }]
      }
    ]
  }
}

Scripting bulk expansions with
reasonhub-skills

使用
reasonhub-skills
批量扩展脚本

When expanding many ValueSets in a loop (e.g., one per LOINC COMPONENT), call
reasonhub-skills expand
from Python via
subprocess.run
with
input=
— do not use a heredoc (
<< 'EOF'
) with nested subprocess calls; that closes stdin and causes
write_stdin failed: stdin is closed
.
python
import json, subprocess

def expand(filter_list, version="2.81", count=5):
    vs = {
        "resourceType": "ValueSet",
        "compose": {"include": [{
            "system": "http://loinc.org",
            "version": version,
            "filter": filter_list
        }]}
    }
    p = subprocess.run(
        ["reasonhub-skills", "expand", f"--count={count}"],
        input=json.dumps(vs),
        text=True, capture_output=True, timeout=60
    )
    return json.loads(p.stdout)
当循环扩展多个ValueSet时(例如每个LOINC COMPONENT对应一个),请通过Python的
subprocess.run
并使用
input=
参数调用
reasonhub-skills expand
——不要在嵌套子进程调用中使用heredoc(
<< 'EOF'
),这会关闭标准输入并导致
write_stdin failed: stdin is closed
错误。
python
import json, subprocess

def expand(filter_list, version="2.81", count=5):
    vs = {
        "resourceType": "ValueSet",
        "compose": {"include": [{
            "system": "http://loinc.org",
            "version": version,
            "filter": filter_list
        }]}
    }
    p = subprocess.run(
        ["reasonhub-skills", "expand", f"--count={count}"],
        input=json.dumps(vs),
        text=True, capture_output=True, timeout=60
    )
    return json.loads(p.stdout)

Call once per analyte — sequential is fine for small sets;

针对每个分析物调用一次——小集合使用顺序执行即可;

for 20+ analytes consider asyncio or ThreadPoolExecutor

若分析物数量超过20个,可考虑使用asyncio或ThreadPoolExecutor

result = expand([{"property": "COMPONENT", "op": "=", "value": "LP14635-4"}, {"property": "STATUS", "op": "=", "value": "ACTIVE"}]) print(result["expansion"]["total"]) # 137 active Glucose terms

**Deduplication:** LOINC expansions often return the same code twice with
different display names (canonical vs. short name). Deduplicate by code
before processing:
```python
seen = {}
for c in result["expansion"].get("contains", []):
    seen.setdefault(c["code"], c["display"])

result = expand([{"property": "COMPONENT", "op": "=", "value": "LP14635-4"}, {"property": "STATUS", "op": "=", "value": "ACTIVE"}]) print(result["expansion"]["total"]) # 137个活跃的葡萄糖术语

**去重:** LOINC扩展结果常出现同一编码对应不同显示名称(规范名称 vs 简称)的情况。处理前请按编码去重:
```python
seen = {}
for c in result["expansion"].get("contains", []):
    seen.setdefault(c["code"], c["display"])

Decision Guide — Which System to Use

决策指南——选择合适的系统

Clinical goalBest systemKey filter
Clinical conditions with rich semantic subsettingSNOMED CTAttribute + hierarchy
Administrative diagnosis coding (billing)ICD-10-CM
parent is-a
Lab observation panels and resultsLOINC
CLASS
+
STATUS
Medication formulary (ordering)RxNorm
TTY=SCD
+
has_ingredient
Medication formulary (ingredient class)RxNorm
TTY=IN
Observation unitsUCUM
property
or verify composed
Rich semantic subsetting from a non-SNOMED starting pointCrossmap to SNOMEDSee
terminology-crossmap

临床目标最佳系统关键过滤器
具有丰富语义子集的临床病症SNOMED CT属性 + 层级结构
行政诊断编码(计费)ICD-10-CM
parent is-a
实验室观察面板和结果LOINC
CLASS
+
STATUS
药物处方集(开单)RxNorm
TTY=SCD
+
has_ingredient
药物处方集(成分类别)RxNorm
TTY=IN
观察单位UCUM
property
或验证复合表达式
从非SNOMED编码开始的丰富语义子集划分映射到SNOMED参见
terminology-crossmap

Debugging Expansions

扩展调试

If
valueset_expand
returns no results or an error:
  1. Check the version — run
    list_available_codesystem_versions()
    and confirm the version string matches exactly.
  2. Check the property code — run
    codesystem_filter_properties(system=...)
    to verify the property code is spelled correctly.
  3. Verify the value concept — run
    codesystem_lookup
    on the filter value to confirm it exists and is active in the right system.
  4. Test a simpler filter first — remove all but one filter condition to isolate which condition is causing empty results.
  5. For SNOMED attribute filters — look up a representative concept you expect to match and confirm it actually has the attribute you're filtering on.

如果
valueset_expand
返回无结果或错误:
  1. 检查版本——运行
    list_available_codesystem_versions()
    并确认版本字符串完全匹配。
  2. 检查属性编码——运行
    codesystem_filter_properties(system=...)
    以验证属性编码拼写正确。
  3. 验证值概念——对过滤值运行
    codesystem_lookup
    以确认其存在且在目标系统中处于活跃状态。
  4. 先测试简单过滤器——移除除一个过滤条件外的所有条件,以隔离导致无结果的条件。
  5. 对于SNOMED属性过滤器——查找一个你期望匹配的代表性概念,确认它确实具有你正在过滤的属性。

Output

输出

Every query produces two deliverables.
每个查询会生成两个交付物。

1. FHIR ValueSet JSON (always deliver this)

1. FHIR ValueSet JSON(始终交付)

Return a complete
ValueSet
resource with
name
,
title
,
status
, and a populated
compose.include
. This is always useful regardless of whether expansion succeeds or fails.
返回完整的
ValueSet
资源,包含
name
title
status
和填充完成的
compose.include
。无论扩展成功与否,此资源始终有用。

2. Expansion (ask the user)

2. 扩展结果(询问用户)

After delivering the ValueSet JSON, ask:
"Would you like me to expand this and show the matching codes? I can format results as a markdown table or CSV."
Attempt
valueset_expand
once if the user says yes. On failure, immediately run
reasonhub-skills expand
with the same ValueSet JSON — do not explain, do not offer alternatives, just run it.
If expansion succeeds, check the response for a
total
count. The MCP transport layer truncates returned rows regardless of the
count
parameter, and
offset
-based paging is unreliable. If rows returned are fewer than
total
, label the output explicitly and stop:
⚠️ Partial result — {n} of {total} codes shown. The full set is defined by the ValueSet JSON above; run it against any FHIR terminology server for the complete expansion.
Do not retry with different
count
or
offset
values — this will not retrieve additional rows.
Markdown table (default):
CodeDisplay
44054006
Type 2 diabetes mellitus
CSV (when the user asks to download, import, or use in a spreadsheet):
csv
code,display
44054006,"Type 2 diabetes mellitus"
For SNOMED, add
semanticTag
as a third column when the expansion mixes concept types. For LOINC,
EXAMPLE_UCUM_UNITS
is a useful addition for quantitative observation sets. For RxNorm,
TTY
clarifies whether each row is an ingredient, clinical drug, or branded product.
交付ValueSet JSON后,请询问:
"是否需要我扩展此ValueSet并显示匹配的编码? 我可以将结果格式化为Markdown表格CSV。"
如果用户同意,请尝试一次
valueset_expand
。若失败,请立即使用相同的ValueSet JSON运行
reasonhub-skills expand
——无需解释,无需提供替代方案,直接运行即可。
如果扩展成功,请检查响应中的
total
计数。无论设置
count
参数如何,MCP传输层都会截断返回的行,且基于
offset
的分页不可靠。如果返回的行数少于
total
,请明确标记输出并停止:
⚠️ 部分结果——显示{n}条,共{total}条编码。完整集合由上述ValueSet JSON定义;可在任何FHIR术语服务器上运行以获取完整扩展结果。
请勿尝试使用不同的
count
offset
值重试——这无法获取更多行。
Markdown表格(默认):
编码显示名称
44054006
2型糖尿病
CSV(当用户要求下载、导入或用于电子表格时):
csv
code,display
44054006,"2型糖尿病"
对于SNOMED,当扩展结果包含多种概念类型时,添加
semanticTag
作为第三列。对于LOINC,对于定量观察集合,添加
EXAMPLE_UCUM_UNITS
会很有用。对于RxNorm,
TTY
可明确每行是成分、临床药物还是品牌产品。