We use cookies
Ilya Beda

Clinical Form & Workflow management

How to maximize the benefits of using EMR software?
The answer is simple: to accurately model your clinical workflows with the tools provided by the EMR. If your workflows run smoothly, you get the benefits of task automation, saving staffs’ time, proper utilization of resources, and much more.

In this article, we’ll share our vision of the unique minimalistic workflow engine implemented in Beda EMR. With this approach, you can build any kind of sophisticated workflow and automate your processes.
What is workflow?
Usually, when you hear the term workflow you envision some complex logic. Many software vendors are putting serious effort into implementing various UI workflow builders. At Beda Software we don’t want to compete with these complex solutions. We follow a slightly different approach.

A workflow could be implemented as a combination of SDC-powered form lifecycle and FHIR subscriptions. You can see the form lifecycle in the image below.
The form lifecycle schema
With the FHIR Questionnaire, you can define an interface to interact with users. It is possible to use Questionnaires as modules and assemble them in one form. You can prepopulate any values in this form to provide some default answers or required context information. The result of user interaction is QuestionnaireResponse which could be validated with FHIRPath expression during constraint checks. Finally, when a form is completed it will be extracted to a set of FHIR resources.

Then FHIR subscriptions are triggered by resource changes. This approach can be leveraged for all forms in the system to define how to react to any user action in the system.

Subscription handlers will produce side effects like email notifications, calling 3rd party software for risk analysis, prediction analytics, etc.
Technical challenges
Data extraction
Unfortunately, the majority of FHIR Questionnaire engines don’t respect the extraction part. They interrupt form life cycle one QuestionnaireResponse is generated. Indeed extraction step is complex, but the advantage of fully extracted data is huge.

You can’t build analytics on top of QuestionnaireResponse. In a nutshell, it is just a key-value storage where keys are driven by questionnaire and form layout. As a result, Questionnaire change may cause QustionnaireResponse structure change. So you can’t query data in the same way even for one questionnaire. Things become even more complex when you need to build analytics on top of multiple questionnaires.

While questionnaires may address the same data (vitals, measures, conditions information) each questionnaire may ask it in its own way. On the FHIR level, the data is perfectly structured as Conditions and Observations. In this way, it is much easier to analyze the data.

FHIR mapping was never an easy topic. Our approach for the mapping evolved over time.

The first tool we used was JUTE. It is a powerful engine that provides a nice experience in creating mappers. The data DSL nature is a big advantage. You can create an FHIR resource and just replace some values with JUTE expressions/directives. Please have a look at this mapper. It is pretty easy to understand what is going on here.

Unfortunately, JUTE provides its own syntax and approach for path expressions, while it is more convenient to use FHIRPath when you query data from FHIR Resources especially if you are querying QuestionnaireResponse. JUTE provides API to add any function inside the engine, so we embedded FHIRPath function. As a result, almost all JUTE expressions call FHIRPath function: jute.yaml It looks like an overhead, so we replaced the JUTE path engine with FHIRPath and made it FHIRPath native.

Finally, data DSL should be LLM-friendly and there should be an easy way to generate a mapper based on the text description. ChatGPT works pretty well with JSON and FHIRPath. So, you can just copy and paste the specification into ChatGPT and try to generate mappers.

As a result, we got the following specifications. Here you can check the video that demonstrates how you can generate mappers automatically via OpenAI.
Beda EMR is a low-code solution on top of SDC IG. No need to write code in a general-purpose programming language to change the system behavior. But you still need a way to check the Questionnaires and Mappers for correctness and write tests to ensure that the system operates correctly and further updates will not cause any regressions. The standard approaches like jest, pytest, erc. Won’t work in this case. It’s not possible to rely on specific programming language runtime availability. Running a custom code may be inappropriate for security reasons. Here is the approach the FHIR community is suggesting. There is a TestScript resource. Initially, it was designed to check that an FHIR server implementation is compliant with specific requirements like AU Core, CarinBB, etc. Beda EMR use case is pretty close to it. TestScript is a perfect approach To make sure that specific installation runs the workflow correctly.

Unfortunately, there is a lack of TestScript engines. The most known implementation is Touchstone. But it is a full-featured IDE for TestScript. While we need a lightweight evaluation engine. So we decided to implement a Python-based engine to evaluate TestScript definitions.
Don’t Repeat Yourself
Reviewing TestScript definitions from the above you may notice that they are bulk and contain lots of repetition. That causes possible errors and misconfiguration. So we started searching for some solution that could DRY TestScriop definitions and make them more compact.

The start point of the investigation: is it possible to write FHIR resources in a short manner? And the answer was yes, you can do it with FSH (FHIR Shorthand). The community created a DSL (domain-specific language) to define the content for IG (implementation guide). Furthermore, FSH provides RuleSet and Alias features that allow you to introduce reusable configurable templates that simplify resource definitions.

Here you can see a test that checks extraction of Questionnaire that creates a HealthcareService.

This example uses Alises and RuleSets defined from Beda EMR profiles.
Building a workflow bundle
The workflow bundle represents a specific workflow and contains all elements required to run it on top of Beda EMR. TestScript resources help you validate that the installed workflow works correctly. This concept simplifies workflow distribution and provides the ability to share workflow across multiple installations of Beda EMR.
Questionnaire bundle
To avoid duplicating code across various project and to maintain singular, sharable RuleSets, we developed Kaitenzushi, an open-source wrapper for SUSHI. This tool enables developers to convert FSH files into FHIR resources (in YAML or JSON format) while incorporating external dependencies like RuleSets and Aliases. Kaitenzushi facilitates the sharing of SUSHI artifacts across multiple projects and builds.

With Kaitenzushi, the CI/CD FHIR testing pipeline is:
  1. Write tests using FSH.
  2. Use Kaitenzushi to load external RuleSet and Alias definitions and convert FSH to JSON
  3. Bundle everything in one ndjson file suitable for FHIR BULK API import
The clinical workflows do not require very sophisticated tools to be implemented. The clinical workflow started pack includes just SDC specification and a set of open-source tools. You can try out the described approach while designing clinical workflows in Beda EMR. Looking forward to your feedback and suggestions.
Get a free consultation
If you have any other questions about Clinical Form and Workflow management, please reach us at hi@beda.software and we'll be happy to chat.