Building an Evidence-Based Clinical AI Workflow with LangGraph and FHIR
Technology Blogs

Building an Evidence-Based Clinical AI Workflow with LangGraph and FHIR

Sanket Nawghare
Full Stack Developer

A clinical question can involve several sources of information. A patient’s allergy history comes from the patient record. A question about a guideline recommendation depends on published evidence. A request to change medication needs additional scrutiny before the application produces an answer.

For the developer, each of these questions creates a different execution path. The application needs to retrieve the right context, decide whether the available evidence is sufficient, control what reaches the language model, and preserve enough state to explain the outcome.

This article follows that flow through the AI Clinical Workflow Engine, a prototype built with FastAPI, LangGraph, HAPI FHIR, Weaviate, and React. It uses synthetic patient data and a small reviewed guideline corpus for educational demonstrations. It is not intended for real clinical decisions.

The Workflow the Application Needs to Support

The user selects a synthetic patient, enters a question, and follows the application’s progress toward an answer or a review decision. Behind that interaction, several components have specific responsibilities:

  • HAPI FHIR provides access to the synthetic patient records.
  • The patient-summary service normalizes those records for the workflow.
  • Weaviate stores the guideline chunks and vectors used during retrieval.
  • LangGraph coordinates the steps and routes their outcomes.
  • A response provider produces a draft when the evidence and safety checks allow it.
  • SQLite stores workflow snapshots and review state.

The frontend brings these results together. It shows the answer, supporting evidence, execution path, and any reason the workflow stopped.

The engineering task is to keep those responsibilities explicit. A successful retrieval does not automatically authorize generation, and a generated draft still needs validation before it becomes a final response.

How the Components Fit Together

The React application communicates with FastAPI. The API creates a workflow run, supplies its dependencies, and returns either a final JSON snapshot or a stream of execution events.

Clinical workflow architecture connecting React, FastAPI, LangGraph, patient retrieval, guideline retrieval, response generation, and workflow persistence.
Fig 1: Clinical workflow architecture connecting React, FastAPI, LangGraph, patient retrieval, guideline retrieval, response generation, and workflow persistence.

The backend coordinates the workflow while each adapter controls access to its own data source.

Patient records and guideline evidence remain in separate systems. HAPI FHIR owns the clinical records and uses PostgreSQL for persistence. The application reads through HAPI’s FHIR API instead of accessing its database tables. Weaviate holds the reviewed guideline index. SQLite stores the application’s run history, transitions, and review information.

Within the backend, the graph works with application-defined contracts. FHIR resources, vector-store responses, and provider output are handled by their adapters before they enter workflow state. This gives each integration a clear place to validate data and translate errors.

The graph also receives its dependencies through a run-scoped runtime object. Tests can supply a predictable clock, synthetic patient summaries, and a fake response generator while exercising the same routing used by the application.

Following a Request into the Graph

Execution starts when the frontend submits a patient ID and question to POST /api/v1/workflows. The backend validates the request, creates the run, and saves its initial queued snapshot.

LangGraph then begins execution, classifies the question, and retrieves the patient summary for supported requests. Unsupported intent is rejected. Failures during retrieval become explicit workflow outcomes with stable error codes.

From this point, the question determines which path the graph follows. The current implementation supports a direct allergy-summary route and a separate route for guideline-backed answers.

Workflow branches showing a direct allergy summary and a longer guideline retrieval and generation path, with review and failure outcomes.
Fig 2: Workflow branches showing a direct allergy summary and a longer guideline retrieval and generation path, with review and failure outcomes.

The two paths share patient retrieval, then perform the work required for that question.

These branches make the application’s behavior visible. A completed allergy summary ends earlier than a generated guideline answer because it has fewer steps to perform.

Reading Patient Context Without Sending the Whole Record

The patient-summary service reads approved FHIR resource categories and produces a normalized representation. Those categories include allergies, conditions, medications, observations, encounters, procedures, and diagnostic reports.

The workflow uses this context for routing, safety checks, and, where appropriate, generation. It does not pass the raw FHIR response directly to the language model.

For a question such as “What is the allergy history of this patient?”, the application can answer from the normalized allergy records. After the safety pre-check passes, it formats those records and attaches a citation to the local patient-summary evidence page. This path does not call Weaviate or a response model.

Only allergies currently have this dedicated response behavior. Although the summary service retrieves other categories, a standalone medication or observation question still needs a supported route and response implementation. Data availability and answer support are separate development tasks.

Bringing Guideline Evidence into the Run

A question about a guideline recommendation follows the retrieval path. The current corpus contains two WHO documents covering adult hypertension and type 2 diabetes.

Before indexing, acquisition tooling verifies the downloaded PDFs against committed provenance and checksums. The parser extracts bounded chunks that stay within individual pages, allowing retrieved evidence to retain a traceable source location.

The local embedding implementation uses deterministic token hashing to create 128-dimensional vectors. This makes ingestion repeatable without an external embedding service. It also means retrieval depends on token overlap rather than the capabilities of a learned semantic embedding model. A change in question wording can therefore affect which passages are found.

The retrieval policy checks source eligibility and relevance before assessing the evidence. Sufficient evidence allows the run to reach the safety pre-check. Insufficient or conflicting evidence sends it to review. A dependency failure stops execution with a failed status.

This assessment is part of the workflow contract. When retrieval cannot support an answer, the application does not continue by asking the model to fill the gap from memory.

Building clinical AI on your own EHR data? Let's talk about your workflow.

Controlling the Generation Request

Generation begins only after evidence retrieval and the pre-generation safety check permit it. The application then builds a bounded request containing the question, selected patient facts, and retrieved evidence excerpts.

The context builder selects at most 12 patient facts and includes at most eight evidence items. Patient IDs, display names, and raw FHIR payloads are excluded from the patient-context structure. Guideline-only questions can omit unrelated patient facts entirely.

The builder also rejects truncated patient context and questions containing the known patient ID or display name. These restrictions support the synthetic demonstration; they do not constitute a general solution for deidentifying real patient information.

Generation boundary showing selected context entering a provider and application owned validation, safety checks, and citations applied to its answer draft
Fig 3: Generation boundary showing selected context entering a provider and application owned validation, safety checks, and citations applied to its answer draft

The provider supplies an answer draft. The application controls evidence identity and final response assembly.

The response interface supports a deterministic fake provider, OpenAI, Anthropic, and Ollama. Each adapter fits into the same workflow contract, allowing provider behavior to change without moving routing decisions into the prompt.

The application validates the returned draft and rejects malformed, oversized, or unexpected output. It attaches the citations already selected during retrieval rather than accepting a replacement citation list from the model.

This preserves citation identity, but answer quality remains a separate concern. A valid response structure and an approved source list do not prove that every sentence is supported by the retrieved text.

Deciding When an Answer Needs Review

Safety checks run at two points. Before generation, deterministic rules examine the request and normalized patient context. After generation, another check examines the draft.

The pre-check covers conditions such as medication-change requests, urgent language, apparent medication/allergy conflicts, and missing or truncated context. The draft check looks for medication-change language, diagnosis or prescribing language, and missing grounding signals. Results include a decision, reason codes, and a policy version.

These are demonstration rules rather than validated clinical decision rules. Their role in the prototype is to make stopping conditions explicit and testable.

The point at which review begins determines what a reviewer can do. A run stopped before generation has no draft to approve. A run stopped after generation can hold an existing draft and its citations for review.

Approval publishes that existing draft. Rejecting or requesting changes terminates the run. Reviewer rationale is recorded with the action; it does not become a new instruction to the model, and requesting changes does not regenerate the answer.

The review service also checks a version when saving an action. This prevents two reviewers working from the same version from independently applying conflicting decisions.

Keeping Execution Visible and Recoverable

The frontend receives server-sent events when graph nodes start and complete. React Flow uses those events to show the active execution step, including time spent waiting for a response provider.

This is node-level progress. The provider’s answer remains buffered until it can be parsed and validated, so the interface does not display model tokens as they arrive.

The backend saves completed-node snapshots in SQLite. These retain transitions, evidence projections, safety results, review information, and any generated draft or final response. The raw question and full patient summary are omitted from the persisted projection, although answer text can still contain clinical content.

On restart, pending reviews remain available. Interrupted queued or running workflows are marked failed rather than automatically replayed. The stored snapshots support inspection and the implemented review actions; they do not provide arbitrary graph resumption.

The frontend’s general run list has a different lifetime: it is browser-session state. An individual persisted run can be fetched by ID, but the UI is not yet a complete browser for all historical runs.

Checking the Behavior Locally

The repository provides a single command to prepare its local demonstration:

CLINICAL_LLM_PROVIDER=fake make demo-up

With the documented Python, Node.js, pnpm, Make, and Docker prerequisites installed, this command prepares dependencies, starts infrastructure, seeds synthetic records, indexes the guidelines, and starts both applications. Initial setup requires downloads.

At http://localhost:5173, select a seeded synthetic patient and start with an allergy-history question. Then try a supported guideline question, such as “What blood pressure target is recommended for adults?” The fake provider makes execution predictable; a configured model provider is needed to evaluate actual generated answer quality.

The demo guide lists supported questions. The repository also includes tests for routing, bounded context selection, provider failures, review concurrency, and restart handling. make check runs the full local quality checks.

Taking the Prototype Further

The current implementation gives developers several concrete extension points. Additional direct patient summaries need explicit routes, formatting rules, and patient-evidence citations. Broader guideline coverage needs reviewed sources and retrieval evaluations, including questions the corpus should refuse to answer.

A more flexible review process needs its own continuation design. Before allowing a reviewer to restart generation, the application would need to decide what context to retain, what evidence to revalidate, and how a changed request affects the original run.

Production authentication, authorization, tenancy, and operational governance also remain outside the current implementation. The prototype is useful today for following a question through patient retrieval, evidence selection, generation, and review, with each transition available for inspection. That is the starting point for extending the workflow without losing track of why it produced an answer or why it stopped.

Conclusion

This prototype shows what an evidence-based clinical AI workflow looks like when FHIR data, guideline retrieval, and language generation are kept in separate, auditable layers. By routing patient context through HAPI FHIR, guideline evidence through Weaviate, and decisions through LangGraph’s branching logic, the system avoids the common trap of sending raw patient records straight to a model.

The safety and review gates, both pre- and post-generation, are what make this more than a retrieval demo. Flagging medication changes or urgent language before a draft reaches a clinician, and requiring review on certain conditions, builds a workable check into the pipeline rather than bolting one on after the fact.

What stands out most is the transparency layer: every execution snapshot preserves the reasoning path and evidence used, without storing raw patient data. That combination, traceable decisions plus data minimization, is the part worth carrying into any production version of this workflow.

Sanket Nawghare

Sanket Nawghare

Full Stack Developer

Connect Now

Sanket Nawghare is a Full Stack Developer with 4+ years of experience building scalable and high-performance web applications. He has hands-on expertise in React, Node.js, Java, and MySQL, with a strong focus on developing clean, maintainable, and efficient solutions across both frontend and backend systems. He has worked extensively on US healthcare projects, contributing to secure, reliable, and user-friendly applications in compliance-driven environments. His interests include system architecture, performance optimization, API development, and building robust enterprise-grade applications.

Share This Blog

Read More Similar Blogs

Let’s #Transform Healthcare,# Together.

Partner with us to design, build, and scale digital solutions that drive better outcomes.

Location

Global Tech Teams LLC, 525 Washington Blvd, Industrious at Newport Tower, Jersey City, NJ 07310, United States.

Contact

+1 408 786 5974
contact@mindbowser.com
BOOK A QUICK CONSULTATION

Have a Healthcare Project in Mind?

Let’s discuss your goals, workflows, and next steps in a focused consultation call.

Calendar icon Schedule a Call

Contact form