Using Node-RED to implement clinical workflow

So a colleague came to me with an interesting challenge – how can you use Node-RED to implement clinical workflow? That’s a rather broad topic, so let’s take a simple use case.

Suppose you have an assessment, and as part of that assessment you want to be able to create a number of actions. For example you might want to book an appointment, order a test, notify someone if a score is above a threshold or enrol them on a case management programme. Let’s look at how we might implement this in Node-RED and FHIR.

The assessment can be represented as QuestionnaireResponse (QR) resource. It’s paired with an actual Questionnaire that has the question text, possible values and so forth, but it’s the QR that has the answers.

To specify what the action is going to be, we can make use of the ActivityDefinition resource. This defines what a specific action is intended to achieve – and the attributes needed to achieve it.

And for the action itself, we’ll use a Task to record it. The idea being that our workflow won’t actually perform the action – it will create a task for someone (or something) to do it. Of course, there’s no reason why the workflow itself couldn’t perform the action in some cases – but let’s not get ahead of ourselves.

So we’re now in a position to sketch out our flow (this is what I like about Node-RED – you get something up early that you can incrementally refine). Here’s what it looks like:

Screen Shot 2019-03-14 at 1.32.28 PM

We’re using a ‘fire and forget’ pattern – the application creating the questionnaire will send it to the flow, and immediately return – it’s not concerned with this extra processing. Of course, we may want to make it a more integral part of the flow – maybe we want to store the QR as well – or extract other resources from it. It’s easy to add this stuff.

So, the flow starts with an HTTP input (Assessment Complete) that receives the QR. The QR is passed to a JavaScript function node that pulls out the actions required from the QR. There can be more than one of course, so the node will generate a new message for each action (We’ll see how to do that in a moment).

The action messages are then passed to an HTTP request node to retrieve the ActivityDefinition, and then on to another JavaScript node to create the Task resource, then finally to an HTTP function node to send it to the server – logging any errors.

So we need to be able to extract a couple of things from the QR:

  • The patient reference
  • Any actions specified by the form filler.

Looking at the QR resource, there’s a subject property for the patient so that’s easy.

To identify an answer as one that will generate a task, we can look for an answer that refers to an ActivityDefinition resource. Those will be sent on to the ‘make Task’ nodes along with the original QR as we’ll need information from that – like the patient. In real life, we’ll likely need some of the other answers as well, as they may be needed to construct the Task. (for example if the task is to schedule an appointment, there may be an answer that specifies the specialty or the priority).

Here is an example of what a minimal QR could look like:

{
  "resourceType":"QuestionnaireResponse",
  "status": "completed",
  "subject": {"reference":"Patient/cf-1494177505991"},
  "item": [
        {"linkId":"task1","answer":[{"valueReference": 
           {"reference":"ActivityDefinition/contactPatient"}}]}
    ]
}

It has a single answer, which refers to the ‘contactPatient activity.

Looking at the nodes in the flow in more detail.

The HTTP input node defines the url to listen on. Provided that the request ‘Content-Type’ header is set to ‘application/json’ it will emit the QR in the msg.body property as a JSON object. It’s hooked to an HTTP response node, so the caller gets an immediate return.

The get tasks node iterates through the QR, pulling out all the references to an ActivityDefinition. For each one it finds, it emits a new message containing the url of the ActivityDefinition (and the QR as well). That’s the node.send() function. The function itself returns null – which means that the original message is not sent any further. So – if there were no actions in the QR, the flow will stop here.

Here’s the code:

Screen Shot 2019-03-14 at 1.37.42 PM.png

The Load Activity node just retrieves the ActivityDefinition resource (we should put some error management here – what if it doesn’t exist?)

Next up we create the Task resource. We have the ActivityDefinition and the original QR in the message, so it’s a simple matter to construct a Task resource. This is a very minimal implementation of course – in reality we’d likely pull more data from both the ActivityDefinition and QR to construct the Task

Screen Shot 2019-03-14 at 1.40.12 PM

After this, the Task is saved using an HTTP request node (it’s actually a POST of course).

And that’s about it. There are a lot of places where the flow could be improved – but that’s the essence of this approach. Get things working, then enhance them.

Oh – and one last point: When manually constructing resources, the $validate operation is invaluable with identifying errors, and it’s implemented by the reference servers. You’ll find it very helpful.

 

About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

3 Responses to Using Node-RED to implement clinical workflow

  1. Michael J Lawley says:

    I like the concept. Would be great to see an example that securely* manages credentials in such an interaction.

    * or at least with a clear articulation of where trust is being placed.

    • David Hay says:

      Thanks Michael! Would you accept checking for a valid access token? What it could do is to check for the token, maybe using an external Auth Server? Could also look at the whole SMART dance as well, or place an API server in front and place trust there…

  2. Pingback: Securing a FHIR endpoint in Node-RED | Hay on FHIR

Leave a Reply to David HayCancel reply

Discover more from Hay on FHIR

Subscribe now to keep reading and get access to the full archive.

Continue reading