Using guards to add conditions to workflow state transitions

You can define a guard within a task definition to control a state transition. A guard is a Boolean expression that operates on field values described using LUSID’s filtering syntax. A guard must evaluate to ‘true’ in order for the state transition to succeed. 

For example, let's imagine you want to model the following simple workflow in a task definition:

You might want three possible state transitions, with three possible triggers, two of which have the following conditions:

  • The transition from Pending to Approved should only succeed if a value for the assignee field is provided.

  • The transition from Pending to Denied should only succeed if values for the assignee and reasonForDecision fields are provided.

To enforce these conditions, you can add a guard to each of these state transitions. To do this, call the CreateTaskDefinition or UpdateTaskDefinition API and, within transitions, pass in a guard value using LUSID's filtering syntax. This portion of the API request might look like this:

"transitions": [
  {
    "fromState": "Pending",
    "toState": "Approved",
    "trigger": "grant",
    "guard": "fields['assignee'] exists"
  },
  {
    "fromState": "Pending",
    "toState": "Denied",
    "trigger": "reject",
    "guard": "fields['reasonForDecision'] exists and fields['assignee'] exists"
  }

If a state transition is attempted but the guard conditions are not met, the request produces an error.

Unique to the Workflow Service, you can also reference a task's CurrentUser, UserCreated and UserUpdated in guard conditions for state transitions. This means you can, for example, prevent a user from approving a data approval task they created themselves. See the examples below for more information.

Field

Explanation

Example

UserCreated

The user who created the task.

UserCreated neq CurrentUser

CurrentUser

The user who triggered the state transition for which the guard is being evaluated.

version.userIdCreated neq CurrentUser

UserUpdated

The user who last updated the task. If the task has not been updated, this is the same as UserCreated (and may in any case be the same user).

UserUpdated neq CurrentUser