Early Access · beta. We're building toward 1.0 — and we want people involved now, while it can still be shaped. Where the project stands →

Developer guide

Build an HL7 interface in Python

An interface in MessageFoundry is four small pieces of plain Python: a Connection in, a Router to decide where messages go, a Handler to transform and send them, and a Connection out. Here's the whole thing — build it, validate it, and test it before it goes live.

The four building blocks

  • Connection — an endpoint that receives (inbound) or sends (outbound) messages over a transport like MLLP, files, HTTP, or a database.
  • Router — a function that looks at a message and returns the names of the Handlers that should process it.
  • Handler — a function that transforms a message and sends it to an outbound Connection (or filters it).
  • Message — the parsed HL7, addressed by path: msg["MSH-9.1"], msg["PID-3"], and so on.

1. Install and create a config directory

Install the engine from PyPI; your interfaces live as Python modules in a config directory you own.

terminal
pip install messagefoundry
mkdir config

2. Declare your Connections

Name an inbound Connection to receive messages and an outbound Connection to send them. Point the inbound at a Router.

config/adt_feed.py
from messagefoundry import MLLP, Send, inbound, outbound, router, handler

inbound("IB_ADT", MLLP(port=2575), router="adt_router")
outbound("OB_EHR", MLLP(host="10.0.0.21", port=6661))

3. Write a Router and a Handler

The Router decides routing; the Handler does the work. Address HL7 fields by path; return an empty list to leave a message unrouted, or None from a Handler to filter it.

config/adt_feed.py
@router("adt_router")
def route(msg):
    if msg["MSH-9.1"] != "ADT":
        return []                    # UNROUTED — not an admit/discharge/transfer
    return ["to_ehr"]

@handler("to_ehr")
def to_ehr(msg):
    return Send("OB_EHR", msg)

4. Validate the interface

Run the commit gate. It checks that every Connection, Router, and Handler is wired correctly before anything ships — the same gate you'd put in CI.

terminal
python -m messagefoundry check --config config

5. Test it, then run it

Run the engine and send a sample message. Every message reaches a recorded disposition — routed, filtered, or unrouted — so nothing is ever silently dropped. Because routers and handlers are plain Python, you can also unit-test them like any function.

terminal
python -m messagefoundry serve --config config --db messagefoundry.db
# in another shell — send a sample ADT to the MLLP port
python samples/send_mllp.py samples/messages/adt_a01.hl7

That's a complete interface. Receive, route, transform, send — version-controlled, validated, and testable. Add more interfaces by adding more modules; one config repo can drive Test, Production, and more.

FAQ

Frequently asked questions

How do I build an HL7 interface?

In MessageFoundry you build an HL7 interface from four blocks: a Connection (inbound and outbound), a Router that decides where each message goes, and a Handler that transforms and sends it. You write them as plain Python in a config module, validate with the commit gate, then run the engine.

Do I have to write code, or can I use a GUI?

Either. The VS Code extension and admin console offer guided wizards for Connections and routes, or you can write them directly in Python for full control. Both produce the same version-controlled config.

How do I test an HL7 interface before production?

Validate the config with the commit gate (python -m messagefoundry check), then send sample messages and watch each message reach a recorded disposition — routed, filtered, or unrouted. Because interfaces are plain Python, you can also unit-test routers and handlers like any code.