CDS Hooks Protocol
CDS Hooks is an HL7 published specification for clinical decision support that enables external services to provide real-time recommendations during clinical workflows.
Overview
CDS hooks are triggered at specific events during a clinician's workflow in an electronic health record (EHR), such as when a patient record is opened or when an order is selected. The hooks communicate using FHIR (Fast Healthcare Interoperability Resources).
CDS Hooks are unique in that they are real-time webhooks that are triggered by the EHR, not by external services. This makes them ideal for real-time clinical decision support and alerts, but also trickier to test and debug for a developer. They are also a relatively new standard, so not all EHRs support them yet.
When | Where | What you receive | What you send back | Common Use Cases |
---|---|---|---|---|
Triggered at certain events during a clinician's workflow | EHR | The context of the event and FHIR resources that are requested by your service | "Cards" displaying text, actionable suggestions, or links to launch a SMART app | Allergy alerts, medication reconciliation, clinical decision support |
HealthChainAPI Integration
Use the CDSHooksService
with HealthChainAPI to handle CDS Hooks workflows:
from healthchain.gateway import HealthChainAPI, CDSHooksService
from healthchain.models import CDSRequest, CDSResponse
app = HealthChainAPI()
cds = CDSHooksService()
@cds.hook("patient-view", id="allergy-alerts")
def check_allergies(request: CDSRequest) -> CDSResponse:
# Your AI logic here
return CDSResponse(cards=[...])
app.register_service(cds, path="/cds")
Supported Workflows
Workflow Name | Description | Trigger | Status |
---|---|---|---|
patient-view |
Triggered when a patient chart is opened | Opening a patient's chart | ✅ |
order-select |
Triggered when a new order is selected | Selecting a new order | ⏳ |
order-sign |
Triggered when orders are being signed | Signing orders | ⏳ |
encounter-discharge |
Triggered when a patient is being discharged | Discharging a patient | ✅ |
API Endpoints
When registered with HealthChainAPI, the following endpoints are automatically created:
Endpoint | Method | Function | Description |
---|---|---|---|
/cds-services |
GET | Service Discovery | Lists all available CDS services |
/cds-services/{id} |
POST | Hook Execution | Executes the specified CDS hook |
Request/Response Format
CDSRequest Example
{
"hookInstance": "23f1a303-991f-4118-86c5-11d99a39222e",
"fhirServer": "https://fhir.example.org",
"hook": "patient-view",
"context": {
"patientId": "1288992",
"userId": "Practitioner/example"
},
"prefetch": {
"patientToGreet": {
"resourceType": "Patient",
"gender": "male",
"birthDate": "1925-12-23",
"id": "1288992",
"active": true
}
}
}
CDSResponse Example
{
"cards": [{
"summary": "Bilirubin: Based on the age of this patient consider overlaying bilirubin results",
"indicator": "info",
"detail": "The focus of this app is to reduce the incidence of severe hyperbilirubinemia...",
"source": {
"label": "Intermountain",
"url": null
},
"links": [{
"label": "Bilirubin SMART app",
"url": "https://example.com/launch",
"type": "smart"
}]
}]
}
Supported FHIR Resources
Patient
Encounter
Procedure
MedicationRequest
For more information, see the official CDS Hooks documentation.
Advanced Workflow Example
This example demonstrates how to build a custom CDS Hooks workflow that performs advanced clinical analysis and generates tailored decision support cards. By combining adapters and a custom pipeline, you can process incoming FHIR data, apply your own logic (such as risk assessment), and return dynamic CDS cards to the EHR.
from healthchain.io import CdsFhirAdapter, Document
from healthchain.pipeline import Pipeline
from healthchain.pipeline.components import CdsCardCreator
from healthchain.models import CDSRequest, CDSResponse
from healthchain.gateway import HealthChainAPI, CDSHooksService
# Build custom pipeline with analysis and card creation
pipeline = Pipeline([Document])
@pipeline.add_node
def analyze_patient_data(doc: Document) -> Document:
"""Custom function to analyze patient data and document content"""
# Access FHIR prefetch resources
patient = doc.fhir.get_prefetch_resources("patient")
document_ref = doc.fhir.get_prefetch_resources("document")
# Perform custom analysis
if patient:
age = 2024 - int(patient.birthDate[:4]) # Simple age calculation
if age > 65:
doc._custom_analysis = {"high_risk": True, "reason": "Age > 65"}
else:
doc._custom_analysis = {"high_risk": False}
return doc
# Add card creator to format output
pipeline.add_node(CdsCardCreator(
template='{"summary": "Risk Assessment", "detail": "Patient risk level: {{ high_risk }}"}'
))
pipe = pipeline.build()
# Set up CDS service with custom workflow
app = HealthChainAPI()
cds = CDSHooksService()
@cds.hook("encounter-discharge", id="risk-assessment")
def assess_patient_risk(request: CDSRequest) -> CDSResponse:
# Use adapter for explicit format conversion
adapter = CdsFhirAdapter()
# Manual conversion with full document access
doc = adapter.parse(request) # CDSRequest → Document
processed_doc = pipe(doc) # Custom analysis + card creation
# Convert back to CDS response
return adapter.format(processed_doc) # Document → CDSResponse
app.register_service(cds, path="/cds")