Agent skill

FHIR Bundle Assembler

by maziyarpanahi in maziyarpanahi/openmed

Packages standalone FHIR R4 resources from OpenMed output into one transaction Bundle with stable fullUrls and rewritten references, ready to post to a FHIR server.

Apache-2.0Auto-check passedResearch & Science

Install FHIR Bundle Assembler

skills CLI
$ npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install maziyarpanahi/openmed assembling-fhir-bundles --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/maziyarpanahi/openmed.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/assembling-fhir-bundles .claude/skills/assembling-fhir-bundles && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
assembling-fhir-bundles
GitHub stars
5.5k
Token cost
~2.2k tokens
SKILL.md length
690 words
Files
1
Skills in repo
74
Repo updated
First seen
Licence
Apache-2.0

At a glance

Packages standalone FHIR R4 resources from OpenMed output into one transaction Bundle with stable fullUrls and rewritten references, ready to post to a FHIR server.

  • Works in 3 steps: Deterministic fullUrl. Each resource… → Reference rewriting. Any {"reference":… → Request blocks. For transaction/batch…
  • Combining several Condition, Observation and MedicationStatement resources into one Bundle
  • SKILL.md covers When to use, What OpenMed gives you…, Quick start and Worked: the transaction Bundle, plus 4 more sections
  • Reaches terminology.hl7.org

What it does

A FHIR server takes a single transaction Bundle whose resources reference each other, and the skill uses OpenMed's mechanical assembler, to_bundle in openmed.clinical.exporters.fhir, to build it from the resources made in the earlier exporting-to-fhir step. It does exactly three things: give each resource a urn:uuid fullUrl seeded by document ID and index so the same input always yields identical output, repoint references to resources present in the Bundle, and add request blocks for transaction or batch types.

References whose targets are absent from the Bundle, such as a Patient removed by de-identification, are left alone. The function raises ValueError for a resource without resourceType or for two resources sharing the same type and ID, and it never invents or validates content, so checking against US Core is handed to a separate validating skill. The description also mentions conditional create.

When your agent uses it

  • Combining several Condition, Observation and MedicationStatement resources into one Bundle
  • Preparing resources to POST to an EHR or FHIR server
  • Making Bundle output byte-identical for golden tests

Example prompts

  • “Take these exported Condition and Observation resources and assemble one transaction Bundle for our FHIR server.”
  • “Build the Bundle with deterministic fullUrls so we can use it in a golden test.”

Requirements

  • Python with the OpenMed package
  • FHIR R4 resources already exported by the exporting-to-fhir skill

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Deterministic fullUrl. Each resource gets a urn:uuid seeded by
  2. Reference rewriting. Any {"reference": "ResourceType/id"} whose target
  3. Request blocks. For transaction/batch bundles each entry gets a

What it can do on your machine

Read from SKILL.md and the folder at commit 34d7b8c. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python and json).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • terminology.hl7.org

    Also links to:

    • hl7.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

FHIR Bundle Assembler loads about 2.2k tokens when it runs. Until then it costs about 162 tokens; SKILL.md has 690 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~162
When it runs · the whole SKILL.md, loaded when a task matches
~2.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from maziyarpanahi/openmed at commit 34d7b8c, republished under its Apache-2.0 licence (© maziyarpanahi). 690 words, ~2,194 tokens.

Download SKILL.mdSave it as .claude/skills/assembling-fhir-bundles/SKILL.md (or your agent's skills folder).
name
assembling-fhir-bundles
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.
license
Apache-2.0
metadata.project
OpenMed
metadata.category
fhir-interop
metadata.pairs
after
metadata.version
1.0

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)

python
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

python
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

json
{
  "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:

python
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.

Show full SKILL.md (274 more words)Show less

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

© maziyarpanahi, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/assembling-fhir-bundles of maziyarpanahi/openmed.

Open the folder on GitHubat commit 34d7b8c

Compare with similar skills

FHIR Bundle Assembler next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

FHIR Bundle Assembler compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
FHIR Bundle Assembler this skillmaziyarpanahi/openmed5.5k—~2.2kAutomated safety check: PassApache-2.0
MCP Server Builderanthropics/skills180k63 repos~2.3kAutomated safety check: PassApache-2.0
MCP Server BuildershareAI-lab/learn-claude-code78k4 repos~1.2kAutomated safety check: PassMIT
Firecrawl Page Scrape Integrationfirecrawl/firecrawl190k1 repos~944Automated safety check: PassISC
Firecrawl Interact Integrationfirecrawl/firecrawl190k1 repos~731Automated safety check: PassISC
CCXT Crypto Exchange Library2025Emma/vibe-coding-cn23k1 repos~4.4kAutomated safety check: PassMIT

Similar skills

  • MCP Server Builder

    anthropics/skills

    Official

    Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.

    180k GitHub starsUsed in 63 repos~2.3k tokens
    Agent WorkflowsAuto-check passed
  • MCP Server Builder

    shareAI-lab/learn-claude-code

    Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.

    78k GitHub starsUsed in 4 repos~1.2k tokens
    Agent WorkflowsAuto-check passed
  • Adds Firecrawl's /scrape endpoint to application code to pull markdown, HTML, links, screenshots or structured data from a single known URL.

    190k GitHub starsUsed in 1 repo~944 tokens
    Data & AnalyticsAuto-check passed
  • Guides adding Firecrawl's /interact endpoint to product code for pages that need clicks, forms, pagination or logged-in flows beyond plain scraping.

    190k GitHub starsUsed in 1 repo~731 tokens
    Data & AnalyticsAuto-check passed
  • CCXT Crypto Exchange Library

    2025Emma/vibe-coding-cn

    Reference help for the CCXT library covering crypto exchange APIs, market data, trading and order management across 150+ exchanges in JavaScript, Python and PHP.

    23k GitHub starsUsed in 1 repo~4.4k tokens
    Business, Finance & HRAuto-check passed
  • Tavily Search API Integration

    andrewyng/context-hub

    Guides building Tavily integrations for web search, URL extraction, site crawling and AI-assisted research in Python or JavaScript agent and RAG projects.

    14k GitHub stars~1.1k tokensUpdated 4 mo ago
    AI & LLM EngineeringAuto-check passed

More from maziyarpanahi/openmed

All 74 skills in this repo
  • Checks OpenMed de-identified clinical text against the 18 HIPAA Safe Harbor identifier categories and reports gaps and residual re-identification risk.

    5.5k GitHub stars~1.7k tokensUpdated today
    Auto-check passed
  • OpenMed Model Card Writer

    maziyarpanahi/openmed

    Fills in a model card for an OpenMed clinical NER or de-identification model from its evaluation reports: intended use, metrics, subgroups and limitations.

    5.5k GitHub stars~1.8k tokensUpdated today
    Auto-check passed
  • Walks a data pipeline against the HIPAA Privacy and Security Rule checklist and produces a gap report before it processes patient data.

    5.5k GitHub stars~2k tokensUpdated today
    Auto-check passed
  • ICD-10 Coding Assistant

    maziyarpanahi/openmed

    Suggests candidate ICD-10-CM diagnosis and ICD-10-PCS procedure codes for clinical text extracted by OpenMed, with rationale for a certified coder to review.

    5.5k GitHub stars~2k tokensUpdated today
    Auto-check passed
  • OpenMed ETL to OMOP CDM

    maziyarpanahi/openmed

    Maps OpenMed-extracted, terminology-coded conditions, drugs and measurements into OMOP CDM v5.4 tables for OHDSI and ATLAS analytics.

    5.5k GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Extracting SDOH and Z-Codes

    maziyarpanahi/openmed

    Finds social risks such as housing instability or food insecurity in clinical notes and proposes matching ICD-10-CM Z-codes for a coder to confirm.

    5.5k GitHub stars~1.9k tokensUpdated today
    Auto-check passed

Works with

Questions about FHIR Bundle Assembler

What does FHIR Bundle Assembler do?

Packages standalone FHIR R4 resources from OpenMed output into one transaction Bundle with stable fullUrls and rewritten references, ready to post to a FHIR server. fhir, to build it from the resources made in the earlier exporting-to-fhir step. It does exactly three things: give each resource a urn:uuid fullUrl seeded by document ID and index so the same input always yields identical output, repoint references to resources present in the Bundle, and add request blocks for transaction or batch types.

When should I use FHIR Bundle Assembler?

FHIR Bundle Assembler fits situations like: combining several Condition, Observation and MedicationStatement resources into one Bundle; preparing resources to POST to an EHR or FHIR server; making Bundle output byte-identical for golden tests.

How do I install FHIR Bundle Assembler in Claude Code?

Run `npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -a claude-code`. Or copy the skill folder (skills/assembling-fhir-bundles in maziyarpanahi/openmed) into .claude/skills/assembling-fhir-bundles in your project. Claude Code loads it when a task matches its description.

How do I install FHIR Bundle Assembler in Codex?

Run `npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -a codex`. Or copy the skill folder (skills/assembling-fhir-bundles in maziyarpanahi/openmed) into .agents/skills/assembling-fhir-bundles in your project. Codex loads it when a task matches its description.

Can I use FHIR Bundle Assembler in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add maziyarpanahi/openmed --skill assembling-fhir-bundles -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/assembling-fhir-bundles, .gemini/skills/assembling-fhir-bundles, .github/skills/assembling-fhir-bundles and .opencode/skills/assembling-fhir-bundles in your project.

What does FHIR Bundle Assembler need to run?

SKILL.md names no scripts, command-line tools or credentials: FHIR Bundle Assembler is instructions for the agent only. Our summary lists: Python with the OpenMed package; FHIR R4 resources already exported by the exporting-to-fhir skill.

Does FHIR Bundle Assembler access the network?

SKILL.md names 2 domains. In commands or code: terminology.hl7.org; the agent is likely to contact it when it follows the instructions. As links in the text: hl7.org. This is read from the text; nothing was executed.

Is FHIR Bundle Assembler safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does FHIR Bundle Assembler use?

FHIR Bundle Assembler is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does FHIR Bundle Assembler use?

About 2.2k tokens (SKILL.md is roughly 8.8k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to FHIR Bundle Assembler?

Skills that share tags, products or a category with FHIR Bundle Assembler: MCP Server Builder (anthropics/skills, 180k stars), MCP Server Builder (shareAI-lab/learn-claude-code, 78k stars), Firecrawl Page Scrape Integration (firecrawl/firecrawl, 190k stars) and Firecrawl Interact Integration (firecrawl/firecrawl, 190k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains FHIR Bundle Assembler?

maziyarpanahi (a GitHub user) maintains it in maziyarpanahi/openmed, which has 5,506 GitHub stars. The repository holds 74 skills in this directory. The repository was last updated on October 11, 2026.

Source: maziyarpanahi/openmed on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.