Business Rule
The Business Rule task allows the evaluation of business rules defined in spreadsheet files. Supported formats include CSV, XLS, and XLSX. If a rule file lacks these extensions, it can also be processed if the Content-Type indicates a supported format.
The Business Rule task evaluates business rules using a specified rule file. The file can be stored on the web, AWS S3, Azure Blob, or elsewhere. The task supports various execution strategies, including cache timeout, as well as input and output columns. The rules can be configured to apply multiple logical operations, such as comparison, string, list, and date operations.
Prerequisites
- If the rule file is not publicly available, you must create an integration for the storage where the file is stored, with the required access keys or tokens:
- For Google Cloud Storage or Google Sheets: Create a GCP integration, then set its name in the
gcpIntegrationNameparameter.
- For Google Cloud Storage or Google Sheets: Create a GCP integration, then set its name in the
- Alternatively, upload the rule file to your cluster by creating a decision rule in Orkes Conductor. No integration is needed. See Create a decision rule in Orkes Conductor below.
Create a decision rule in Orkes Conductor
Available since
- v5.6.0 and later
Instead of hosting a rule file on external storage, you can save the decision table in Orkes Conductor and reference it by name in the Business Rule task. Only CSV is supported.
Create and use a decision rule
Use the Save business rule API (POST /api/business-rules) or navigate to Definitions > Decision Rules, and configure the decision rule using the following parameters:
| Parameter | Description |
|---|---|
| Rule Name | A unique name for the decision rule. Use this name as ruleName in the Business Rule task. The name cannot be changed after the rule is created. |
| Rule Data | Optional. Upload a CSV file to start with a decision table. You can also add rows and columns after creating the rule. In the API, pass the table as CSV text. |
You can version the decision rules, add tags, and grant READ, UPDATE, and DELETE access to other groups/applications by providing access via respective applications/groups. Learn more on RBAC.
Once created, in the Business Rule task, set ruleName instead of ruleFileLocation. Set ruleVersion to use a specific version. If you leave it out, the latest version is used.
Task parameters
Configure these parameters for the Business Rule task.
| Parameter | Description | Required/ Optional |
|---|---|---|
| inputParameters.gcpIntegrationName Available since: v5.6.0 and later | The name of the GCP integration used to read the rule file from a private Google Cloud Storage bucket or a private Google Sheet. The integration’s service account must have read access to the file. If the integration does not exist, the task fails. | Optional. |
| inputParameters.ruleFileLocation | URL of the spreadsheet to be evaluated, in CSV, XLS, or XLSX format. The file can be stored on the web, AWS S3, Azure Blob, Google Cloud Storage, Google Sheets, etc. For private Google Cloud Storage and Google Sheets files, create a GCP integration.
Content-Type indicates a supported format, such as a Google spreadsheet published to the web. |
Required if the rule is stored as a file, at a public or private URL. |
| inputParameters.ruleName Available since: v5.6.0 and later | Name of a decision rule saved in Orkes Conductor. | Required if using a decision rule saved in Orkes Conductor. |
| inputParameters.ruleVersion Available since: v5.6.0 and later | Version of the decision rule to use. If not provided, the latest version is used. | Optional. |
| inputParameters.executionStrategy | Strategy for rule execution. Supported types:
cacheTimeoutMinutes parameter. Rules saved in Orkes Conductor are not affected by this delay. Updates take effect from the next execution. |
Required. |
| inputParameters.cacheTimeoutMinutes Available since: v5.2.1 and later, v4.1.69 and later | The cache timeout, in minutes, which is the duration for which rule files are cached. If not configured, the task uses the default timeout of 60 minutes. Changes to a rule file take effect only after the cached copy expires. Note: When multiple tasks access the same rule file, the timeout is determined by the first task that loads the file. Subsequent tasks use the same cached file until it expires. See an example of cacheTimeoutMinutes in use. |
Optional. |
| inputParameters.inputColumns | The inputs to the rule file, which can be fixed or passed as a dynamic variable. Supports string, number, boolean, null, and object/array. | Required. |
| inputParameters.outputColumns | List of columns that will be present in the task output, which can be fixed or passed as a dynamic variable. | Required. |
Execution strategy
To understand the executionStrategy parameter, consider the following spreadsheet example:
| Name | Price |
|---|---|
| Phone | 10$ |
| Phone | 11$ |
If the input name is "Phone":
- With
FIRE_FIRST, the output price will be $10. - With
FIRE_ALL, the output price will be $11, as the second rule overwrites the first.
The following are generic configuration parameters that can be applied to the task and are not specific to the Business Rule task.
Caching parameters
You can cache the task outputs using the following parameters. Refer to Caching Task Outputs for a full guide.
| Parameter | Description | Required/ Optional |
|---|---|---|
| cacheConfig.ttlInSecond | The time to live in seconds, which is the duration for the output to be cached. | Required if using cacheConfig. |
| cacheConfig.key | The cache key is a unique identifier for the cached output and must be constructed exclusively from the task’s input parameters. It can be a string concatenation that contains the task’s input keys, such as ${uri}-${method} or re_${uri}_${method}. |
Required if using cacheConfig. |
Other generic parameters
Here are other parameters for configuring the task behavior.
| Parameter | Description | Required/ Optional |
|---|---|---|
| optional | Whether the task is optional. If set to true, any task failure is ignored, and the workflow continues with the task status updated to COMPLETED_WITH_ERRORS. However, the task must reach a terminal state. If the task remains incomplete, the workflow waits until it reaches a terminal state before proceeding. |
Optional. |
Supported operators
The Business Rule task supports the following operators:
| Operator type | Operator/Syntax | Description | Example |
|---|---|---|---|
| Comparison | <=, >=, =, <, > |
Performs numerical comparison between values. | price >= 100 |
| String | = |
Exact string match comparison. | name = John |
| String | != |
String inequality comparison. | name != John |
| String | startsWith Available since
|
Checks if a string begins with a specified substring | productName startsWith("iPhone") matches "iPhone 14", "iPhone 14 Pro", etc. |
| String | endsWith Available since
|
Checks if a string ends with a specified substring. | fileName endsWith(".pdf") matches "document.pdf", "report.pdf", etc. |
| String | contains Available since
|
Checks if a string contains a specified substring anywhere in it. | description contains("premium") matches "premium quality", "our premium product", etc. |
| String | matches Available since
|
Performs pattern matching using a regular expression. | email matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$") validates an email address format. |
| String | length Available since
|
Compares the length of a string with a numerical value. | password length >= 8 ensures a password has at least eight characters. |
| List | inList |
Checks if a value is in a specified list. | productName inList({"phone","laptop"}) will match if productName is a phone or laptop. |
| List | !=inList |
Checks if a value is not in a specified list. | productName !=inList({"phone","laptop"}) |
| Others | createList |
Generates a list with the specified elements. | createList({"A","B","C"}) will generate a list {"A", "B", "C"} in output. |
| Date comparison | - | Compares date values in supported formats: yyyy-MM-dd, yyyy-MMM-dd, yyyy-MM-dd HH:mm:ss. | purchaseDate >= 2025-01-01 |
Task configuration
This is the task configuration for a Business Rule task.
{
"name": "business_rule",
"taskReferenceName": "business_rule_ref",
"inputParameters": {
"ruleFileLocation": "https://business-rules.s3.amazonaws.com/rules.xlsx",
"executionStrategy": "FIRE_FIRST",
"cacheTimeoutMinutes": "30",
"inputColumns": {
"InputVariable1": "${workflow.input.InputVariable1}",
"InputVariable2": "${workflow.input.InputVariable2}"
},
"outputColumns": [
"OutputVariable1"
]
},
"type": "BUSINESS_RULE"
}
{
"name": "business_rule",
"taskReferenceName": "business_rule_ref",
"inputParameters": {
"gcpIntegrationName": "my-gcp-integration",
"ruleFileLocation": "gs://my-bucket/rules.csv",
"executionStrategy": "FIRE_FIRST",
"cacheTimeoutMinutes": "30",
"inputColumns": {
"InputVariable1": "${workflow.input.InputVariable1}",
"InputVariable2": "${workflow.input.InputVariable2}"
},
"outputColumns": [
"OutputVariable1"
]
},
"type": "BUSINESS_RULE"
}
{
"name": "business_rule",
"taskReferenceName": "business_rule_ref",
"inputParameters": {
"ruleName": "pricing-rule",
"ruleVersion": 1,
"executionStrategy": "FIRE_FIRST",
"inputColumns": {
"InputVariable1": "${workflow.input.InputVariable1}",
"InputVariable2": "${workflow.input.InputVariable2}"
},
"outputColumns": [
"OutputVariable1"
]
},
"type": "BUSINESS_RULE"
}
Task output
The Business rule task will return the following parameters.
| Parameter | Description |
|---|---|
| result | Contains the evaluated parameters based on the matching rule. The specific parameters inside the result object depend on the output columns specified in the task configuration. |
| matchedRows Available since: v5.5.2 and later | A list containing one entry per rule that fired, in fire order. Each entry has the same output columns as result.Regardless of executionStrategy, matchedRows lists every rule that fired, one entry per row, in fire order, and is empty if none matched. result keeps its last-wins behavior unchanged, so existing workflows are unaffected. With FIRE_FIRST, matchedRows has at most one entry. With FIRE_ALL, it can have several. |
| message | Returned only when no rule matches the input. States that no rules fired and lists any rule file columns that are missing from both inputColumns and outputColumns. |
| missingColumns | Returned only when no rule matches the input. A list of the rule file columns that are in neither inputColumns nor outputColumns. These columns are treated as inputs with empty values. |
| _ruleName | Name of the decision rule that was evaluated. Returned only for rules saved in Orkes Conductor. |
| _ruleVersion | Version of the decision rule that was evaluated. Returned only for rules saved in Orkes Conductor. |
| _ruleUpdateTime | Time the evaluated version was last updated. Returned only for rules saved in Orkes Conductor. |
If no rule matches the input, the task still completes, with an empty result and matchedRows.
Examples
Here are some examples for using the Business Rule task.
Using Business Rule task in a workflow
To illustrate the use of the Business Rule task in a workflow, consider the following rule file:
productType | productCategory | purchaseDate | itemCount | price | Discount | ShippingCharges
electronics | cellphone | <=2022-04-22 | 8 | != 100 | 11% | 5$
electronics | cellphone | <=2022-04-22 | 8 | < 100 | 13% | 15$
electronics | laptop | > 2022-mar-12 | >10 | <10.2 | 5% | 4$
beauty | powder | = 2022-01-01 | >15 | >=10.3 | 15% | 2$
food | pizza | < 2022-03-22 12:20:22 | 25 | >300 | 7% | 10$
Save the rule file as an Excel file with the name Product.xlsx and upload it to a publicly accessible location. Note the file URL.
Next, let’s create the workflow definition.
To create a workflow:
- Go to Definitions > Workflow, from the left navigation menu on your Conductor cluster.
- Select + Define workflow.
- In the Code tab, paste the following workflow definition:
{
"name": "BusinessRuleDemo",
"description": "Sample workflow demonstrating business rule task",
"version": 1,
"tasks": [
{
"name": "rule",
"taskReferenceName": "rule",
"inputParameters": {
"ruleFileLocation": "https://example-bucket.s3.amazonaws.com/Product.xlsx",
"executionStrategy": "FIRE_FIRST",
"inputColumns": {
"productType": "${workflow.input.productType}",
"productCategory": "${workflow.input.productCategory}",
"price": "${workflow.input.price}",
"itemCount": "${workflow.input.itemCount}",
"purchaseDate": "${workflow.input.purchaseDate}"
},
"outputColumns": [
"Discount",
"ShippingCharges"
]
},
"type": "BUSINESS_RULE"
}
],
"schemaVersion": 2
}
- Select Save > Confirm.
Ensure to update the ruleFileLocation to your location where the Excel file is stored.
Let’s test the different cases by running the workflow with varying input parameters.
To run the workflow for any case:
- Go to the Run tab, and enter the Input params for the case you want to test.
- Select Execute.
Case 1
If the workflow is triggered using the following input with FIRE_FIRST as the execution strategy:
{
"productType": "electronics",
"productCategory": "cellphone",
"price": "5",
"itemCount": "8",
"purchaseDate": "2022-04-22"
}
To find the matching rule,
Explanation:
- productType: Matches "electronics", which corresponds to rules defined for electronics in the rule file (rows 1, 2, and 3).
- productCategory: Matches "cellphone", narrowing down the applicable rules to those for electronics and cellphone (eliminating row 3).
- purchaseDate: Matches "
<=2022-04-22" (April 22, 2022 is on or before April 22, 2022), applying to rules (matching rows 1 and 2). - itemCount: Matches "8", which applies to rules requiring an itemCount of 8 (matching rows 1 and 2).
- price: Matches "!= 100" (5 is not equal to 100), specifically matching rules where the price is not equal to 100. Also matches “
<100” where 5 is less than 100 (matching rows 1 and 2).
With the FIRE_FIRST execution strategy, the first rule that matches the input will be evaluated. Therefore, even though both the first and second rules match, the first rule is chosen for execution.
Consequently, the output generated is:
Case 2
When using FIRE_ALL as the execution strategy, with the same input as Case 1:
{
"productType": "electronics",
"productCategory": "cellphone",
"price": "5",
"itemCount": "8",
"purchaseDate": "2022-04-22"
}
Here, since the input is the same as Case 1, we can narrow down the evaluation to row 1 and 2.
With the FIRE_ALL execution strategy, all rules that match the input will be evaluated. In this case, both the first and second rows match the input criteria. However, according to the FIRE_ALL strategy, subsequent rules can overwrite the output values of previous rules if they also match the input.
Therefore, even though both the first and second rules match, the second rule is chosen for execution.
Consequently, the output generated is:
Case 3
For a different case, if the workflow is triggered using the following input with FIRE_FIRST as the execution strategy:
{
"productType": "electronics",
"productCategory": "laptop",
"price": "10.0",
"itemCount": "12",
"purchaseDate": "2022-04-22"
}
To find the matching rule,
Explanation:
- productType: Matches "electronics", which corresponds to rules defined for electronics in the rule file (rows 1, 2, and 3).
- productCategory: Matches "laptop", narrowing down the applicable rules to those for electronics and laptops (eliminating rows outside this category).
- purchaseDate: Matches "> 2022-mar-12" (The input purchase date April 22, 2022 is after March 12, 2022), applying to rules where the purchase date is after March 12, 2022.
- price: Matches "
<10.2" (10.0 is less than 10.2). - itemCount: Matches ">10" (12 is greater than 10).
Based on these conditions, the input meets the criteria defined by the third rule in the rule file (row 3). Therefore, the output generated is:
Using `cacheTimeoutMinutes`
To illustrate the use of the cacheTimeoutMinutes parameter, consider a rule file that is used by multiple Business Rule tasks.
In this example, the Business Rule tasks A, B, C, and D use the same rule file fileA.
When multiple Business Rule tasks use the same rule file, the cache timeout is determined by the first task that loads the file. All other tasks share that cached version until it expires, regardless of their own cacheTimeoutMinutes value.
For example:
- At 10:00 AM, task A runs with
cacheTimeoutMinutesset to 10. It downloadsfileAand caches it for 10 minutes, until 10:10 AM. - At 10:05 AM, task B runs with
cacheTimeoutMinutesset to 60. It uses the cachedfileA. - At 10:08 AM, task C runs with
cacheTimeoutMinutesset to 5 . It also uses the cachedfileA. - At 10:10 AM, the initial cache expires.
- At 10:15 AM, task D runs with
cacheTimeoutMinutesset to 30. Because the previous cache has expired, it downloadsfileAagain and caches it for 30 minutes. Any task using this file within the next 30 minutes will use the cached version.
Using `matchedRows` to see every fired rule
To see how matchedRows differs from result, consider the following rule file:
Save this as shipping-rules.csv and upload it to a publicly accessible location. Note the file URL.
Use it in a workflow with the following configuration:
{
"name": "business_rule_matchedrows",
"description": "Business Rule matchedRows example",
"version": 1,
"schemaVersion": 2,
"tasks": [
{
"name": "business_rule",
"taskReferenceName": "business_rule_ref",
"inputParameters": {
"ruleFileLocation": "https://example-bucket.s3.amazonaws.com/shipping-rules.csv",
"executionStrategy": "FIRE_ALL",
"inputColumns": {
"shippingMethod": "${workflow.input.shippingMethod}",
"containerSize": "${workflow.input.containerSize}"
},
"outputColumns": [
"shippingCharge"
]
},
"type": "BUSINESS_RULE"
}
]
}
Case 1: FIRE_ALL, input matches all three rows
With the input:
All three rows match. With FIRE_ALL, each firing rule overwrites result, so only the last one survives there, but matchedRows keeps all three:
{
"result": {
"shippingCharge": "20"
},
"matchedRows": [
{ "shippingCharge": "10" },
{ "shippingCharge": "15" },
{ "shippingCharge": "20" }
]
}
Case 2: FIRE_FIRST, same input
With executionStrategy changed to FIRE_FIRST and the same input, all three rows still match, but only the first one fires:
Using a saved decision rule
To illustrate the use of a decision rule saved in Orkes Conductor, consider the following rule table. Save it as Product.csv on your device:
productType,productCategory,purchaseDate,itemCount,price,Discount,ShippingCharges
electronics,cellphone,<=2022-04-22,8,!= 100,11%,5$
electronics,cellphone,<=2022-04-22,8,< 100,13%,15$
electronics,laptop,> 2022-mar-12,>10,<10.2,5%,4$
beauty,powder,= 2022-01-01,>15,>=10.3,15%,2$
food,pizza,< 2022-03-22 12:20:22,25,>300,7%,10$
Next, go to Definitions > Decision Rules and create a decision rule named product-pricing by uploading the CSV file.
Then, create a workflow that utilizes this saved decision rule. Go to Definitions > Workflow and create a workflow using the following definition:
{
"name": "BusinessRuleDecisionRuleDemo",
"description": "Sample workflow demonstrating a Business Rule task with a saved decision rule",
"version": 1,
"tasks": [
{
"name": "rule",
"taskReferenceName": "rule",
"inputParameters": {
"ruleName": "product-pricing",
"ruleVersion": 1,
"executionStrategy": "FIRE_FIRST",
"inputColumns": {
"productType": "${workflow.input.productType}",
"productCategory": "${workflow.input.productCategory}",
"price": "${workflow.input.price}",
"itemCount": "${workflow.input.itemCount}",
"purchaseDate": "${workflow.input.purchaseDate}"
},
"outputColumns": [
"Discount",
"ShippingCharges"
]
},
"type": "BUSINESS_RULE"
}
],
"schemaVersion": 2
}
Run the workflow with the following input:
{
"productType": "electronics",
"productCategory": "cellphone",
"price": "5",
"itemCount": "8",
"purchaseDate": "2022-04-22"
}
The input matches the first and second rows. With FIRE_FIRST, the first matching rule is used, so the output generated is:
{
"result": {
"ShippingCharges": "5$",
"Discount": "11%"
},
"matchedRows": [
{
"Discount": "11%",
"ShippingCharges": "5$"
}
],
"_ruleName": "product-pricing",
"_ruleVersion": "1",
"_ruleUpdateTime": "1793885657239"
}
Next, let's update the rule and run the workflow again to see how changes take effect. Go to Definitions > Decision Rules, open product-pricing, change the Discount in the first row to 12%, and save. Run the workflow again with the same input. The updated rule is used from the next execution, and _ruleUpdateTime has a new value: