If you work in healthcare operations, you already know the fax machine should be dead. It isn't. And the reason it isn't has nothing to do with whether the technology exists to replace it. It has everything to do with the fragmented mess of systems that surround it.

I'll take you through how I deployed a purely agentic workflow that handled the entire fax process every morning. No humans were involved nor hurt in the making of this process. Failures are caught and retried without anyone having to know it happened. Before we hop into technical architecture, I’ll walk you through what contributed to the lack of efficiency in the first place.

The "There's an App for That" Era Left Healthcare a Mess

Somewhere between the mid-2000s and the early 2010s, every business function in healthcare got its own SaaS solution. There was software for scheduling, storing healthcare records, apps for invoices…the list goes on and on. And, the pitch was always the same: buy this tool, solve this problem and move on with your life.

No one really took the time to answer this question: how do all of these systems talk to each other?

Unsurprisingly, in most healthcare organizations, they simply don't. Or they do, but the way they converse is via a person, couriering data from one system to another. A staff member downloads a report from one system, reformats it in Excel to match what another system needs, pastes it in, and sends a fax from a third. If something goes wrong, they find out days later and start over. The technology budget went to buying point solutions. Integration was an afterthought, if it was budgeted at all.

What you end up with is not a technology ecosystem. It's a pile of disconnected tools with people manually bridging the gaps between them. In healthcare specifically, those gaps have consequences that go beyond operational inefficiency. Delays in referrals, prior authorizations, and prescription confirmations hold up patient care. The person sending the faxes often doesn't see that downstream impact directly. It looks like paperwork from where they're sitting. It isn't.

That's the environment this flow was built for. The goal wasn't to save a few minutes per day. It was to remove the human from a process that never should have required one in the first place.

The Framework I Use: PTAO

Before getting into the build, I want to walk through the framework I use to design every agentic flow. I call it PTAO: People, Triggers, Actions, Outcomes.

Most automation content leads with the technology. That's the wrong starting point. If you build around the tools first, you'll end up with something technically impressive that doesn't actually fit how the people in the process work. Nobody adopts it. Nothing changes.

PTAO starts with the humans and works outward from there.

People are everyone affected by the process, not just whoever is clicking the button. In healthcare automation, this almost always includes clinical staff who never interact with the system at all but absorb every delay it creates.

Triggers are what the system is listening for. It could be a timestamp or a case record created in a CRM. A rejection message landing in a service inbox. The trigger is what starts everything.

Actions are what happens when the trigger fires. RPA bots, Python scripts, cloud flows, API calls. This is the technical layer, and it only makes sense relative to what triggered it and what outcome it's supposed to produce.

Outcomes are the actual goal, not the output. The output is a PDF sent via email to a fax gateway. The outcome is a clinician getting the confirmation they need to move forward with a patient's treatment. Those are not the same thing, and keeping that distinction clear is what keeps the build grounded.

People: Who This Flow Is Actually For

The staff who were manually running this process had a workflow that went like this: pull data out of a legacy system, reformat it in Excel to match the fax template, run a mail merge, send the fax, and then circle back days later to check whether it went through. If it failed, they would refax it manually. Each attempt ran 10 to 13 minutes on average. Across a week, this was eating 2 to 3 hours per person. One person on a good day could get through about 60 faxes.

The volume this flow needed to handle was 650 per day.

On the other side of those faxes are the clinicians waiting on them. Physicians checking whether a referral cleared or pharmacists waiting on a prior auth. The confirmation they need to proceed with treatment is sitting in that fax queue. Every hour it takes to get there is an hour the patient waits.

The design goal was straightforward: staff shouldn't have to think about faxes at all. Clinicians should get confirmations faster than they did before. Neither group should have to learn a new system or change how they work. The friction gets removed on the back end where they can't see it.

Triggers: What the System Listens For

This flow runs on two separate triggers.

The first is time-based. Every morning at 5:00 AM, an RPA bot wakes up on a Windows server and starts pulling data. No one kicks it off. No one has to remember.

The second trigger handles failures. A Power Automate cloud flow watches a service account inbox around the clock. When a fax fails, the eFax gateway sends a rejection message back to that inbox. Something like: "Message to 555-867-5309 failed." That email is the trigger for the retry logic.

There are two triggers that run the same number of jobs. One is dedicated to starting the work, while the other's sole purpose is to fix what breaks in the first one.

Actions: How the Flow Works

Step 1: RPA Extraction at 5:00 AM

The source system has no API. This is not unusual in healthcare. A lot of the platforms running clinical operations were built in the 90s and early 2000s and were never designed to integrate with anything. Getting data out of them means doing what a human would do: open a browser, log in, run a report, download the file.

That's what the RPA bot does. Power Automate Desktop running on a Windows server boots a browser at 5:00 AM and pulls the data. Same steps a human would take, just automated and finished before anyone's at their desk.

Step 2: Python Normalization

The data coming out of the legacy system is unstructured. Field names are inconsistent. Values that need to be separate are concatenated. Date formats are wrong. You can't load it directly into Dynamics 365.

A Python script picks up the downloaded file and normalizes it: cleans field names, splits concatenated values, reformats dates, maps everything to the D365 case schema. This step is what makes the rest of the flow possible. Skip it and you're just moving bad data from one place to another.

Step 3: Loading Into Dynamics 365

The normalized data loads into D365 as case records. Each fax that needs to go out becomes a case. D365 is the hub from this point forward.

Step 4: Power Automate Cloud Flow

A cloud flow is waiting for cases to land. Once they do, it pulls all cases created that day, loops through them, and for each one stores the relevant data in variables: recipient name, fax number, clinical content.

Then it grabs a Word template from SharePoint via Microsoft Word Business Online, populates it with the case data, and saves it as a PDF. The PDF requirement comes from the eFax gateway. The email-to-fax integration expects a PDF attachment, so the Word-to-PDF conversion is not optional. It is not the most elegant step in the flow, but it is reliable.

The flow attaches the PDF to an email addressed to the recipient's fax number at the gateway domain and sends it. If that succeeds, the case in D365 gets marked as Sent and a follow-up task is created automatically.

Step 5: Error Handling

This is the part most automation writeups leave out. It's also the part that determines whether something actually works in production.

When a fax fails, the gateway sends a rejection email to the service account inbox. The cloud flow monitoring that inbox parses out the fax number from the message, queries D365 for any cases with that number created today that haven't been confirmed as sent, and queues them for a retry. The system will try up to four times. After that, an alert goes to the admin so a human can check whether the fax number is correct.

Nothing drops silently. Every failure has a paper trail in D365 and a defined path to resolution.

Outcome: What Changed

650 faxes go out automatically every morning. Staff don't touch the process. Clinicians get confirmations faster. Failures get caught and retried without anyone having to notice.

The staff hours that were going into downloading, reformatting, merging, sending, and following up are now available for work that actually needs a person. That's the outcome. Not the architecture. Not the tool count.

Automation, Even When Systems Are Old and Messy, Is Possible

This flow connected an API-less legacy system, a Windows RPA bot, a Python normalization script, Dynamics 365, Power Automate Desktop, Power Automate cloud flows, Microsoft Word Online, and an eFax gateway. When these things were implemented individually, not much thought was given to how they'd interact with one another, and that's exactly the point.

The "there's an app for that" era sold healthcare organizations on point solutions and left the integration problem for someone else to figure out. In a lot of organizations, that someone else turned out to be a staff member with an Excel spreadsheet, large doses of caffeine and angst, and a fax machine. The systems causing the most pain right now, the ones with no API and no obvious path to modernization, are exactly where this approach does its best work. You don't have to wait for a vendor to build you an integration. You simply build it yourself, around what already exists. Of course, this process isn't perfect, and anyone working in with agents will tell you that UI based automations are the most brittle flows around. But, if you have a choice between that and relying on a human to remember to do this correctly, choose the bot, everytime.