Parsing Hl7v2 Messages logo

Parsing Hl7v2 Messages

CommunityPopular
maziyarpanahi
parsing-hl7v2-messages

Decodes pipe-delimited HL7 v2.x messages (ADT, ORU, MDM, ORM) into structured segments/fields/components and surfaces OBX-5 and NTE-3 free-text narrative for OpenMed. Use before OpenMed processing when ingesting HL7 v2 feeds from an interface engine, lab/results system, or ADT stream and you need the embedded clinical note text de-identified and analyzed. Flatten OBX/NTE text then call openmed.deidentify and openmed.analyze_text; segment-aware redaction is available via openmed.interop.hl7v2. Trigger keywords: HL7, HL7 v2, ADT, ORU, OBX, MSH, PID, pipe-delimited, interface engine, Mirth, lab results.

Overview

Publishermaziyarpanahi
Repositoryopenmed
Skill nameparsing-hl7v2-messages
Stars
5.3K
Forks
677
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by maziyarpanahi on GitHub. Read the source before you install it.

Installation

Install the Parsing Hl7v2 Messages AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/maziyarpanahi/openmed.git /tmp/openmed
mkdir -p .claude/skills
cp -r /tmp/openmed/skills/parsing-hl7v2-messages .claude/skills/parsing-hl7v2-messages
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Parsing Hl7v2 Messages in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Parsing Hl7v2 Messages on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Parsing Hl7v2 Messages is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Parsing HL7 v2 Messages for OpenMed

HL7 v2.x is the workhorse of hospital interfacing — ADT (admit/discharge/ transfer), ORU (observation results), MDM (document management), and ORM (orders) messages flow continuously between EHR, lab, radiology, and ancillary systems. The clinical narrative you want for NLP is buried in OBX-5 (observation value) and NTE-3 (notes/comments) fields, wrapped in a pipe-and-caret encoding. This skill decodes that envelope and hands the free text to OpenMed.

When to use

  • You receive HL7 v2 messages from an interface engine (Mirth/NextGen Connect, Rhapsody, Cloverleaf) and want to mine embedded note/result text.
  • A lab feed (ORU^R01) carries impression/comment narrative in OBX/NTE.
  • An MDM^T02 transcription message carries a full report in OBX-5.
  • You need a de-identified, structured feed into openmed.analyze_text.

HL7 v2 structure in one minute

A message is segments separated by \r (carriage return). Each segment is 3-letter-named, then fields split by |, components by ^, repetitions by ~, sub-components by &, with \ as escape. The encoding characters are declared in MSH-1 (the field separator) and MSH-2 (^~\&). Field positions are one-based, and MSH is special: MSH-1 is the separator, so MSH-2 is the first real field.

MSH|^~\&|LAB|HOSP|EHR|HOSP|20240302101500||ORU^R01|MSG0001|P|2.5
PID|1||MRN12345^^^HOSP^MR||DOE^JANE^Q||19700115|F|||1 FAKE ST^^SPRINGFIELD^IL^62704
OBR|1||ORD9|CBC^Complete Blood Count
OBX|1|TX|IMPRESSION||Mild leukocytosis; clinically correlate.||||||F
NTE|1||Patient reports fatigue x1 week. Dr. Smith notified.

Quick start

Parse the envelope and pull narrative from OBX-5 / NTE-3, then hand off:

python
import openmed
from openmed.interop.hl7v2 import parse_hl7v2

raw = open("results.hl7", encoding="utf-8").read()
msg = parse_hl7v2(raw)               # -> HL7Message (segments preserved)

narrative_chunks = []
for seg in msg.segments:
    if seg.name == "OBX":
        # OBX-2 is the value type; OBX-5 is the observation value.
        value_type = seg.get_field(2)
        if value_type in {"TX", "FT", "CE", "ST"}:
            narrative_chunks.append(seg.get_field(5) or "")
    elif seg.name == "NTE":
        narrative_chunks.append(seg.get_field(3) or "")

# Decode component delimiters into plain text before NLP.
flat = "\n".join(c.replace("^", " ").replace("&", " ") for c in narrative_chunks if c)

# Hand the narrative to OpenMed.
deid = openmed.deidentify(flat, method="replace", policy="hipaa_safe_harbor")
result = openmed.analyze_text(deid.text, output_format="dict")

HL7Segment.get_field(position) uses one-based HL7 positions and returns None for absent fields. HL7Message.segment_names() lists segments in order.

Whole-message segment-aware de-identification

When you need to redact the entire message (structured PID/NK1/GT1 fields and OBX/NTE free text) while preserving HL7 framing, use the bundled redactor instead of hand-rolling it:

python
from openmed.interop.hl7v2 import redact_hl7v2

safe = redact_hl7v2("results.hl7")   # path or message text
# PID-3 hashed, PID-5 name surrogated, PID-7 DOB date-shifted, OBX-5/NTE-3
# free text masked via openmed.deidentify — delimiters and segment order kept.

redact_hl7v2 applies DEFAULT_FIELD_MAP (PID, PD1, NK1, GT1, IN1/IN2, OBX, NTE). Extend or override it with field_map={("ZPS", 4): {"action": "hash"}} for site-specific Z-segments, and pass date_shift_days= for a fixed, interval-preserving shift.

Workflow

  1. Frame-split safely. Real feeds use \r, \r\n, or MLLP framing (\x0b\x1c\r). parse_hl7v2 auto-detects the segment separator; strip MLLP control bytes before parsing.
  2. Read encoding from MSH — never assume |^~\&. The adapter derives the delimiter set from MSH-1/MSH-2 (HL7V2Encoding.from_msh_segment).
  3. Locate narrative. OBX-5 (gated by OBX-2 value type), NTE-3, and report-bearing segments. Concatenate repetitions (~) and components (^).
  4. De-identify, then analyze with OpenMed.
  5. Rejoin results to the patient/encounter via PID-3 (patient id) and PV1-19 (visit number) — but redact those identifiers in anything you persist.

Hand-off to / from OpenMed

  • To OpenMed: flattened OBX-5/NTE-3 text → openmed.deidentifyopenmed.analyze_text.
  • Adapter: openmed.interop.hl7v2 provides parse_hl7v2, redact_hl7v2, HL7Message, HL7Segment, HL7V2Encoding, HL7FieldRule, and DEFAULT_FIELD_MAP for segment-aware de-id that preserves message framing. It is parse-and-redact only — not a conformance validator.
  • Re-link by id, not by PHI: carry PID-3/PV1-19 as keys, but store hashed or surrogate values (the default redact_hl7v2 hashes PID-3).

Edge cases & gotchas

  • MLLP wrapper. Messages off a TCP MLLP listener are framed with \x0b (start) and \x1c\r (end). Strip these before parse_hl7v2.
  • Escape sequences. \F\, \S\, \T\, \R\, \E\ encode literal delimiters, and \.br\ is a line break inside OBX text. Unescape before NLP.
  • Repeating OBX. A single result can span many OBX segments (one line each); reassemble in order before summarizing.
  • Value types matter. Only treat OBX-5 as narrative when OBX-2 is a text type (TX, FT, ST, CE); numeric (NM) and coded-only values are not free text. The default redactor restricts free-text redaction to FT/TX.
  • Z-segments. Site-defined Z* segments often carry extra PHI; add explicit field_map rules — they are not in the default map.
  • Versions vary. v2.3 through v2.8 differ in field cardinality; resolve positions against MSH-12 (version id), don't hardcode across versions.

Standards & references

Frequently asked questions

What does the Parsing Hl7v2 Messages AI skill do?

Decodes pipe-delimited HL7 v2.x messages (ADT, ORU, MDM, ORM) into structured segments/fields/components and surfaces OBX-5 and NTE-3 free-text narrative for OpenMed. Use before OpenMed processing when ingesting HL7 v2 feeds from an interface engine, lab/results system, or ADT stream and you need the embedded clinical note text de-identified and analyzed. Flatten OBX/NTE text then call openmed.deidentify and openmed.analyze_text; segment-aware redaction is available via openmed.interop.hl7v2. Trigger keywords: HL7, HL7 v2, ADT, ORU, OBX, MSH, PID, pipe-delimited, interface engine, Mirth, la...

Why use Parsing Hl7v2 Messages on TypingMind?

Because you install it once and use it with any model. Parsing Hl7v2 Messages is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Parsing Hl7v2 Messages in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/maziyarpanahi/openmed/tree/master/skills/parsing-hl7v2-messages. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Parsing Hl7v2 Messages?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Parsing Hl7v2 Messages?

As many as you like. As long as a model supports skills, you can use Parsing Hl7v2 Messages with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Parsing Hl7v2 Messages AI skill free?

Yes. It is published on GitHub by maziyarpanahi under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇