Deploy ML Models: Predictions to FHIR RiskAssessments
Level: Intermediate
You have a model that outputs risk scores. To make those scores useful inside an EHR — visible to clinicians, dashboards, and quality measures — they have to become FHIR RiskAssessment resources. This tutorial shows the bridge: take the predictions your model already produced and emit spec-valid FHIR, one resource per patient, then optionally write them back to a live FHIR server.
Check out the full working example here!
Quick Start
The example runs offline with a pre-baked predictions dict — no model file, no server, no setup:
Built 3 RiskAssessment resources:
Patient/1: HIGH (85%) → RiskAssessment/hc-1cdf...
Patient/2: MODERATE (52%) → RiskAssessment/hc-5de5...
Patient/3: LOW (9%) → RiskAssessment/hc-e1cb...
Bring Your Own Model
HealthChain is deliberately unopinionated about the model. XGBoost, a neural net, a scikit-learn pipeline — the only thing this step needs is the score your model already produced. Represent each prediction as a plain dict keyed by patient reference:
PREDICTIONS = {
"Patient/1": {"probability": 0.85, "qualitative_risk": "high"},
"Patient/2": {"probability": 0.52, "qualitative_risk": "moderate"},
"Patient/3": {"probability": 0.09, "qualitative_risk": "low"},
}
How you get from raw FHIR to those features is your model's business — LOINC/SNOMED lookups, aggregation windows, imputation. HealthChain picks up once you have a score.
Emit FHIR
create_risk_assessment_from_prediction turns a prediction into a spec-valid RiskAssessment: the outcome as a coded CodeableConcept, the probability as probabilityDecimal, and the qualitative level as a coded qualitativeRisk. Loop it over your predictions and collect the results in a Bundle:
from healthchain.fhir import create_bundle, add_resource
from healthchain.fhir import create_risk_assessment_from_prediction
SEPSIS = {
"code": "A41.9",
"display": "Sepsis, unspecified organism",
"system": "http://hl7.org/fhir/sid/icd-10",
}
bundle = create_bundle()
for subject, scores in PREDICTIONS.items():
risk = create_risk_assessment_from_prediction(
subject=subject,
prediction={
"outcome": SEPSIS,
"probability": scores["probability"],
"qualitative_risk": scores["qualitative_risk"],
},
comment="Generated by sepsis-risk model v1",
)
add_resource(bundle, risk)
Example RiskAssessment Resource
{
"resourceType": "RiskAssessment",
"id": "hc-1cdf...",
"status": "final",
"subject": { "reference": "Patient/1" },
"prediction": [{
"outcome": {
"coding": [{
"system": "http://hl7.org/fhir/sid/icd-10",
"code": "A41.9",
"display": "Sepsis, unspecified organism"
}]
},
"probabilityDecimal": 0.85,
"qualitativeRisk": {
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/risk-probability",
"code": "high",
"display": "High"
}]
}
}]
}
For anything the helper doesn't cover — basis references to the observations behind a score, a coded method for the model, an occurrence timestamp — construct the RiskAssessment via fhir.resources directly.
Take It Live
Producing FHIR is the point because the resources can land in the EHR. Configure a FHIRGateway source and write each assessment back, where it becomes available to dashboards, reports, and downstream workflows:
from healthchain.gateway import FHIRGateway
from healthchain.gateway.clients import FHIRAuthConfig
gateway = FHIRGateway()
gateway.add_source("medplum", FHIRAuthConfig.from_env("MEDPLUM").to_connection_string())
for entry in bundle.entry:
created = gateway.create(entry.resource, source="medplum")
print(f"wrote RiskAssessment/{created.id}")
Prerequisites: a FHIR server with patient data. This example uses Medplum — see the FHIR Sandbox Setup guide for credentials, then add them to .env:
MEDPLUM_BASE_URL=https://api.medplum.com/fhir/R4
MEDPLUM_CLIENT_ID=your_client_id
MEDPLUM_CLIENT_SECRET=your_client_secret
MEDPLUM_TOKEN_URL=https://api.medplum.com/oauth2/token
The written resources are visible in the Medplum console — search "RiskAssessment" in the resource type search bar.
Next Steps
- Real-time alerts: To surface a score at the point of care instead of persisting it, return it as a CDS Hooks card — see the CDS Hooks reference.
- Add more FHIR sources: The gateway supports multiple sources — see the FHIR Sandbox Setup guide.
- Go to production: Scaffold a project with
healthchain newand run withhealthchain serve— see From cookbook to service.