Skip to main content

Using Tasks to Manage Clinical Workflow

Workflow management is an essential part of healthcare, and healthcare operations requiring coordination of many manual steps physicians, patients, nurses, care coordinators, etc. Generally, our goals are to

  • Top-of-License Care: Ensure clinicians' time is being used efficiently.
  • Compliant Fifty-State Workflow: Make sure we can serve patients across a wide geographic area robustly and efficiently
  • Automation: Eliminate routine tasks to avoid clinician burnout.

The Medplum Clinical Task Management Demo provides an in-depth reference implementation of a task management system that addresses these concerns.


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 a 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: ''
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: status, businessStatus, and statusReason.

Task.status maps to 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 remain stable as your implementation scales. (Note: in the diagram below, the codes requested, received, accepted, and rejected only apply when Tasks are shared between systems. Most implementations will just use ready to indicate a Task can be actioned.)

Task lifecyle

Task.businessStatus should map to your implementation's specific operational funnel. It provides fine-grained information to help customer service and operations teams 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.

routineThe request has normal priority.
urgentThe request should be actioned promptly - higher priority than routine.
asapThe request should be actioned as soon as possible - higher priority than urgent.
statThe request should be actioned immediately - highest possible priority (i.e., 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 be either:

You can search for all unassigned tasks using the :missing search modifier.

await medplum.searchResources('Task', 'owner:missing=true');
Assigning tasks to roles

A common pattern in telehealth practices is the assignment of 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 codes for common roles used in digital healthcare. Use the SNOMED online browser to search for additional codes.

Doctors158965000 (Doctor)29-1210 (Physicians)
Nurse Practitioner224571005 (Nurse Practitioner)29-1171 (Nurse Practitioners)
Registered Nurse224535009 (Registered Nurse)29-1141 (Registered Nurses)
Care Coordinator768820003 (Care Coordinator)11-9111 (Medical and Health Services Managers)
Care Team Coordinator768821004 (Care Team Coordinator)11-9111 (Medical and Health Services Managers)
Medical Billing Specialist1251542004 (Medical Coder)29-2072 (Medical Records Specialists)
Quality Assurance56542007 (Medical record administrator)15-1253 (Software Quality Assurance Analysts and Testers)
Assistant449161006 (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',
// Snomed
system: '',
display: 'Medical Coder'
system: ""

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 for data hygiene and streamlining operations and analytics . Ensuring that every Task has a populated focus reference will make it easier to find all touchpoints for a given clinical resource, spot operational bottlenecks, and calculate turnaround-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 use 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.


Tasks can be organized into a hierarchical structure to create subtasks. To represent this hierarchy, subtasks should reference their parent using the using the Task.partOf element. Task.partOf is a searchable field that 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.


Use CaseTask OwnerFocal ResourceExample businessStatusesAdditional Info
Complete patient intake questionnaireNew Patient. Care CoordinatorQuestionnaire
  1. Questionnaire sent to patient
  2. First reminder sent
  3. Second reminder sent
  4. Questionnaire completed by patient
  5. Responses reviewed by care coordinator
Use Task.output to reference resulting QuestionnaireResponse
Review lab reportPhysicianDiagnosticReport
  1. Report Available
  2. Assigned to physician
  3. Reviewed by physician
  4. Discussed with patient
Verify patient identity (e.g. driver's license)Patient. Care CoordinatorDocumentReference
  1. Identification document requested
  2. Documentation received
  3. Documentation received
  4. Documentation verified
Complete encounter notesPhysicianClinicalImpression
  1. Encounter complete. Physician note required
  2. Note drafted
  3. Note finalized
Use Task.encounter to reference the original encounter

See Also