What we learned building healthcare integrations for the past year
Source: Dev.to
Introduction
Over the past year we’ve been building integrations with EHRs and payor portals that don’t expose real APIs. It’s been a pain, so we thought it would be helpful to share what we’ve learned and hear from others about what’s worked well—or hasn’t.
Why Healthcare Integration Is Hard
- Fragmented data – The accessible APIs are missing large amounts of functionality or simply don’t exist.
- Limited FHIR endpoints – They often lack the data you actually need and provide no write‑back capability.
- Costly vendor routes – Going directly through EHR vendors is expensive and slow.
- Payor portals – Most have no APIs at all; those that do are heavily limited.
- Third‑party APIs – Coverage gaps are common.
Because of these constraints, many healthcare startups, including us, turned to browser automation.
Starting with Fully Agentic Browser Agents
We began with AI‑driven browser agents because they required the lowest implementation lift and seemed robust. However:
- The EHR workflows were non‑intuitive and required many clicks.
- Agents struggled to perform the workflows correctly.
- They were slow and expensive, needing an LLM call for each action.
- Granting an agent full autonomy to click anything raised safety concerns.
Switching to Stagehand
Stagehand offered a mix of determinism and AI to catch errors. Unfortunately:
- It relied on the accessibility tree, which didn’t always map to the correct actions/selectors on the EHRs.
- It consistently failed on complex DOMs (e.g., Athena).
- The errors we encountered weren’t the types Stagehand was designed to handle.
Moving to Playwright
We identified three common error buckets when running automations:
- Nondeterministic pop‑ups
- Slow rendering elements
- Edge cases with internal logic (e.g., duplicate patients with no clear identifier)
Improvements
- Built a lightweight pop‑up detector and smarter wait/reload logic.
- Handled edge cases manually to avoid unintended LLM decisions (e.g., linking the correct referral between duplicate patients).
Using Network Requests Where Possible
For reliability, speed, and maintainability we rebuilt some integrations as direct API/network calls. Benefits:
- Faster and more reliable than browser agents or Playwright scripts.
- However, some sites have security measures that detect bots and block them, making this approach unsuitable for those cases.
The Bigger Shift: Build‑Time AI vs. Runtime AI
The most important mental‑model change was moving from runtime AI (agents making decisions during live Playwright execution) to build‑time AI:
- Claude Code generates and iterates on Playwright scripts, fixing errors before they run.
- Engineers retain full visibility and control over the code.
- We stay in the loop for any edge case, deciding the proper handling rather than letting an LLM act autonomously.
Our Current Stack
Script Creation
- Local development with Playwright + Claude Code.
- Record workflows, add comments, run the flow, and let Claude inspect logs and network requests to refine the automation.
Robustness
- Specific cases use AI fallbacks, such as a pop‑up detector that captures a screenshot, determines X/Y coordinates, closes the pop‑up, and retries the intended logic.
Infrastructure
- Previously self‑hosted on GCP Cloud Run jobs, capturing screenshots and structured error logs on failure for easy debugging.
- Recently migrated to hosted platforms like Kernel and Browserbase, though this has introduced more flakiness.