Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    hl7 fhir bridge

    1

    Convert HL7 v2 messages to FHIR R4 Bundles with deterministic mapping and regional profile validation.

    Free

    1 installSecurity scanned
    hl7 fhir bridge

    hl7 fhir bridge

    Example session with this skill installed

    I'm wiring Acme Lab's result feed into our patient-facing app, which consumes FHIR R4. Can you convert this ORU to FHIR and tell me if it's US Core-ready? I also need a short list of what to ask the lab to fix.

    MSH|^~&|ACMELAB|ACME|PATAPP|CLINIC|20261014093000||ORU^R01^ORU_R01|ACME000417|P|2.5.1
    PID|1||MRN-88231^^^CLINIC^MR||RIVERA^ANA^M||19870412|
    OBR|1|ORD-5521^PATAPP|ACME-77310^ACMELAB|24357-6^URINALYSIS MACRO PANEL^LN|||20261014081500|||||||||||||||||F
    OBX|1|NM|2350-7^GLUCOSE UR^LN||100|mg/dL|<15|H|||F|||20261014084000
    OBX|2|CE|5778-6^COLOR OF URINE^LN||DKYEL^DARK YELLOW^99ACME||||||F|||20261014084000
    NTE|1|L|Specimen received 35 min after collection

    • Read your context and instructions
    • Compiled the hl7 fhir bridge

    Verdict: converted, but not US Core-ready. I validated against the us-core profile and got 1 error and 2 warnings. I also found two blocking problems the validator doesn't check: the DiagnosticReport has no status, and the timestamps have no time zone. Both are under "Not checked by the engine" below.

    This is a translation and validation aid, not a medical device. These results will reach patients, so have someone check the mapped output before go-live.

    Resources

    ResourceKey content
    Patientidentifier MRN-88231 (system CLINIC), name (family + first given), birthDate 1987-04-12, no gender
    Observation2350-7 GLUCOSE UR (LOINC), 100 mg/dL, reference range text <15, interpretation H (high), final, effective 2026-10-14T08:40:00
    Observation5778-6 COLOR OF URINE (LOINC), value DKYEL "DARK YELLOW" (no code system), final, effective 2026-10-14T08:40:00
    DiagnosticReport24357-6 URINALYSIS MACRO PANEL (LOINC), category LAB, links to both Observations and the Patient. No status, no effective/issued time, no identifier

    Observation.category = laboratory is a fixed value the ORU map always sets, because HL7 v2 has no field for it. It isn't a guess.

    Issues (from the engine)

    SeverityCodeLocationWhat it meansHow to fix
    errorPROFILE_REQUIREDPatient.genderUS Core Patient requires gender. PID-8 (the patient's administrative sex) is empty in the message.The lab populates PID-8. Don't fill the gap from the M in PID-5. That's the middle-name component (RIVERA^ANA^M), not sex.
    warningCODING_NO_SYSTEMObservation.valueCodeableConcept.coding[0]The urine-color answer DKYEL has no system URI. OBX-5.3 is 99ACME, a lab-local code system, so nothing downstream can tell what the code means.The lab adds a standard code (LOINC answer or SNOMED CT) in OBX-5.4–5.6 and/or gives us the canonical URI for 99ACME. We then register that URI in the ORU map. We don't guess it.
    warningUNMAPPED_SEGMENTNTEThe ORU map doesn't read NTE (comment) segments, so the note "Specimen received 35 min after collection" is not in the Bundle.Map side: NTE → Observation.note is still listed as pending in the ORU map. Until it's added, your app won't show this note.

    Not checked by the engine (my observations)

    I confirmed each of these by parsing the message or reading the Bundle. They're my own findings, separate from the deterministic list above.

    1. The DiagnosticReport has no status, which makes it invalid FHIR R4. The OBR segment has only 24 fields, so the F landed in OBR-24 (diagnostic service section) instead of OBR-25 (result status). The | before it is one short. status is mandatory (1..1) in base FHIR R4 and in US Core. I re-ran a synthetic message with F in OBR-25 and it mapped to status: final.

    Timestamps have no time zone. OBX-14 20261014084000 becomes 2026-10-14T08:40:00. FHIR R4 doesn't allow a dateTime with a time but no offset, so strict FHIR parsers will reject it. MSH-7 and OBR-7 have the same problem. I checked that an offset sent by the lab (e.g. …084000-0500) is kept in the output.
    3.

    The DiagnosticReport has no effective/issued time. OBR-7 (collection time) is in the message, but the ORU map doesn't map OBR-7 or OBR-22 yet (documented as pending). OBR-22 (report time) is also empty in the message. US Core's lab DiagnosticReport expects an effective time. This is a gap in the map, not a lab error.
    4.

    The order and report IDs aren't carried over. OBR-2 (placer ORD-5521) and OBR-3 (filler ACME-77310) don't reach DiagnosticReport.identifier or basedOn. Without them, a later corrected result can't be matched to this one, and your app would show duplicates. Map side.
    5.

    Patient.identifier.system is "CLINIC", not a URI. The map copies PID-3.4 (assigning authority) as-is. This is a known, deliberate TODO(mapeo) gap in the ORU map. It passes the engine's US Core rule because system and value are both present, but it isn't a resolvable namespace. This is your own MRN echoed back, so you decide the URI, not the lab.
    6.

    The NTE probably sits in the wrong place. It comes right after OBX 2, so under HL7 rules it's a note on the urine-color result. The text reads like a note about the whole specimen.
    7. Minor gaps:

    • The middle initial (PID-5.3) isn't mapped.
    • valueQuantity carries only the mg/dL text, with no UCUM system/code. It stays that way even if OBX-6 says ^^UCUM, which I checked. It's fine for display, but the map needs it if the app compares or converts units.

    The engine checks structure and must-support elements for Patient, Observation and codings. It doesn't check full IG conformance or terminology bindings. Before go-live, run the official HL7 FHIR Validator with US Core as a second pass.

    What to ask Acme Lab to fix

    1. Populate PID-8 (administrative sex). This clears the only US Core error.

    Put the result status in OBR-25. Add the missing | before F. Right now it lands in OBR-24 and the report has no status.
    3. Send timestamps with a UTC offset in MSH-7, OBR-7 and OBX-14, e.g. 20261014084000-0500.
    4.

    Code coded results with a standard system. Send a LOINC answer or SNOMED CT code in OBX-5.4–5.6 with coding system LN or SCT, and/or tell us the canonical URI of 99ACME.
    5. Two smaller items:

    • Populate OBR-22 (report time).
    • Check where the NTE belongs. If the note is about the whole specimen, they should send it right after OBR instead of after the urine-color OBX.

    Bundle (exactly as produced)

    {
      "resourceType": "Bundle",
      "type": "collection",
      "entry": [
        {
          "fullUrl": "urn:uuid:4d76e1a9-53d4-42ad-94e1-04d8cd13997e",
          "resource": {
            "resourceType": "Patient",
            "identifier": [
              {
                "value": "MRN-88231",
                "system": "CLINIC"
              }
            ],
            "name": [
              {
                "family": "RIVERA",
                "given": [
                  "ANA"
                ]
              }
            ],
            "birthDate": "1987-04-12"
          }
        },
        {
          "fullUrl": "urn:uuid:386051ae-c102-4c64-8ccc-da62ab40eca6",
          "resource": {
            "resourceType": "Observation",
            "category": [
              {
                "coding": [
                  {
                    "system": "http://terminology.hl7.org/CodeSystem/observation-category",
                    "code": "laboratory"
                  }
                ]
              }
            ],
            "status": "final",
            "code": {
              "coding": [
                {
                  "code": "2350-7",
                  "display": "GLUCOSE UR",
                  "system": "http://loinc.org"
                }
              ]
            },
            "valueQuantity": {
              "value": 100,
              "unit": "mg/dL"
            },
            "interpretation": [
              {
                "coding": [
                  {
                    "code": "H",
                    "system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
                  }
                ]
              }
            ],
            "referenceRange": [
              {
                "text": "<15"
              }
            ],
            "effectiveDateTime": "2026-10-14T08:40:00",
            "subject": {
              "reference": "urn:uuid:4d76e1a9-53d4-42ad-94e1-04d8cd13997e"
            }
          }
        },
        {
          "fullUrl": "urn:uuid:f306779d-0e58-4e43-acd6-c051ed13b5c3",
          "resource": {
            "resourceType": "Observation",
            "category": [
              {
                "coding": [
                  {
                    "system": "http://terminology.hl7.org/CodeSystem/observation-category",
                    "code": "laboratory"
                  }
                ]
              }
            ],
            "status": "final",
            "code": {
              "coding": [
                {
                  "code": "5778-6",
                  "display": "COLOR OF URINE",
                  "system": "http://loinc.org"
                }
              ]
            },
            "valueCodeableConcept": {
              "coding": [
                {
                  "code": "DKYEL",
                  "display": "DARK YELLOW"
                }
              ]
            },
            "effectiveDateTime": "2026-10-14T08:40:00",
            "subject": {
              "reference": "urn:uuid:4d76e1a9-53d4-42ad-94e1-04d8cd13997e"
            }
          }
        },
        {
          "fullUrl": "urn:uuid:7e621ab3-2718-4b83-9759-7010e94d71dc",
          "resource": {
            "resourceType": "DiagnosticReport",
            "category": [
              {
                "coding": [
                  {
                    "system": "http://terminology.hl7.org/CodeSystem/v2-0074",
                    "code": "LAB"
                  }
                ]
              }
            ],
            "code": {
              "coding": [
                {
                  "code": "24357-6",
                  "display": "URINALYSIS MACRO PANEL",
                  "system": "http://loinc.org"
                }
              ]
            },
            "result": [
              {
                "reference": "urn:uuid:386051ae-c102-4c64-8ccc-da62ab40eca6"
              },
              {
                "reference": "urn:uuid:f306779d-0e58-4e43-acd6-c051ed13b5c3"
              }
            ],
            "subject": {
              "reference": "urn:uuid:4d76e1a9-53d4-42ad-94e1-04d8cd13997e"
            }
          }
        }
      ]
    }
    

    Next steps

    1. Send the lab list above to Acme. Items 1–3 block US Core and valid R4. Item 4 removes the coding warning.
    2. Extend the ORU map on our side:
      • Map OBR-7 → DiagnosticReport.effectiveDateTime, OBR-22 → issued, and OBR-2/OBR-3 → identifier.
      • Map NTE → Observation.note.
      • Register the 99ACME URI once Acme provides it.
      • Decide the URI for the CLINIC MRN namespace.

    Re-test with a corrected sample. Re-run map --profile us-core on a corrected sample from Acme, then run the official HL7 FHIR Validator (US Core) as a second pass before go-live.

    Connects securely to your tools. The creator never sees your data.

    About this skill

    Handling HL7 v2 to FHIR R4 translation is notoriously error-prone, often resulting in silent failures or non-compliant JSON that breaks downstream systems. This skill integrates a deterministic offline engine that maps, validates, and explains interoperability issues with surgical precision.

    What it does

    • Deterministic mapping translates HL7 v2 messages (ADT, ORU, ORM, OUL) into FHIR R4 Bundles using declarative YAML maps.
    • Localized validation checks outputs against US Core, CL Core (Chile), or CO Core (Colombia) profiles.
    • Segment-level error reporting identifies the exact location of failures in both the source HL7 segment and the target FHIRPath.
    • Message parsing breaks down MSH, PID, OBR, and OBX segments to inspect message structure without full conversion.
    • Issue explanation interprets external logs or validation errors to provide actionable remediation steps.

    How it works

    1. Command selection involves choosing map for full conversion, validate for existing JSON/HL7 checks, or parse for structural inspection.
    2. Execution runs the hl7bridge.mjs engine via a Node.js environment, piping the message through stdin or a file path.
    3. Review provides a structured verdict including a resource summary table, a detailed issues list, and the final FHIR Bundle.

    Frameworks & tools

    Built for Node.js 20+ environments. It utilizes a deterministic mapping engine with YAML-based transformation rules and a built-in validator for FHIR R4 and regional Implementation Guides.

    Why this beats prompting it yourself

    Generic LLMs often hallucinate FHIR mappings or invent missing values to satisfy schema requirements, creating dangerous data integrity risks. This skill uses a hard-coded engine that refuses to guess, ensuring that every resource produced is traceable, auditable, and production-ready.

    Use cases

    • Convert lab results (ORU^R01) into FHIR Observation resources for a patient portal.
    • Audit a hospital admission feed to ensure it meets US Core requirements.
    • Debug why a specific segment is causing a FHIR server to reject an incoming Bundle.
    • Localize interface mappings for the Chilean or Colombian healthcare markets.

    Known limitations

    Supports only ADT^A01, ORU^R01, ORM^O01, and OUL^R22 to FHIR R4. Does not handle CDA documents, X12 claims, or FHIR-to-HL7 conversion. Offline validation does not include full terminology binding.

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    1 install

    Downloaded by developers to date

    Free forever

    No account required to browse

    Trust & safety

    Security scanned

    Verified clean 4 days ago

    • Free to download with an account

    Requires

    Node.js 20 or later
    A shell the agent can run commands in (bash, zsh or PowerShell)
    Node.js

    Listed4 days ago

    What's inside

    Frequently Asked Questions