Case study · Healthcare · 2025–2026
An offline automation ecosystem for a US diagnostics provider
MedStar Diagnostics is a mobile diagnostic testing provider serving physicians across the New York tri-state area. My role sits between field testing and billing. In six months I replaced the manual back office with a system that runs it.
- 12+Workflows automated
- 60–75%Processing time cut
- 100%Offline, no cloud calls
- 6Months to company standard
Context
Every day, technicians run diagnostic exams in physicians' offices. Each exam produces raw machine output that has to become a clean clinical report, be scored, be checked against the right billing rules for that specific client, be invoiced, be delivered to the physician, and be tracked until it's paid. Across every patient seen, every day.
When I arrived, that entire chain was manual. Paper logs. A Word document used as a billing cheat sheet. Report formatting done by hand, one document at a time — the single most time-consuming task in the company. Clinical scores looked up in a printed chart and typed back into the report. Billing reconciliation done by cross-referencing two systems by eye.
Nobody had asked me to fix it. I was hired to run the process, not rebuild it.
I didn't start with a plan to build a system — I started by doing the work myself, by hand, to understand it. When the tedium became real, I brought in Claude: one session, one set of copy-pasted instructions per task. Claude Skills replaced the copy-pasting. Claude Projects let me centralize the rules and instructions across sessions. Then I hit a different kind of wall — token consumption. I was paying for my own subscription, and waiting on resets wasn't how I wanted to run a live operation. That's the point where I stopped building inside Claude and used Claude Code to write a standalone Python application — one that needed no API calls and no tokens to run at all. Everything from there followed the same rule: build the smallest working version, run it on real data, watch what breaks, fix it, repeat.
The constraints
Three constraints shaped every decision, and they're the reason the obvious approach wouldn't work.
- Patient data cannot leave the machine. This is clinical data. Sending it to a cloud API for processing was never an option — not as a preference, as a hard requirement. The finished system makes zero external calls at runtime.
- Clinical judgment cannot be automated away. A physician's interpretation is a physician's interpretation. Anything the system suggests has to stop and wait for a human before it becomes final.
- It had to run on the machine that already existed. No server, no infrastructure budget, no IT department. A Windows desktop and whatever I could deploy onto it.
What I built
A single desktop application containing eight lettered pipelines plus an orchestrating agent, covering four stages of the operation:
Intake and billing
Daily technician logs are read automatically into a patient tracker. A rules engine then applies client-specific billing logic — routing, invoicing, which documents get attached to which email — by reading a single source-of-truth spreadsheet. Nothing is hardcoded. When a client's billing terms change, the operations team edits one cell; nobody edits code.
Clinical processing
Raw machine drafts are formatted to clinical standard automatically — fonts, spacing, page borders, margins, and page breaks placed so patient information always stays on page one. Nerve-conduction scores are extracted from the report tables, averaged, looked up against the scoring chart, and written back into the document with a severity classification. A separate pipeline reads the diagnostic machine's raw binary output directly and produces a finished report — including rendered waveforms — bypassing the vendor's own reporting screen entirely.
Reconciliation
A single run reconciles the biweekly billing export against the tracker, flags discrepancies, and classifies every patient into the correct payment-status folder — paid in full, awaiting secondary, needs review, unpaid. This replaced a three-step manual cross-check between two systems.
Delivery
Client email drafts are generated with the right recipients, subject, body and attachments pulled from the rules engine. Certification paperwork — neurology order forms and consult forms — is generated from the formatted exam data, with diagnostic and procedure codes selected automatically based on which study the report contains.
The agent
On top of the pipelines sits an unattended processing mode. Point it at a folder of reports and it runs assess → format → score → interpret across the batch, carrying a confidence level for each phase, retrying what it can and stopping hard on what it can't. Then it stops — at a human approval gate — before anything is finalized. The reviewer can approve, reject, or modify and re-run.
The gate is the point. It would have been easy to build something that ran end to end with no interruption and looked more impressive in a demo. It would also have been unusable, because the thing being automated is a clinical document that a physician signs. The system does the repetition. The expert still decides.
Results
- 60–75% reduction in processing time, with the gain increasing as patient volume rises — the manual process scaled linearly, the system doesn't.
- 12+ previously manual workflows replaced, from intake through to payment tracking.
- Adopted as company operational standard, having started as a personal initiative with no mandate and no budget.
- Zero cloud dependency. Patient data never leaves the machine.
- A ~16,000-line codebase with a 46-section user manual and an operations handbook, so it can be maintained by someone who isn't me.
Six months after starting, I brought the efficiency data and a capacity-avoidance argument to the owner and asked for a compensation increase. He agreed to the full amount without a counter. I mention it because it's the cleanest evidence I have that the work was valued by the person paying for it — not just by me.
What I'd do differently
- I wrote to the input folders before I understood why that was wrong. Processing files in place produced a whole class of bugs — duplicated content on re-runs, originals silently altered. The fix was a hard rule: inputs are read-only, every output is written to a mirrored output tree. I should have started there. Now I treat "never mutate the source" as a default, not a lesson.
- I built an API-based triage feature and removed it the same day. It worked. It also meant patient data would touch an external service, which contradicted the constraint I'd set myself. Reverting it was correct, but I should have caught it in design rather than after it was written.
- I under-invested in de-identification early on. Real patient identifiers ended up in test fixtures and log output before I did a proper scrub pass. The system now identifies rows by number and office rather than by name, and never stores patient rows at all — but that should have been the design from commit one, not a remediation.
- I'd get a second reviewer sooner. Building alone for six months meant some decisions went unchallenged longer than they should have.
Stack
Python · Tkinter · openpyxl · python-docx · pypdf · reportlab · Pillow · matplotlib · PyInstaller · Claude AI (development, not runtime) · Excel · Power Query
Client and patient details are omitted throughout. No code, screenshots or repository access are published — this system processes protected health information and remains the property of the company.