Small Open Models for Healthcare
A lot of healthcare is paperwork, and a good share of the people in a hospital, a practice or a health plan spend their whole day on it, well away from the exam room. Clinicians write notes after every visit, coders turn those notes into billing codes, revenue cycle teams chase prior authorizations and appeal denied claims, front-desk and referral staff get patients registered and scheduled, care teams answer patient messages, and research teams pull data out of the record for studies and registries. AI is showing up in all of these, from ambient scribes in the exam room to tools that draft appeal letters. Most of the work is reading, and a surprising amount of what gets read still arrives on paper.
In this post I’ll start with why that reading is slow, then look at what a few healthcare teams are already doing with open models. Then I’ll go through how I think about a job like this: break it into steps, decide whether it runs as a fixed workflow or an agent, and work out which steps code can do and which need a small model trained for one task. After that come two examples from the SIE cookbook, a faxed referral and a research request for clinical notes, told the same way, and a short section on running them yourself.
Why the Paperwork Is Slow Today
People do almost all of this by reading, page by page, and a lot of the pages still arrive by fax. Yes, it’s 2026. Yes, it’s still fax. When a doctor’s office refers a patient, it usually has the patient’s name, date of birth, insurance and reason for referral as fields in its own EHR. Faxing turns all of that into a dithered, slightly tilted black-and-white image with no text layer, and someone at the other end retypes it. Nothing about that is dramatic, but it adds up. A packet that sits unread in the fax inbox is a patient nobody has scheduled yet, and a callback to ask for a member ID your EHR already had wastes a call and a day.
Research has the same problem in a different shape. When a study looks at what happens to patients, the structured fields in the EHR are easy to pull, but most of the answers are in the clinicians’ notes, and somebody has to read every note to hide the patient’s personal details before the research team can analyze them.
What Other Healthcare Teams Are Doing With Open Models
Most of that work is reading and checking: turning a fax image into text (OCR), finding the fields in it, spotting a relative’s name inside a sentence of a discharge summary, or finding what an appeal needs in a long record. The healthcare teams that have written about jobs like these build on open models, and each one sizes the model to the job:
- Abridge said in June 2026 that it’s building a new model on the NVIDIA Nemotron open model family, trained with de-identified data, so it can deploy “the right model for the right workflow, at the right scale.” The model is still being built.
- R1 wrote in October 2026 about post-training Nemotron 3.5 Super VL 120B for long-context medical reasoning to reduce denials (the first post of a series, with results on synthetic denial-appeal cases).
- Sword Health fine-tuned its MindGuard safety classifiers from Qwen3Guard-Gen at 4 and 8 billion parameters, and Nebius’s customer story says they screen every user message in Sword’s Dawn product.
- Johns Hopkins fine-tuned a 7-billion-parameter LLaMA-architecture model and tested it on 42,160 patients in its own health system, for clinical and operational prediction tasks.
What I like about this list is the spread of sizes. R1 uses a large 120B model because its job is reading a long record and reasoning over it, and Sword uses small 4B and 8B classifiers because its job is screening every single user message for safety, so each one picked a size for its job. Three of them trained their own models and Abridge is training one, while the recipes below run models as shipped with Python around them; I’ve written up when that’s enough separately.
How I Break a Healthcare Job Into Steps
I start with the job as a person does it today and write the steps down in order. When I did this for the referral recipe below, the first thing I noticed was how few of the steps need a model at all. The EHR already knows existing patients and their member IDs, the provider directory knows the referring clinician’s NPI, phone and fax, and the intake checklist is, well, a list. Those are lookups, and code does them. What no system has as data is the fax itself, because faxing turns typed fields back into a picture.
That leaves two things for a model to do in these recipes: turning the fax pages into text (and pointing at the fields in it), and finding the personal details in a clinical note so they can be hidden. Each goes to a small model trained for that one kind of job, and then Python checks what it found against what the EHR (and, for referrals, the provider directory) already holds. A job that needs a long record read and something new written (R1’s denial appeals, say) is where I think a large generative model earns its cost, though neither recipe below needs one. And the clinical and release decisions, like how soon a patient is seen or whether an extract may go to the research team, stay with a person every time.
Then I decide how the steps run. Both examples below run as fixed workflows: Python picks every step and calls a small model where a step needs one, because you can write the steps down before the first page arrives and the same packet should take the same steps every time. Nobody is at the screen asking follow-up questions, and nothing in either job needs a model deciding what to do next. When an agent or a mix of the two does make sense is a question I’ve answered in when to use a workflow and when to use an agent, and the cookbook’s agent recipes show it on KYC checks, counterparty news, contract review and repair invoices.
One thing healthcare adds is where the models run. The model reads the raw fax pages and notes, protected health information included, before any check runs, so I settle that before I pick a model; the healthcare page covers the rules.
Turning a Faxed Referral Into a Draft Referral
As an example, consider a cardiology practice that gets referrals for new patients. Most come from primary-care offices on a different EHR, so many still arrive by fax: a cover sheet, a referral order and the last clinic note, landing in an e-fax inbox as an image-only PDF. A referral coordinator works through that inbox. For each packet they read the order and the note, search the EHR by name and date of birth, match a chart or register a new patient, enter the referral and attach the pages. A clinician decides how soon the patient is seen, and the coordinator phones or faxes the referring office for whatever the intake rules say is missing. The risky parts are small and specific: a form that says “within 72 hours” without the word “urgent” can wait behind routine ones, and a signed clinic note stapled behind an unsigned order looks complete at a glance.
The faxed referrals recipe runs this as a workflow. The tempting shortcut is to hand the whole packet to one big model and ask “is this referral complete?”, but you’d get an answer you can’t audit, and it would ignore the chart you already have. Instead, the searches go to code and only two steps go to small models. LightOnOCR-3-4B reads each page into Markdown and keeps the “Label: value” lines intact. gliner2-large-v1 then points at the fields in that text and writes nothing of its own, so Python can check every value: it has to sit right after its own label, an NPI has to pass its check digit, a phone needs ten digits, the signer has to be on the order page itself, and when the fax leaves a field blank, the recipe only fills it from the EHR if the chart matches exactly. Every packet then goes to the clinical review queue, sorted with urgent and time-bound requests first, and a clinician decides how soon.

Each packet comes out checks_passed, missing_info or review. The recipe ships with synthetic packets, each written to test one way a packet can go wrong, so they show how the checks behave and nothing about how often the recipe is wrong on your faxes. A few show what the recipe does with a packet that has a problem. In one, the order’s signature line is blank and the clinic note behind it is e-signed, so the order goes on the callback list. In another, the fax has no member ID and the chart does, so the draft fills it from the chart and says where it came from instead of calling the office. And the check that a value sits right after its own label threw out a lot. The model offered every clinic note’s e-signature as the signer of the order, and every fax header’s “TO:” number as the patient’s phone. Neither one followed the right label, so Python set them aside. The model was confident; the fax header was not the patient.
In one packet the extractor fell short. The reason for referral reads “New leg swelling, breathless lying flat, BNP 1,240 pg/mL.”, and the model returned nothing for it, because long free text is where it’s weakest. The recipe asks the office for the reason instead, which is a wasted call on exactly the packet where the clinical reviewer wants the reason most. I’d fix it with a few lines of Python that take whatever follows “Reason for referral:” on the page, used only when the model comes back empty.
Pro-tip: with checks like these, trying a smaller model is a one-line change in rules.yaml. I swapped in gliner2-base-v1 and it pointed at more wrong spans, “BNP 1,240 pg/mL” offered as an NPI among them. The label check threw those out, but that only tells you the checks work, not whether the smaller model reads your faxes well enough, so try it on your own before you trust it.
Pseudonymizing Clinical Notes for a Research Request
For a second example, consider a hospital’s quality-improvement team. It wants to know what happens to patients in the weeks after discharge, and the answers are in the clinicians’ notes. The privacy office approves the request, and the honest broker (the person in the middle who sees the real notes and keeps the key that links them to the study’s version) pulls the notes, replaces the identifiers, checks the flagged ones against the originals and hands over an extract; the requester never gets the key. A discharge summary names the patient, sure, but also the daughter who drives her to appointments, the daughter’s phone number and the son-in-law’s employer. All of that has to go, while “readmitted five days after discharge” has to survive, because that’s what the study is about.
The pseudonymization recipe is a workflow for the same reason as the referral example, with the honest broker checking the flagged notes and signing off at the end. Broken into steps, most of it is again a lookup. The EHR knows which patient each note belongs to, along with that patient’s name, aliases, MRN, date of birth, address and phone, so those get replaced by matching against what the EHR holds, with no model. Regex handles the formatted identifiers (MRNs, phones, ZIPs, dates and ages over 89). The model only has to find what’s written in the sentences of a note and nowhere else: the daughter’s name and phone, the son-in-law’s employer, street addresses, the granddaughter’s email. superlinked/pii-redact reads for those. It’s the right tool for names and employers and the wrong one for formatted identifiers (it can tag an ordinary date as a date of birth), so the model only marks what it thinks is personal data, and the rules decide whether each piece gets a placeholder, a shifted date or nothing. Python shifts each patient’s dates by one random offset, and a final sweep runs the regex again over the output for anything that survived.

Because every date for a patient moves by the same offset, “readmitted five days after discharge” still reads as five days. The check I like most has no model in it at all. One lab fax was filed under the wrong patient. Its header carries another patient’s MRN, and the EHR knows that MRN. If the recipe had shifted its dates like the rest of the filed patient’s notes, someone else’s lab result would have landed in the filed patient’s timeline in the study. So Python removes the dates and holds the note out of the extract, using nothing more than a match against the patient list.
Watch what the recipe leaves readable. A bracketed emergency contact kept its initial “W.”, and the recipe can leave initials and first names in a note. It’s one letter, but the honest broker decides whether that’s acceptable, just as which HIPAA de-identification route the extract takes is for the IRB and the privacy office.
Run It Yourself
If you want to see how this feels on a real run, the easiest place to start is SIE Serverless with the synthetic data that ships with the recipes. You need uv and an SIE API key:
git clone https://github.com/superlinked/cookbookcd cookbookcp .env.example .env # then set SIE_API_KEYcd healthcare/process_faxed_referralsuv run recipe.pyEach run writes runs/<timestamp>/ with the draft referrals, callback-list.csv and clinical-review-queue.csv, so you can read what the recipe decided packet by packet. For the research recipe, cd healthcare/pseudonymize_clinical_notes instead. I ran both recipes this way. Serverless sends your inputs to Superlinked, which is fine for synthetic packets and not for real faxes, so when you move to real patient data, point SIE_BASE_URL in .env at an SIE server inside your own network; the code stays the same, and SELF_HOSTING.md has the setup.
Conclusion
Healthcare has plenty of paperwork jobs like these two (the cookbook READMEs name a few more: a faxed prior authorization checked against the scheduled procedure, faxed lab orders, faxed records requests matched to charts, a registry submission and case notes for an outside quality collaborative). You can take any of them apart the same way: write down the steps a person takes, give code every question the EHR and your directories can already answer, give a small model only what no system holds as data (the text on a fax page, a relative’s name in a note), check what it found against the EHR, and decide whether the whole thing runs as a workflow or needs an agent. The decisions about patients stay with the people who make them today.
If you try this on your own paperwork, I’d love to hear which step broke first. My money is on long free-text fields.