Tasks

The Canvas SDK includes functionality to create, update and add comments to tasks in Canvas.

Adding a Task #

To add a task, import the AddTask class and create an instance of it.

Attribute TypeDescription
idoptionalstring or UUIDTask unique UUID. If none one will be generated automatically.
assignee_idoptionalstringThe id of the staff the task should be assigned to.
team_idoptionalstringThe id of the team the task should be assigned to.
patient_idoptionalstringThe id of the patient the task is associated with.
titlerequiredstringThe title of the task. This is displayed at the top of a task card in the Canvas UI.
dueoptionaldatetimeA date/time when the task is due.
statusoptionalTaskStatusA status of OPEN, CLOSED or COMPLETED. Defaults to OPEN if not supplied.
priorityoptionalTaskPriorityA priority of STAT, URGENT, or ROUTINE. Defaults to no priority if not supplied.
labelsoptionallist[string]A list of labels that will be added at the bottom of a task card in the Canvas UI.
author_idoptionalstring or UUIDAuthor’s id to set task creator, defaults to CanvasBot.
linked_object_idoptionalstring or UUIDLinked object id of linked object.
linked_object_typeoptionalLinkableObjectTypeType of the LinkedObject

Enumeration Types #

Linked Object Type #

ValueDescription
REFERRALREFERRAL
IMAGINGIMAGING

TaskPriority #

ValueDescription
STATThe request should be actioned immediately — highest possible priority. E.g. an emergency.
URGENTThe request should be actioned promptly — higher priority than routine.
ROUTINEThe request has normal priority.

An example of adding a task:

import arrow

from canvas_sdk.effects import Effect
from canvas_sdk.effects.task import AddTask, AddTaskComment, UpdateTask, TaskPriority, TaskStatus
from canvas_sdk.events import EventType
from canvas_sdk.handlers import BaseHandler

from canvas_sdk.v1.data.lab import LabReport
from canvas_sdk.v1.data.staff import Staff
from canvas_sdk.v1.data.team import Team
from canvas_sdk.v1.data.referral import Referral


class MyHandler(BaseHandler):
    RESPONDS_TO = [
        EventType.Name(EventType.LAB_REPORT_CREATED),
    ]

    def compute(self) -> list[Effect]:
        lab_report = LabReport.objects.get(id=self.target)
        staff_assignee = Staff.objects.get(last_name="Weed")
        team = Team.objects.get(name="Labs")

        linked_task_type = AddTask.LinkableObjectType.REFERRAL
        referral = Referral.objects.get(id="d2194110-5c9a-4842-8733-ef09ea5ead11")

        if lab_report.patient:
            add_task = AddTask(
                assignee_id=staff_assignee.id,
                author_id=staff_assignee.id,
                team_id = team.id,
                patient_id=lab_report.patient.id,
                title="Please call the patient with their test results.",
                due=arrow.utcnow().shift(days=5).datetime,
                status=TaskStatus.OPEN,
                priority=TaskPriority.URGENT,
                labels=["call"],
                linked_object_id=referral.id,
                linked_object_type=linked_task_type,
            )

            return [add_task.apply()]

        return []

Updating a Task #

To update an existing task, import the UpdateTask class and create an instance of it.

Attribute TypeDescription
idrequiredstringThe id of the task being updated.
assignee_idoptionalstringThe id of the staff the task should be assigned to.
team_idoptionalstringThe id of the team the task should be assigned to.
patient_idoptionalstringThe id of the patient the task is associated with.
titleoptionalstringThe title of the task. This is displayed at the top of a task card in the Canvas UI.
dueoptionaldatetimeA date/time when the task is due.
statusoptionalTaskStatusA status of OPEN, CLOSED or COMPLETED. Defaults to OPEN if not supplied.
priorityoptionalTaskPriorityA priority of STAT, URGENT, or ROUTINE. See TaskPriority.
labelsoptionallist[string]A list of labels that will be added at the bottom of a task card in the Canvas UI.

An example of updating a task to a status of COMPLETED:

from canvas_sdk.effects.task import UpdateTask, TaskStatus
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        update_task = UpdateTask(
            id="d06276ba-85c5-471b-87c0-9c9805f4ca6f",
            status=TaskStatus.COMPLETED,
        )

        return [update_task.apply()]

Adding a comment to a task #

To add a comment to a task, import the AddTaskComment class and create an instance of it.

Attribute TypeDescription
task_idrequiredstringThe id of the task being updated.
bodyrequiredstringThe comment body.
author_idoptionalstring or UUIDAuthor’s id to set task comment creator, defaults to CanvasBot.
from canvas_sdk.effects.task import AddTaskComment
from canvas_sdk.handlers.base import BaseHandler
from canvas_sdk.v1.data.staff import Staff

class MyHandler(BaseHandler):
    def compute(self):
        author = Staff.objects.get(last_name="Weed")
        add_task_comment = AddTaskComment(
            task_id="d06276ba-85c5-471b-87c0-9c9805f4ca6f",
            body="I tried to call the patient but did not get an answer.",
            author_id=author.id
        )

        return [add_task_comment.apply()]

Creating a task and a comment together #

AddTaskComment requires the task_id of an existing task. To create a brand new task and add a comment to it in a single compute() return, supply your own id to AddTask and reuse that same value as the task_id on AddTaskComment. Because the id on AddTask is optional and is generated for you when omitted, the trick is simply to generate it yourself so you can reference it on the comment.

There is no need to create the task first and listen for a follow-up event — just return both effects from the same handler, with the AddTask effect before the AddTaskComment effect.

import uuid

import arrow

from canvas_sdk.effects import Effect
from canvas_sdk.effects.task import AddTask, AddTaskComment, TaskStatus
from canvas_sdk.events import EventType
from canvas_sdk.handlers import BaseHandler


class MyHandler(BaseHandler):
    RESPONDS_TO = [
        EventType.Name(EventType.LAB_REPORT_CREATED),
    ]

    def compute(self) -> list[Effect]:
        # Generate the task id up front so the comment can reference it.
        task_id = str(uuid.uuid4())

        add_task = AddTask(
            id=task_id,
            title="Please call the patient with their test results.",
            due=arrow.utcnow().shift(days=1).datetime,
            status=TaskStatus.OPEN,
        )

        add_task_comment = AddTaskComment(
            task_id=task_id,
            body="Results flagged abnormal — follow up today.",
        )

        # Order matters: the task must be created before the comment.
        return [add_task.apply(), add_task_comment.apply()]

Note: The effects are applied in the order they are returned, so the AddTask effect must come before the AddTaskComment effect that references it. Both effects must be returned from the same handler — don’t split them across separate handlers or plugins, and don’t defer either effect, since that breaks the ordering the comment relies on.