Inspiration
Anyone who has sat in an emergency department knows the feeling: hours pass, staff move purposefully around you, and you have no idea whether you are next or forgotten.
What struck us is that the hospital is not withholding anything. The information already exists. A clinician placed the order, the sample reached the lab, the scan finished but the report has not been read yet. Every one of those facts is recorded in the EHR the moment it happens. It just never reaches the one person whose day is organized entirely around it.
So we did not set out to build a new source of truth. We set out to project one that already exists.
What it does
CarePath turns recorded healthcare events into a live patient journey: what is happening now, why a step is waiting, what the patient needs to do next, and who is helping.
- Hospital EHR view. A presenter-facing interface where clinical actions write real FHIR resources to hosted Medplum. Recorded Activity reveals only milestones that were actually completed, activated, or ordered — untouched future steps stay hidden.
- Patient journey. A timeline that updates over Server-Sent Events without a refresh, with dependency-based explanations for every wait.
- Ask CarePath. Conversational explanations grounded in the current journey, with validation, an independent review pass, and a deterministic fallback.
- CarePath Network. Real ANS discovery, identity verification, and consultation submission to a remote specialist agent, where a human acknowledges and responds through a deployed HTTPS inbox.
- Post-discharge guidance. After the real discharge event, a mobile guide generated strictly from the saved discharge-instructions
Communication, alongside a recap of confirmed milestones and an interactive 3D body-region view.
One rule governs the whole system:
FHIR owns facts. The Journey Engine owns workflow. AI explains recorded information.
How we built it
The heart of the project is a deterministic Journey Engine that projects FHIR evidence into workflow state. It preserves distinctions that a naive status tracker collapses: an order is not work in progress, a completed scan is not an available report, a submitted consultation is not an acknowledged one, and a cancellation never satisfies a dependency.
The event path is deliberately unglamorous:
Hospital action
→ version-checked FHIR transaction (hosted Medplum)
→ authenticated resource webhook
→ durable PostgreSQL inbox (persisted and deduplicated)
→ worker rereads authoritative FHIR state
→ committed graph and revisioned snapshot
→ SSE journey.updated → patient browser
The patient UI never advances optimistically from a staff click. A delayed event triggers a reread of current FHIR state rather than a replay of stale state, and reconciliation is recorded separately from webhook delivery so the two can be told apart when something goes wrong.
Specialist coordination runs over a Go ANS SDK bridge behind a Python adapter. The adapter discovers the specialist endpoint through ANS rather than a hardcoded URL, fails closed on any verification error, and transmits consultation context only after identity holds. The specialist inbox is genuinely deployed over HTTPS on its own host, reached through an authenticated handoff using a short-lived, single-use ticket, so no credentials ever leave the server.
The stack itself is intentionally boring: FastAPI, SQLAlchemy and Alembic behind Next.js and TypeScript, with PostgreSQL for durable state.
Challenges we ran into
Deciding what the AI is allowed to touch. The tempting version of this project has a model narrating the patient's care. We rejected that early. The explanation layer can read recorded state and phrase it, but it cannot write a clinical fact, order anything, or advance the journey. Discharge guidance must be grounded in the saved source, and unsupported sections are omitted rather than filled in. Enforcing that boundary in code, instead of trusting a prompt, was the most consequential design work we did.
Real webhooks are not a straight line. Events arrive late, twice, or out of order. Getting to a durable inbox with deduplication, optimistic concurrency on FHIR updates, and a worker that rereads authoritative state — rather than trusting the payload in hand — took more iterations than the feature list suggests.
Making agent-to-agent coordination honest. It would have been easy to fake the specialist. Instead we deployed a real remote agent, ran production ANS discovery and verification against it, and put a human in the loop for acknowledgement and response. That meant TLS, Nginx path routing, agent metadata, and a credential handoff that survives being demoed in public.
Two sessions, one truth. Keeping an already-open patient tab correct through the discharge transition — including persistence, so a refresh returns the saved guide rather than regenerating it — surfaced most of our remaining state bugs.
Accomplishments that we're proud of
The full flow passes manual end-to-end testing, captured at checkpoint 0d82829. Hospital actions write real FHIR transactions; real webhooks drive a real worker; an already-open patient page updates over SSE; a real remote specialist is discovered, verified, and responded to by a human; and the discharge guide is generated from the hosted FHIR Communication and then persisted. The checkpoint passed 7 focused backend tests, 15 frontend tests, a frontend typecheck, and both production builds.
We are equally proud of what we refused to claim. The demo runs on a hybrid deployment, the patient data is synthetic, ANS verification proves which service we are talking to and not that it is clinically qualified, and the 3D viewer shows an adult reference surface rather than a patient-specific scan. None of that is hidden in a footnote.
What we learned
Most of the hard problems in patient-facing healthcare software are not modelling problems — they are provenance problems. Knowing that a scan finished is easy. Knowing whether the thing you are showing a frightened person is confirmed, inferred, or merely scheduled is the entire job.
We also learned how much discipline it takes to keep a language model in an explanatory role when it would happily do more, and how much clearer a system becomes once the boundary is drawn in the architecture rather than the copy.
What's next for CarePath
- Publicly hosting the full patient application, not just the specialist inbox and agent endpoints
- Worker and inbox coordination so more than one API process can serve the same journey
- Broadening the scenario beyond Maya, including cancellations, re-orders, and multi-encounter journeys
- A clinician-side review path for generated explanations before any pilot involving real patients
Built With
- ans
- fastapi
- fhir
- gemini
- medplum
- next.js
- postgresql
- python
- typescript
Log in or sign up for Devpost to join the conversation.