Agent Skillsmaziyarpanahi/openmed › assembling-fhir-bundles

assembling-fhir-bundles

GitHub

将多个FHIR R4资源组装为有效的事务Bundle,用于POST到EHR。支持确定性URN、自动引用重写及请求块生成,适用于需打包Condition等资源的场景。

skills/assembling-fhir-bundles/SKILL.md maziyarpanahi/openmed

Trigger Scenarios

用户要求构建或打包 Bundle 需要将多个独立 FHIR 资源 POST 到服务器 提及 transaction、references 或 posting

Install

npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -g -y
More Options

Use without installing

npx skills use maziyarpanahi/openmed@assembling-fhir-bundles

指定 Agent (Claude Code)

npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -a claude-code -g -y

安装 repo 全部 skill

npx skills add maziyarpanahi/openmed --all -g -y

预览 repo 内 skill

npx skills add maziyarpanahi/openmed --list

SKILL.md

Frontmatter
{
    "name": "assembling-fhir-bundles",
    "license": "Apache-2.0",
    "metadata": {
        "pairs": "after",
        "project": "OpenMed",
        "version": "1.0",
        "category": "fhir-interop"
    },
    "description": "Package multiple FHIR R4 resources produced from OpenMed output into a single valid transaction Bundle ready to POST to an EHR, using OpenMed's verified bundle assembler openmed.clinical.exporters.fhir.to_bundle. Covers deterministic urn:uuid fullUrls, automatic in-Bundle reference rewriting, request blocks (method\/url) for transaction vs batch, and conditional create. Use after exporting-to-fhir when the user has several Condition\/Observation\/MedicationStatement resources and wants one transaction Bundle, mentions Bundle, transaction, references, or posting to a FHIR server. Builds on exporting-to-fhir; pairs after."
}

Assembling FHIR Bundles

A FHIR server ingests one transaction Bundle, not loose resources, and the resources inside it must cross-reference each other (Condition.subject → Patient, Observation.encounter → Encounter, DiagnosticReport.result → Observation). OpenMed ships a deterministic, mechanical Bundle assembler — openmed.clinical.exporters.fhir.to_bundle — that wraps the resources you built in exporting-to-fhir into a valid R4 Bundle and wires up the references.

When to use

Use after you have a list of standalone resources from exporting-to-fhir and the destination is a FHIR server. Reach for it when the user says "build a Bundle", "transaction", "POST these resources", or needs internal references resolved. To check the Bundle against US Core, hand off to validating-us-core.

What OpenMed gives you (verified API)

from openmed.clinical.exporters.fhir import to_bundle, deterministic_fullurl

bundle = to_bundle(
    resources,                       # Sequence[Mapping] each with a resourceType
    doc_id="note-2024-03-02-001",    # seeds stable urn:uuid fullUrls
    bundle_type="transaction",       # "transaction" | "batch" | "collection" | ...
)

to_bundle does exactly three things, and never synthesises or validates:

  1. Deterministic fullUrl. Each resource gets a urn:uuid seeded by doc_id + its index, so the same input always produces byte-identical output (golden-test friendly). You can pre-compute the same urn with deterministic_fullurl(doc_id, index).
  2. Reference rewriting. Any {"reference": "ResourceType/id"} whose target is present in the Bundle is repointed at that resource's fullUrl. References to resources absent from the Bundle (e.g. a Patient removed by de-identification) are left untouched — no dangling internal refs.
  3. Request blocks. For transaction/batch bundles each entry gets a request block ({"method": "POST", "url": "<ResourceType>"}) so the server knows to create it.

It raises ValueError if a resource lacks resourceType, or if two resources share the same ResourceType/id (duplicate ids would silently corrupt the reference map).

Quick start

from openmed.clinical.exporters.fhir import to_bundle
from openmed.clinical.exporters.codeable_concept_simple import coding, codeable_concept

condition = {
    "resourceType": "Condition", "id": "cond-1",
    "clinicalStatus": {"coding": [{
        "system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
        "code": "active"}]},
    "code": codeable_concept(
        [coding("snomed", "44054006", "Diabetes mellitus type 2")],
        text="type 2 diabetes"),
    "subject": {"reference": "Patient/patient-1"},   # internal ref, rewritten
}
medication = {
    "resourceType": "MedicationStatement", "id": "med-1", "status": "active",
    "medicationCodeableConcept": codeable_concept(
        [coding("rxnorm", "860975", "metformin 500 MG Oral Tablet")],
        text="metformin 500 mg"),
    "subject": {"reference": "Patient/patient-1"},
}
patient = {
    "resourceType": "Patient", "id": "patient-1",
    "gender": "unknown",                              # de-identified, synthetic
}

bundle = to_bundle([patient, condition, medication],
                   doc_id="demo-note", bundle_type="transaction")

Worked: the transaction Bundle

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:6f1c...e2",
      "resource": { "resourceType": "Patient", "id": "patient-1", "gender": "unknown" },
      "request": { "method": "POST", "url": "Patient" }
    },
    {
      "fullUrl": "urn:uuid:9a3b...77",
      "resource": {
        "resourceType": "Condition", "id": "cond-1",
        "subject": { "reference": "urn:uuid:6f1c...e2" }
      },
      "request": { "method": "POST", "url": "Condition" }
    },
    {
      "fullUrl": "urn:uuid:c0d4...19",
      "resource": {
        "resourceType": "MedicationStatement", "id": "med-1",
        "subject": { "reference": "urn:uuid:6f1c...e2" }
      },
      "request": { "method": "POST", "url": "MedicationStatement" }
    }
  ]
}

Note Condition.subject and MedicationStatement.subject were rewritten from "Patient/patient-1" to the Patient entry's fullUrl — that is what makes the transaction resolvable in a single POST.

Workflow

  1. Build resources with exporting-to-fhir; give each a unique id.
  2. Put any resource you reference inside the same Bundle — including the Patient — so the reference resolves. References to resources you intend to be already on the server (e.g. an existing Patient) are left as literal "Patient/<id>"; resolve those with conditional create (below).
  3. Call to_bundle(resources, doc_id=<stable>, bundle_type="transaction").
  4. POST the whole Bundle to the server base: POST [base] {Bundle}.
  5. Validate first against US Core (validating-us-core).

Conditional create (don't duplicate an existing Patient)

to_bundle writes POST <ResourceType> request blocks. To make a transaction idempotent, post-process the entry's request to add an ifNoneExist query so the server reuses an existing match instead of creating a duplicate:

for entry in bundle["entry"]:
    if entry["resource"]["resourceType"] == "Patient":
        entry["request"]["ifNoneExist"] = "identifier=http://hospital.example|MRN-REDACTED"

The server creates the Patient only if no match exists; otherwise it links the references to the existing one. PUT with a known id is the alternative for true upserts.

Hand-off to / from OpenMed

  • From OpenMed: the resource list comes from exporting-to-fhir, which in turn comes from openmed.analyze_text. Keep doc_id stable per source document so re-running the pipeline yields the same Bundle.
  • De-identify a built Bundle: openmed.interop.fhir_operations.de_identify_bundle(bundle) walks every entry's free text + XHTML narrative and de-identifies it while preserving Bundle type, entry order, fullUrls, request blocks, and references — codes, systems, and temporal values are never altered. Use it as a final safety pass before transmission if any narrative might carry PHI.
  • OperationOutcome: a transaction either fully succeeds or fully fails; the server returns a Bundle of responses (or an OperationOutcome on error). Surface those to the user; for your own pre-flight findings use to_operation_outcome(...) from the same package.

Edge cases & gotchas

  • Resources without an id are valid but unreferenceable — nothing can point at them and they will not be reference-rewrite targets.
  • Duplicate ResourceType/id raises. This is intentional: a duplicate id would silently overwrite an entry in the reference map and corrupt cross-references. Make ids unique.
  • External references are left alone. Only references whose target is in the Bundle are rewritten; a "Patient/existing-123" you mean to resolve on the server stays literal — pair it with ifNoneExist or a PUT.
  • transaction vs batch. transaction is atomic (all-or-nothing, server resolves urn:uuid references); batch is independent per-entry and does not guarantee reference resolution. Use transaction when entries reference each other.
  • collection/document bundles get no request blocks (only transaction/batch do) — correct, since they are not meant to be POSTed for creation.
  • The assembler does not validate profiles. Run validating-us-core before submission.

Standards & references

Version History

  • f213557 Current 2026-07-23 00:43

Same Skill Collection

skills/building-with-openmed/SKILL.md
skills/loading-openmed-models/SKILL.md
skills/annotating-variants/SKILL.md
skills/auditing-deid-leakage/SKILL.md
skills/auditing-deidentification-runs/SKILL.md
skills/auditing-part11-trails/SKILL.md
skills/auditing-safe-harbor-checklist/SKILL.md
skills/auditing-subgroup-fairness/SKILL.md
skills/authoring-model-cards/SKILL.md
skills/batch-processing-clinical-text/SKILL.md
skills/benchmarking-clinical-ner/SKILL.md
skills/bridging-presidio-and-spacy/SKILL.md
skills/building-gold-corpus/SKILL.md
skills/building-patient-timelines/SKILL.md
skills/checking-hipaa-compliance/SKILL.md
skills/choosing-openmed-models/SKILL.md
skills/coding-hcc-risk-adjustment/SKILL.md
skills/coding-icd10/SKILL.md
skills/computing-ecqms/SKILL.md
skills/configuring-privacy-policies/SKILL.md
skills/defining-cohort-phenotypes/SKILL.md
skills/deidentifying-clinical-text/SKILL.md
skills/deidentifying-multilingual-text/SKILL.md
skills/deploying-openmed-mcp/SKILL.md
skills/detecting-pv-signals/SKILL.md
skills/enforcing-nophi-logging/SKILL.md
skills/etl-to-omop-cdm/SKILL.md
skills/evaluating-with-leakage-gates/SKILL.md
skills/exporting-bulk-fhir/SKILL.md
skills/exporting-to-fhir/SKILL.md
skills/extracting-clinical-entities/SKILL.md
skills/extracting-dicom-metadata/SKILL.md
skills/extracting-lab-tables/SKILL.md
skills/extracting-pii-entities/SKILL.md
skills/extracting-sdoh/SKILL.md
skills/fetching-fhir-resources/SKILL.md
skills/gating-deid-leakage/SKILL.md
skills/generating-synthea-data/SKILL.md
skills/generating-synthetic-surrogates/SKILL.md
skills/ingesting-clinical-documents/SKILL.md
skills/linking-umls-concepts/SKILL.md
skills/mapping-loinc/SKILL.md
skills/mapping-to-snomed/SKILL.md
skills/mining-pubmed-literature/SKILL.md
skills/normalizing-rxnorm/SKILL.md
skills/parsing-ccda-documents/SKILL.md
skills/parsing-hl7v2-messages/SKILL.md
skills/parsing-lab-values/SKILL.md
skills/parsing-trial-eligibility/SKILL.md

Metadata

Files
0
Version
f213557
Hash
651f5e1c
Indexed
2026-07-23 00:43

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-30 06:56
浙ICP备14020137号-1 $Carte des visiteurs$