Using Tasks
to Manage Workflow
Introduction
Workflow is an essential part of healthcare, and healthcare operations requiring coordination of many manual steps physicians, patients, nurses, care coordinators, etc.
While the majority of FHIR resources represent clinical data that is operated on, FHIR also defines a set of workflow resources that describe and track work to be done. This guide will discuss the usage of the Task
resource, which is the basic building-block resource used to implement care plans and track workflow progress.
For example, a Task
might represent the task of having a practitioner complete a PHQ-9 questionnaire for a patient as part of their onboarding.
A common application is for organizations to build task queue systems to route tasks to the correct practitioner based on specialty, level of credential, and availability. The Medplum Task Demo application provides a minimalist task queue that demonstrates task search, assignment, and status.
Task type
The Task.code
element is used to represent the task type, equivalent to the task title. This can either be different from task to task, or selected from an standard set of task types. Using the latter approach helps enable querying across all Tasks
of the same type.
While using SNOMED or LOINC codes are preferred, many implementations simply use the Task.code.text
element, as task types are often implementation-specific.
Task.description
can be used to add additional descriptive text to the specific Task
instance.
**Example: **
{
resourceType: 'Task',
id: 'example-task',
code: {
text: 'Complete PHQ-9',
coding: [{
code: '715252007',
system: 'http://snomed.info/sct'
}]
},
description: "Patient to complete PHQ-9 depression screening",
//...
}
Task status
Designing status codes for tasks varies from implementation to implementation, and requires a good understanding of your operations.
Task
provides three fields fields, status
, businessStatus
, and statusReason
.
Task.status
maps to a the FHIR task lifecycle shown below. It provides coarse-grained information about the activity state of a Task
and is most useful for day-to-day operations, as it allows for efficient queries on active, completed, and cancelled tasks. These queries will remains stable as your implementation scales. (Note: in the diagram below, the codes requested
, received
, accepted
, rejected
only apply when Tasks
are shared between systems. Most implementations will just use ready
to indicate a Task
can be actioned)
Task.businessStatus
should map to your implementation's specific operational funnel. It provides fine-grained information for customer-service and operations teams to troubleshoot tasks and monitor progress. It is also useful for analytics teams to compute conversion metrics between pipeline stages.
Task.statusReason
describes why the Task
has the current status, and is most commonly used when status
is set to "on-hold"
or "cancelled"
. Using an orthogonal statusReason
allows operations teams to efficiently query for all tasks at the same point in the funnel, while analytics teams can further break down by all the reasons they may be on hold.
Task priority
Task.priority
can be used to indicate the urgency of the task. This field uses a fixed set of codes that are borrowed from acute in-patient care settings.
Code | Definition |
---|---|
routine | The request has normal priority. |
urgent | The request should be actioned promptly - higher priority than routine. |
asap | The request should be actioned as soon as possible - higher priority than urgent. |
stat | The request should be actioned immediately - highest possible priority. E.g. an emergency. |
While these terms might feel awkward in a digital health setting, Medplum recommends that implementations use these codes rather than create their own extensions in order to maintain interoperability with the ecosystem.
Task assignment
Task.for
indicates who benefits from the task, and is most commonly the patient for whom care is being delivered.
Task.owner
indicates the party responsible for performing the task. This can either:
- An individual:
Practitioner
,PractitionerRole
,Patient
,RelatedPerson
- A group:
Organization
,HealthcareService
,CareTeam
You can search for all unassigned tasks, using the :missing
search modifier.
- Typescript
- CLI
- cURL
await medplum.searchResources('Task', 'owner:missing=true');
medplum get 'Task?owner:missing=true'
curl 'https://api.medplum.com/fhir/R4/Task?owner:missing=true' \
-H 'authorization: Bearer $ACCESS_TOKEN' \
-H 'content-type: application/fhir+json' \
A common pattern is telehealth practices to assign to assign tasks to all practitioners with a given role (e.g. clinical specialty, level of credential, etc.). Task.performerType
is a searchable element that can be used to indicate which roles can/should perform this task.
It is a best practice to select these roles from a standard code system to promote interoperability. The US Core Guidelines recommend using the SNOMED Care Team Member Function valueset for performerType
.
In rare instances, SNOMED might not contain an appropriate code for a given role (e.g. Customer Service Representative). Medplum recommends using the Standard Occupational Classification (SOC) codes published by the Bureau of Labor Statistics.
The table below contains SNOMED code for the common roles used in digital healthcare. Use can use the SNOMED online browser to search for additional codes.
Name | SNOMED Code | SOC Code |
---|---|---|
Doctors | 158965000 (Doctor) | 29-1210 (Physicians) |
Nurse Practitioner | 224571005 (Nurse Practitioner) | 29-1171 (Nurse Practitioners) |
Registered Nurse | 224535009 (Registered Nurse) | 29-1141 (Registered Nurses) |
Care Coordinator | 768820003 (Care Coordinator) | 11-9111 (Medical and Health Services Managers) |
Care Team Coordinator | 768821004 (Care Team Coordinator) | 11-9111 (Medical and Health Services Managers) |
Medical Billing Specialist | 1251542004 (Medical Coder) | 29-2072 (Medical Records Specialists) |
Quality Assurance | 56542007 (Medical record administrator) | 15-1253 (Software Quality Assurance Analysts and Testers) |
Assistant | 449161006 (Physician assistant) | 29-1071 (Physician Assistants) |
Below is an example of a Task.performerType
CodeableConcept using both SNOMED and SOC systems.
{
resourceType: 'Task',
// ...
performerType: [
{
text:'Medical Billing Specialist',
coding:[
// Snomed
{
code:'1251542004',
system: 'http://snomed.info/sct',
display: 'Medical Coder'
},
// US SOC
{
code:"29-2072"
system: "https://www.bls.gov/soc"
}
],
}
]
}
Task focus
The Task.focus
element tracks the FHIR resource being operated on by this task, known as the "focal resource". See the Examples section below for examples of focal resources in common scenarios.
Well maintained Task.focus
elements are critical data hygiene that streamlines operations and analytics . Making sure that every Task
has a populatedfocus
reference will make it easier to find all touch points for a given clinical resource, spot operational bottlenecks and calculate turn-around-times, conversions, and care quality metrics as your implementation scales.
Task start / due dates
The Task.restriction.period
field describes the time period over which the Task
should be fulfilled, with Task.restriction.period.end
representing the due date, and Task.restriction.period.start
representing the (potentially optional) start date.
Task completion times
The Task.executionPeriod
field describes the time period over which the Task
was actually actioned. Properly populating this field makes it easier to identify stalled tasks and compute turnaround-time metrics.
Task.executionPeriod.start
is used to store the start time of the first action taken against this task.
Task.executionPeriod.end
is used to mark the completion time of the final action taken against this task.
Task comments
Task.note
can be used to capture narrative text that is not represented elsewhere in the resource.
The most common usage for this field is to record comments from the task assignee as they work on the task. When used this way, it is a best practice to include the author
and time
fields in the Annotation
.
Subtasks
Tasks
can be organized into a hierarchical structure to create subtasks, sub-tasks, etc. To represent this hierarchy, subtasks should reference their parent using the using the Task.partOf
element. Task.partOf
is a searchable field, which can be used to query all sub-tasks of a given task, and can be combined with the _revinclude
and :iterate
directives to query the entire Task
tree.
While task hierarchy functionality is powerful, it can be complex to maintain and operationalize. Medplum recommends that most implementations start with a single-level Task
hierarchy, and gradually add depth over time.
Examples
Use Case | Task Owner | Focal Resource | Example businessStatuses | Additional Info |
---|---|---|---|---|
Complete patient intake questionnaire | New Patient. Care Coordinator | Questionnaire |
| Use Task.output to reference resulting QuestionnaireResponse |
Review lab report | Physician | DiagnosticReport |
| |
Verify patient identity (e.g. driver's license) | Patient. Care Coordinator | DocumentReference |
| |
Complete encounter notes | Physician | ClinicalImpression |
| Use Task.encounter to reference the original encounter |