October 1, 2019

K2 Workflow & Application History

You are probably aware that K2 automatically captures an audit trail for all workflow instances, including information such as who started the workflow, the start date and time of all the steps, and who actioned tasks and what action they took. This information is exposed via SmartObjects (found under the Workflow Reports category) and forms the basis for the reports found in the Management and Workspace sites.

While this information is valuable, it does have some limitations.

The first limitation is that this information is security trimmed, meaning that your visibility of the workflow audit data is controlled by your workflow rights. For example, while someone with admin rights can see every workflow instance, someone with just View Participate can only see those that they started or actioned a task form.

The second limitation is that this information contains no business-related data. It does not, for example, capture any comments made when a user actions a task or allow for the addition of ad-hoc comments during the life of the workflow instance (or even before and after it). Additionally, this information is workflow specific, meaning it cannot be (easily) used to tie information about multiple workflow instances together.

A pattern that can be implemented to address these limitations is to create your own generic “Workflow/Application Instance History” SmartObject and use this to capture and display history for your workflow or application instance. There are two approaches to implementing this pattern – a workflow instance focus, or an application instance focus.

A workflow instance focus means that we are going to tie all the historical data that we capture to a specific workflow instance. This will work well for simple K2 apps that have a linear business process, such as a leave request app. A leave request typically does not spawn of separate workflow processes, and the data captured for a leave request is only used once by a workflow. In this approach, we would use the “Workflow ID” of the workflow instance as the common value to store for our workflow history.

The second approach ties all the history data to an “Application” instance. This approach works well for applications that may have multiple workflows started for the same data record. For example, a Change Request application may allow for sub-tasks to be created for a single change record, or it may start sub workflows as part of the main workflow. We want to tie the history for all related workflow instances together and present them as a single set of information for the request. For this approach we will need to use a common ID, such as a “Request ID”, to tie all of the workflow information together. Typically, this “Request ID” will be stored as a Guid (Global Unique Identifier) to allow us to generate a unique ID that can be used across multiple applications (e.g. the Change Request app and an Employee Onboarding app) – meaning we can re-use our history SmartObject anywhere.

For both approaches, there is a similar set of data we want to capture, including:

  • Action (e.g. the action a user or workflow took – e.g. approve)
  • ActionByUserEmail (email of user who performed the action)
  • ActionByDisplayName (Display name of the user who performed the action)
  • ActionDateTime (Date and time the action occurred)
  • Comments (any comments captured as part of completing the action)
  • WorkflowInstanceID – the unique ID for a workflow instance (generated by K2)

A SmartObject to capture Workflow Instance history could look like this:

To capture application instance history a SmartObject may look like this (note that we have an “ApplicationInstanceID” and a “WorkflowInstanceID” property)

You are of course free to choose what information you want to store, what your property names are and where you want to store this data (I have chosen SmartBox but this may not be advisable if you expect to create a large amount of data).

Regardless of the approach you want to take, there are two places that you will want to create history data – as part of your workflow to capture step history (e.g. approval tasks), and on your forms to allow users to add ad-hoc comments.

For both SmartObjects above I have an “ID” column that is set to auto-number. This column is used simply to generate a unique id for each row we add, and it allows K2 to get execute a Create method for this SmartObject (as a unique key is required for this).

For the “WorkflowInstanceID” column we are going get this value from within our Workflow. We will also need to store this data against our main application data object. For example, in a Leave Request app we would need to store this against our “Leave Request” SmartObject. This is what will allow us to tie our Leave Request to the related workflow history we are going to capture.

For the “ApplicationInstanceID” column you will also need to generate and store the same Guid against your main application instance data object. For example, if you have a Change Request application, you would need to have a property on your “Change Request” SmartObject to store and retrieve this value. I am not going to go into details on how to achieve this, apart from noting the following:

· A new Guid value can be generated by K2 using the System -> Management -> SmartObjects -> SmartObjects -> Common.NewGuid SmartObject
Once you have your SmartObject created it is simply a matter of calling it’s create method in your workflows and forms in the appropriate place. Let’s look at workflows first.

For a workflow history approach, the first thing you want to do is store the Workflow Instance ID against your main application SmartObject. This could be done together with any other update you do at the start of your workflow, such as setting the request status. The Workflow Instance ID can be found under the “Workflow” tab of the Context Browser under the “Workflow Section” and is simply called “ID”.

From there it is a matter of simply calling the “Create” method of your history SmartObject whenever appropriate. You may want to record the submit action (i.e. when the user submitted the form to start the workflow) in which case you can use the “Originator” fields and the “Now” function in the Context Browser.

The next logical place to want to create a history record is after each task is actioned. To make our lives easier K2 exposes some information in the context browser that means we only need to execute our create method once per task, not on each outcome path after our task decision step. By placing the SmartObject step immediately after the Task step in a multi-step, we can use the “Task User” section in the Context Browser to capture the Task User details and action.

At this point you might be wondering where I got the Comments input value from. This is simply a workflow variable I called “Approval Comments”. To populate this value, I pass it into the workflow when I call the “action a worklist item” rule on my form. Of course, this value will not get populated if you action your task via email, so be sure to reset this value to an empty string (using a “Set Variables” step) if you have multiple task recipients or tasks.

The only caveat to note about adding this SmartObject method as a multi-step with a task is that it will not get called if the task expires. If you want to capture the task expiry as part of the workflow history, you will need to add another SmartObject step on the Expiry path from your decision step.

Here is an example of a workflow with the calls to the create method of the history SmartObject outlined.

That’s it for the workflow, what about our forms? On a form you are going to want to display the workflow/application history and possibly allow users to add ad-hoc comments. The first step is to create a List View for our history SmartObject. Your list view layout will look something like the one below, with paging turned on and editing not allowed.

To get the list to display only the relevant data, I am going to use a parameter on the view and pass it to my Get List method on the View Initialise rule. I have called my parameter pWorkflowInstanceID and made it a number.

On my View Initialise rule I check if the parameter has been passed to the view, and if so, I call the Get List view method

When configuring the Get List method I add map my parameter as an input to the “WorkflowInstanceID” property, and sort the data by ActionDateTime.

To implement this view on a form we will need to be able to pass the “WorkflowInstanceID” from our main application SmartObject to the view (or if we are using the Application Instance approach then we would be passing the “ApplicatonInstanceID”). To do this we can configure the form initialize rule so that the view initialize rule for the history list view occurs after we initialize and load the data on our application SmartObject view (e.g. the view that displays the System Access data).

After running a workflow and actioning the approval task, when I open the Leave Request form for this request I can now see the workflow history (I have added the list view to a tab on the form)

What if I want users to add ad-hoc comments to my workflow history? Simply add a toolbar button to your history list view and open as subview to capture a comment. Make sure you pass the “WorkflowInstanceID” to the subview (can be done as a parameter) so you can save this when you save the comment.

My comment now appears in the workflow history.

By creating a reusable SmartObject and Views we can implement this “workflow/application” history with any app we build, or even retro-fit in into existing apps, and provide the app users with easy access to workflow history and ad-hoc comments.


Book a call to find out more about how K2 can help with low-code digital process automation which will allow you to build faster and automate smarter or alternatively Play with K2.


This K2 trial experience provides you with 30 days of unlimited access to K2 Cloud so that you can evaluate everything the platform has to offer.