Skip to main content
Version: 3.3.4

Make decisions

The decision-making process is based on the rule engine that relies on two distinct rule files written in the Drools MVEL dialect:

  • Default rule file is an out-of-the-box set of rules that should not be modified. These rules are designed to handle standard decision-making scenarios and serve as the baseline for the system. The file is located in MinIO S3: doc-upload/payment_sanctions_screening/{tara_version}/rules/rules_v1.drl.

  • Custom rule file allows the implementation of specific rules tailored to business requirements. These rules are flexible and are used instead of the default ones, providing a way to handle a unique set of requirements. You can copy the default rule file, modify its content as needed, assign any name to your custom file, and add the name to the configuration. The file must be manually created and uploaded to MinIO S3: doc-upload/payment_sanctions_screening/rules/custom_rules.drl.

info

Do not change the filenames.

Business object

The rule file written in the Drools language uses a business object that contains all input and processed data values required for adjudication and decision-making. You can find this object in the message_wrapper column in Control Tower output for every request.

See sample message in JSON
{
"message": {
"id": "5384557",
"type": "PAYMENT_TRANSFER",
"subtype": null,
"content": null,
"contentFormat": null,
"payment": null,
"customAttributes": null
},
"hits": [
{
"hit": {
"id": "687139127",
"tagContent": "rubber meets the road Mueller-Bode customer journey",
"tagName": null,
"tagType": "FREETEXT",
"hitType": null,
"hitStartIndex": null,
"hitEndIndex": null,
"hitText": null,
"paymentInput": {
"id": null,
"type": null,
"subType": null,
"name": null,
"dob": null,
"address": null,
"locations": null,
"country": "",
"city": null,
"state": null,
"zip": null,
"codeMap": null
},
"derived": {
"id": null,
"idSource": null,
"name": "rubber meets the road",
"nameConfirmed": null,
"nameScore": 0.9959743469953537,
"nameSource": "NER",
"country": null,
"countryConfirmed": null,
"countrySource": null,
"address": null,
"addressConfirmed": null,
"addressSource": null,
"addressScore": 0.0,
"zip": null,
"zipConfirmed": null,
"zipSource": null,
"type": "NONENTITY",
"subType": null,
"typeConfirmed": null,
"typeSource": "NER"
}
},
"wle": {
"id": null,
"name": "RUBBER AB Science S.A. ",
"primaryName": "RUBBER AB Science S.A. ",
"aliases": [],
"address": "",
"locations": [],
"country": "PT",
"city": null,
"state": null,
"zip": null,
"type": "ORGANIZATION",
"dob": "",
"listType": "WORLD_COMPLIANCE",
"source": "SANCTIONS",
"sourceEntryId": null,
"sourceKeywords": null,
"codeMap": null,
"customAttributes": null
},
"idMatch": {
"match": null,
"input": "",
"inputProcessed": null,
"wle": "",
"wleProcessed": null,
"source": null
},
"typeMatch": {
"inputType": "NONENTITY",
"wleType": "ORGANIZATION",
"inputTypeConfidenceScore": 0.9959743469953537,
"match": false,
"input": "rubber meets the road",
"inputProcessed": null,
"wle": "RUBBER AB Science S.A. ",
"wleProcessed": null,
"source": "NER"
},
"nameMatch": {
"score": 0.4643,
"blackListed": false,
"blackListedWordStr": "",
"blacklistedSource": "NONE",
"nameMatcherSource": "wf-name-matcher",
"matchedWLEEntity": "WLE_NAME",
"inputHasLegalEnding": false,
"wleHasLegalEnding": true,
"legalEndingsAreDifferent": false,
"match": false,
"input": "rubber meets the road",
"inputProcessed": "rubber meets road",
"wle": "RUBBER AB Science S.A. ",
"wleProcessed": "rubber ab science",
"source": "NER"
},
"countryMatch": {
"blackListed": false,
"blackListedStr": "",
"blacklistedSource": "NONE",
"match": null,
"input": "",
"inputProcessed": "",
"wle": "PT",
"wleProcessed": "PT",
"source": "NER"
},
"addressMatch": {
"matcherSource": "STRING",
"comparisonOutput": null,
"score": 0.0,
"match": false,
"input": null,
"inputProcessed": null,
"wle": null,
"wleProcessed": null,
"source": null
},
"dobMatch": {
"match": null,
"input": "",
"inputProcessed": null,
"wle": "",
"wleProcessed": null,
"source": null
}
}
]
}

Each section of the JSON is represented in the Drools file as factors or global objects and is used to formulate rules.

Data model for rules

The following data model is available during rule evaluation.

Message

PaymentMessage message

Sample:

"message": {
"id": "35166_resolve",
"type": "PAYMENT_TRANSFER",
"subtype": null,
"content": null,
"contentFormat": null,
"payment": null,
"customAttributes": null
}

Object definition:

public class PaymentMessage {
private String id;
private MessageType type;
private String subtype;
private String content;
private ContentFormat contentFormat;
private PaymentInfo payment;
private Map<String, String> customAttributes;
}
FieldTypeValues in DRL
idString
typeEnum
  • MessageType.GGDS
  • MessageType.ACH
  • MessageType.SWF
  • MessageType.FED_WIRE
  • MessageType.PAYMENT_TRANSFER
  • MessageType.ISO_20022
subtypeEnum103
contentStringOriginal payment message or null
contentFormatEnum
  • FUF
  • TCM
  • NATIVE
  • SWIFT_MT
  • SWIFT_MX
  • SWIFT_NPP
  • SWIFT_ADK
paymentObjectCan be null
payment.directionEnum
  • INCOMING
  • OUTGOING
payment.senderObject
  • bic: String
  • name: String
  • country: String
payment.receiverObject
  • bic: String
  • name: String
  • country: String
customAttributesMap<String, String>Custom values that can be used in rules

Hit

A hit is a complex object that contains:

  • General hit information

  • Input information: screened entity data

  • Derived information received from Named Entity Recognition (NER) and LOOKUP

PaymentMessageHit hit

Sample:

"hit": {
"id": "123",
"tagContent": "/SE1350000000054910000011 \nWXYZSESS",
"tagName": "50A",
"tagType": "FREETEXT",
"hitText": "Key",
"hitStartIndex": null,
"hitEndIndex": null,
"paymentInput": {
"type": null,
"subType": null,
"name": null,
"dob": "01/01/2020",
"address": null,
"country": "Sweden",
"city": null,
"state": null,
"zip": null,
"ids": {
"IBAN": "SE1350000000054910000011",
"BIC": "WXYZSESS"
}
},
"derived": {
"id": "WXYZSESS",
"idSource": "NER",
"name": "Joe Doors",
"nameConfirmed": null,
"nameScore": null,
"nameSource": "LOOKUP",
"country": null,
"countryConfirmed": null,
"countrySource": null,
"address": null,
"addressConfirmed": null,
"addressSource": null,
"zip": null,
"zipConfirmed": null,
"zipSource": null,
"type": "ID",
"subType": "BIC",
"typeConfirmed": null,
"typeScore": null,
"typeSource": null
}
}

Object definition:

public class PaymentMessageHit {
private String id;
private String tagContent;
private String tagName;
private TagType tagType;
private String hitType;
private Integer hitStartIndex;
private Integer hitEndIndex;
private String hitText;
private PaymentInputEntity paymentInput;
private PaymentDerivedData derived;
}
FieldTypeValues in DRL
idStringUnique hit ID
tagContentStringTag value
tagNameStringTag name
tagTypeEnum
hitTextStringCan be null
hitStartIndexIntegerNot in use
hitEndIndexIntegerNot in use

Payment input object

FieldTypeValues in DRL
typeEnum
  • INDIVIDUAL
  • ORGANIZATION
  • COUNTRY
  • LOCATION
  • VESSEL
  • AIRCRAFT
  • ID
  • NAME
  • NONENTITY
  • ACCOUNT
subType of IDEnum
  • UUID
  • IBAN
  • BIC
  • ISIN
  • OTHER
nameStringScreened name
dobStringScreened date of birth
addressStringScreened address
countryStringScreened country
cityStringScreened city
stateStringScreened state
zipStringScreened postal code
codeMapMap<String, String>Map of collected IDs
locationsObjectAdditional set of location data

Derived object

FieldTypeValues in DRL
idStringNER-detected value.
idSourceEnum
  • NER
  • LOOKUP
  • SCREENED
nameStringNER-detected value.
nameConfirmedStringCurrently, always false.
nameScoreDoubleNER score for the name detected in free text.
nameSourceEnum
  • NER
  • LOOKUP
  • SCREENED
countryStringCan come from parsing ID or lookup
countryConfirmedStringSet to true if lookup can confirm the country.
countrySourceEnum
  • NER
  • LOOKUP
  • SCREENED
addressStringNER-detected value.
addressConfirmedStringSet to true if lookup can confirm the address.
addressSourceEnum
  • NER
  • LOOKUP
  • SCREENED
zipStringNot in use.
zipConfirmedStringCurrently, always false.
zipSourceEnumNot in use.
typeEnum
  • INDIVIDUAL
  • ORGANIZATION
  • COUNTRY
  • LOCATION
  • VESSEL
  • AIRCRAFT
  • ID
  • NAME
  • NONENTITY
  • ACCOUNT
subTypeString
  • UUID
  • IBAN
  • BIC
  • ISIN
  • OTHER
typeConfirmedStringCurrently, always false.
typeScoreDoubleNER score for the detected type.
typeSourceEnum
  • NER
  • LOOKUP
  • SCREENED

WLE

A watchlist entity (WLE) refers to the sanctioned entity information.

PaymentWatchListEntity wle

Sample:

"wle": {
"id": null,
"name": "Sanction Name Investment LLC",
"primaryName": "CONSOLIDATED INVESTMENTS LLC",
"aliases": null,
"address": "6820 S. Harl Ave., Tempe, Ariz., 85283, U.S.",
"locations": null,
"country": "US",
"city": null,
"state": null,
"zip": null,
"type": "ORGANIZATION",
"dob": null,
"listType": null,
"source": null,
"sourceEntryId": "id_1",
"sourceKeywords": null,
"codeMap": null,
"customAttributes": null
},

Object definition:

public class PaymentWatchListEntity {
private String id;
private String name;
private String primaryName;
private List<AliasInfo> aliases;
private String address;
private List<Location> locations;
private String country;
private String city;
private String state;
private String zip;
private EntityType type;
private String dob;
private String listType;
private String source;
private String sourceEntryId;
private String sourceKeywords;
private Map<String, String> codeMap;
private Map<String, String> customAttributes;
}
FieldTypeValues in DRL
idString
typeEntityType
  • INDIVIDUAL
  • ORGANIZATION
  • COUNTRY
  • LOCATION
  • VESSEL
  • AIRCRAFT
  • ID
  • NAME
  • NONENTITY
  • ACCOUNT
nameStringSanctioned name or location
aliasesString arrayAKA names
addressStringWLE address
countryStringWLE country
cityStringWLE city
stateStringWLE state
zipStringWLE postal code
dobStringWLE date of birth
codeMapMap<String, String>WLE list of IDs
locationsList<Object>WLE additional list of locations (type, country, state, city, address)
customAttributesMap<String, String>WLE list of custom values that can be used for adjudication
sourceStringWLE sanctioned source like OFAC
listTypeStringWLE listing type
sourceEntryIdStringWLE unique entry ID
sourceKeywordsStringWLE keywords

Thresholds

You can define thresholds during the AI Agent configuration. They are also available in the model:

  • dateMatchingThreshold: integer value in days

  • nameMatchingThreshold: double value

Decision factors

idMatch

IdMatch idMatch

Sample:

"idMatch": {
"match": false,
"input": "WXYZSESS",
"wle": "",
"source": "NER",
"inputProcessed": null,
"wleProcessed": null
}

Object definition:

public class IdMatch {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
}
FieldTypeValues in DRL
matchBoolean
  • true
  • false
  • null
inputStringMatched screened value
wleStringMatched WLE value
inputProcessedStringProcessed screened value
wleProcessedStringProcessed WLE value
sourceSourceType
  • NER
  • LOOKUP
  • SCREENED

typeMatch

TypeMatch typeMatch

Sample:

"typeMatch": {
"match": false,
"input": "John Doe",
"wle": "Johnson LLC",
"source": "NER",
"inputProcessed": null,
"wleProcessed": null,
"inputType": "INDIVIDUAL",
"inputTypeConfidenceScore":0.9
"wleType": "ORGANIZATION"
}

Object definition:

public class TypeMatch {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
private EntityType inputType;
private EntityType wleType;
private Double inputTypeConfidenceScore;
}
FieldTypeValues in DRL
matchBoolean
  • true
  • false
  • null
inputString
wleString
inputProcessedString
wleProcessedString
sourceSourceType
  • NER
  • LOOKUP
  • SCREENED
inputTypeEntityType
  • INDIVIDUAL
  • ORGANIZATION
  • COUNTRY
  • LOCATION
  • VESSEL
  • AIRCRAFT
  • ID
  • NAME
  • NONENTITY
  • ACCOUNT
inputTypeConfidenceScoreDoubleA value between 0 and 1 (probability) reflecting how confident the model is about the predicted type of the input entity
wleTypeEntityType
  • INDIVIDUAL
  • ORGANIZATION
  • COUNTRY
  • LOCATION
  • VESSEL
  • AIRCRAFT
  • ID
  • NAME
  • NONENTITY
  • ACCOUNT

nameMatch

NameMatch nameMatch

Sample:

"nameMatch": {
"score": 0.5593499999999999,
"blackListed": false,
"blackListedWordStr": "",
"blacklistedSource": "NONE",
"nameMatcherSource": "wf-name-matcher",
"matchedWLEEntity": "PRIMARY_NAME",
"inputHasLegalEnding": true,
"wleHasLegalEnding": true,
"legalEndingsAreDifferent": true,
"match": false,
"input": "INVESTMENT HOLDINGS INC",
"inputProcessed": "investment holdings",
"wle": "CONSOLIDATED INVESTMENTS LLC",
"wleProcessed": "consolidated investments",
"source": "NER"
}

Object definition:

public class NameMatch {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
private Double score;
private Boolean blackListed;
private String blackListedWordStr;
private BlacklistedSource blacklistedSource;
private String nameMatcherSource;
private MatchedWLEEntity matchedWLEEntity;
private Boolean inputHasLegalEnding;
private Boolean wleHasLegalEnding;
private Boolean legalEndingsAreDifferent;
}
FieldTypeValues in DRL
matchBoolean
  • true
  • false
  • null
inputStringScreened value
wleStringWLE value
scoreDoubleMatching score between 0 and 1
blacklistedBoolean
  • true
  • false if a blacklisted keyword is found
blackListedWordStrStringBlacklisted keyword value
blacklistedSourceBlacklistedSource Enum
  • ENTITY
  • CONTENT
  • COUNTRY
  • NONE
inputProcessedStringProcessed input name
wleProcessedStringProcessed WLE name
sourceSourceType Enum
  • NER
  • LOOKUP
  • SCREENED
inputHasLegalEndingBoolean
  • true
  • false
  • null
wleHasLegalEndingBoolean
  • true
  • false
  • null
nameMatcherSourceStringwf-name-matcher
matchedWLEEntityMatchedWLEEntity Enum
  • PRIMARY_NAME
  • WLE_NAME
  • ALIAS

countryMatch

CountryMatch countryMatch

Sample:

"countryMatch": {
"match": false,
"input": "Roslagsgatan 10 \n113 51 Stockholm, Sweden",
"wle": "123 Adams Street \n United States",
"blacklisted": false,
"source": "LOOKUP",
"inputProcessed": "SE",
"wleProcessed": "US",
},

Object definition:

public class CountryMatch {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
private Boolean blackListed;
private String blackListedStr;
private BlacklistedSource blacklistedSource;
}
FieldTypeValues in DRL
matchBoolean
  • true
  • false
  • null
inputStringScreened value
wleStringWLE value
blacklistedBoolean
  • true if a blacklisted country is found
  • false
blacklistedSourceBlacklistedSource Enum
  • ENTITY
  • CONTENT
  • COUNTRY
  • NONE
blackListedStrStringBlacklisted country value
inputProcessedStringScreened ISO2 country (can be multiple pipe-separated values)
wleProcessedStringWLE ISO2 country (can be multiple pipe-separated values)
sourceSourceType Enum
  • NER
  • LOOKUP
  • SCREENED

addressMatch

AddressMatch addressMatch

Sample:

addressMatch": {
"matcherSource": "AVSERVICE",
"comparisonOutput": {
"house_number_match": true,
"city_match": true,
"state_match": true,
"country_match": true,
"postal_code_match": null,
"road_match": true
},
"match": true,
"input": "6820 S Harl Ave, Tempe, AZ 85283, USA",
"inputProcessed": "6820 South Harl Avenue Tempe Arizona United States ",
"wle": "6820 S Harl Ave, Tempe, AZ 85283, USA",
"wleProcessed": "6820 South Harl Avenue Tempe Arizona United States ",
"source": "SCREENED"
}

Object definition:

public class AddressMatch extends ModelFeature {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
private AddressCompareSource matcherSource;
private ComparisonOutput comparisonOutput;
private double score;
}
FieldTypeValues in DRL
matcherSourceAddressCompareSource Enum
  • AVSERVICE
  • GEOCODER
  • STRING
matchBoolean
  • true if a full match
  • false
inputStringMatched input value
inputProcessedStringProcessed matched input value
wleStringMatched WLE value
wleProcessedStringProcessed matched WLE value
sourceSourceType
  • NER
  • LOOKUP
  • SCREENED
scoreDoubleValue between 0.0 and 1.0

ComparisonOutput contains details on which part of the address matched. Available in AVSERVICE only.

FieldTypeValues in DRL
house_number_matchBoolean
city_matchBoolean
state_matchBoolean
country_matchBoolean
postal_code_matchBoolean
road_matchBoolean

AVSERVICE indicates that the external address matching service was selected as the address matching source during the configuration. The addressMatch object is populated with values from the comparisonOutput object only when AVSERVICE is used, as shown in the table.

In addition to the match parameter that indicates whether the input address and the WLE address are an exact match, the score parameter is also available. It provides a fuzzy match score between the input address and the WLE address. For more information on how this score is calculated, refer to Perform address comparison.

dobMatch

DobMatch dobMatch

Sample:

"dobMatch": {
"match": false,
"input": "2000-01-01",
"wle": "Jul 23 1998",
"source": "SCREENED",
"inputProcessed": "01/01/2000",
"wleProcessed": "07/23/1988",
},

Object definition:

public class dobMatch {
private Boolean match;
private String input;
private String inputProcessed;
private String wle;
private String wleProcessed;
private SourceType source;
}
FieldTypeValues in DRL
matchBoolean
  • true
  • false
  • null
inputStringScreened value
wleStringWLE value
inputProcessedStringNormalized screened date to mm/dd/yyyy format
wleProcessedStringNormalized WLE date to mm/dd/yyyy format
sourceSourceType Enum
  • NER
  • LOOKUP
  • SCREENED

Model decision

In the default rule file, if no rules fired, the default decision is displayed:

"modelDecision: {
"suggestedAction": "NO_DECISION",
"comment": ""Cannot resolve potential match on sanctioned name(John Doe)
}

Create rule

Facts and globals

In Drools, globals and facts are two fundamental concepts used to pass external data and context to rules and represent the data that rules act upon:

  • Facts are the data objects or domain objects that rules use to make decisions. A fact can be any Java object, and it serves as the basis for rule conditions, such as the when section of a rule. The following facts are defined:

    • PaymentMessage

    • PaymentMessageHit

    • PaymentInputEntity

    • PaymentDerivedData

    • PaymentWatchListEntity

    • TypeMatch

  • Globals are external objects made available to your rules, but, unlike facts, they are not part of the working memory. Globals provide a way to inject external resources, services, or configuration settings into your rules. Globals are typically immutable within a single rule execution. Once set, the value does not change during the rule execution. The following globals are defined:

    • idMatch

    • typeMatch

    • nameMatch

    • countryMatch

    • addressMatch

    • nameMatchingThreshold

    • dateMatchingThreshold

    • modelDecision

By combining facts and globals, you can build complex and flexible rule-based systems that leverage external resources while making decisions based on the current state of your data.

See the example to illustrate the use of facts and globals in Drools:

import com.example.Order

global com.example.ShippingService shippingService

rule "Apply Shipping Discount"
when
$order: Order(totalAmount > 100)
then
double discount = shippingService.calculateDiscount($order);
$order.applyDiscount(discount);
end

In the example:

  • Order is a fact that represents the order with a total amount.

  • shippingService is a global that provides access to a shipping service to calculate discounts.

  • The rule applies a discount to the order if its total amount is larger than 100. It uses both the fact and the global to make this decision.

Additional functions

In the rule file, you can use the functions defined in the RulesUtil class:

  • resolve("comment", rulesDecision) makes the RESOLVE decision.

  • escalate("comment", rulesDecision) makes the NO_DECISION decision.

  • minimumDistance(String date1, String date2) calculates the period between two dates.

  • mapContainsValue(Map<String, String> messageMap, String key, String value) checks if a map key contains a given value.

  • textContainsMapValue(String text, Map<String, String> valueMap) checks if the text contains a map value.

  • textContainsValue(String text, String value) checks if the text contains a value.

  • isValidStr(String value).

  • isValidMap(Map<String, String> valueMap).

  • isWleLocationInText(String text, PaymentWatchListEntity wle) checks if any sanctioned location elements are found in the text; used when a sanctioned type is LOCATION.

  • isWleLocationInText(String text, PaymentWatchListEntity wle, boolean searchName) checks if any sanctioned location elements (name, city, country) are found in the text. Set boolean searchName to false to exclude name search, which allows using this function for any entity type or searching the whole content for the matching location.

  • isLocationAnyMatch(String scrCountry, String wleCountry). Country can contain multiple pipe-separated values, such as RU|GB.

  • isNameInText(String text, String name, boolean tokensOnly) returns true if all name tokens are found in the text.

  • isNamesInText(String text, List<String> names, boolean tokensOnly) returns true if any name in the list or all name tokens are found in the text.

  • String prepareConcatValue(String value) returns text in uppercase, without spaces and punctuation marks.

  • String prepareValue(String value) returns text in uppercase, with trimmed spaces and without punctuation marks.

  • hasMultipleTokens(String value) returns true if a string has multiple tokens separated by spaces or punctuation marks.

  • hasNTokens(String value, int n) returns true if a string has more than N tokens separated by spaces or punctuation marks.

  • int charsDifferenceDirectional(String one, String two) returns a minimum set of characters of String one that must be removed from (or added to) String two to make the strings equal.

  • int charsDifference(String one, String two) returns a minimum set of characters that must be removed from (or added to) the respective strings to make the strings equal.

  • isNameInclusive(String one, String two, boolean bidirectional) checks if one name token is contained within another. The boolean parameter controls if the name inclusion works both ways (true); otherwise (false), it returns true if the first name is contained within the second one.

  • isHieroglyphsChars(String text) returns true if a string does not contain hieroglyphs.

  • isLatinChars(String text) returns true if a string contains only Latin characters.

  • transliterate(String text) transliterates a given string to Latin characters.

  • textMatchRegex(String text, String regex, boolean fullMatch) matches or finds a regex pattern in a given text, with support for the Pattern.DOTALL, Pattern.CASE_INSENSITIVE, and Pattern.MULTILINE flags.

When

In most cases, the section is required to qualify a hit or watchlist entity for a new rule. You can use any objects mentioned above. See the code sample:

$hit: PaymentMessageHit(conditions via comma)
$wle: PaymentWatchListEntity(conditions via comma)
eval (expression)

Then

The section contains two available options:

  • Resolve:

    resolve("comment", rulesDecision)
  • Escalate:

    escalate("comment", rulesDecision)

Salience

The out-of-the-box default rules have salience in the range of 3000 to 1000.

In Drools, the salience attribute is a crucial element in the rule definition that influences the execution order of rules within a rule file. It allows you to specify the priority of a rule relative to the other ones. Rules with higher salience values are executed before rules with lower ones. You can assign an integer value to the salience attribute to set up the rule execution order.

Mind the following key points about the salience attribute in Drools:

  • Execution order. The salience attribute determines the execution order of rules. The higher the value, the more important the rule is, and it gets executed earlier in the rule execution cycle.

  • Default value. If a rule does not specify a salience value, it is assigned the default value of 0. Rules without explicit salience values are executed in an arbitrary order and can depend on the rule engine's internal decisions.

  • Ascending order. When evaluating rules with the salience values, Drools arranges them in the ascending order. Rules with the lowest salience values are executed first, followed by rules with higher values.

  • Negative values. You can assign negative salience values to rules if you want specific rules to be executed earlier than rules with positive salience values. For example, a rule with salience -1 is executed before a rule with salience 0.

  • Use cases. The salience attribute is used to control the rule execution order or prioritize rules based on a specific business logic, for example, when specific rules should have precedence over others.

  • Caution. While the salience attribute can be a powerful tool for rule prioritization, it should be used judiciously. Overusing or misusing of salience values can make rule sets complex and hard to manage. Maintain clarity in your rule definitions and document the reasons for setting particular salience values.

Thus, the salience attribute is a mechanism used to control the rule execution order based on assigned priorities. By assigning salience values to rules, you ensure that rules critical to your business logic execute in the desired order, allowing you to create a robust and efficient rule-based system.

Add custom rule file

To write rules, you can use the following applications:

To add a rule, complete the following steps:

  1. Create a custom rule file locally. The recommended filename is custom_rules.drl.

    You can use a different name for your custom rule file and specify it when configuring Tara. This allows you to maintain multiple versions of the rule file, which is useful for managing variations or retaining versions for auditing purposes.

  2. Edit the rule file. Use any text editor of your choice to open the file.

  3. Create a rule using the following template:

    rule "Name of the rule"
    activation-group "default"
    salience 2003
    when
    // Evaluation of the rule conditions goes here
    then
    // Define the actions to resolve or escalate based on the rule
    end
    1. Replace "Name of the rule" with a meaningful and descriptive name for your rule.

    2. Leave activation-group as "default".

    3. Set salience based on specific requirements.

    4. In the when section, define the conditions to be met for the rule to trigger.

    5. In the then section, specify the actions to be taken when the rule is triggered, including how to resolve or escalate the decision.

  4. Save the changes.

  5. Upload the modified file to MinIO S3: doc-upload/payment_sanctions_screening/rules/custom_rules.drl.

Example

As an example, let's implement the following business rule: "A hit should be resolved when the sender and the receiver are from the same country. Should be executed before the default rules."

  1. Define the rule structure:

    • Leave activation-group "default". This is a required value.

    • Set salience to 4000. As the rule should be executed before the default one, you must set the salience value to more than 3000.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when

    then

    end
  2. Define the when section:

    1. Specify the $message object.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage()
    then
    end
    1. Add base filtering for the message based on the payment info object.
    tip

    In Drools MVEL, you can call fields of the objects in () and also use . to access fields in the nested objects.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null)
    then
    end
    1. Add filtering for the country existing in the sender and receiver objects. Check for null values to avoid a Null Pointer Exception.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    then
    end
    1. Add a condition to evaluate the hit. You can use $message to get the sender and receiver data. Wrap all conditions in the eval() method to produce a Boolean outcome.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    eval($message.payment.sender.country == $message.payment.reciever.country)
    then
    end
  3. Define the then section.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    eval($message.payment.sender.country == $message.payment.reciever.country)
    then
    resolve("Sender and Receiver countries are the same: " + $message.payment.sender.country, rulesDecision)
    end

Migrate custom rules for version compatibility

The rule file structure can change between Tara versions, which might require manual synchronization with custom rules created in earlier versions. Mind the following:

  • Check import statements and update them if needed.

  • Update location match objects if applicable. Thus, starting with v3.3.0, locationMatch was split into countryMatch and addressMatch, and the LocationMatch object was renamed to CountryMatch.

  • If you set up filtering rules in previous Tara versions, transfer their settings to your custom rule file. As of v3.3.1, the BP messages filter bot step was removed, so any filtering logic must now be included directly in the custom rule file.

  • The rule file can control which decision score to use per rule. Usually, all name match and mismatch rules use the Name Matcher score, and all type match and mismatch rules use the type confidence score. If you want control over this, replace one function with the other. Note that older versions of the functions below continue working as well:

    • RulesUtils.resolve("narrative", rulesDecision, typeMatch.inputTypeConfidenceScore);
    • RulesUtils.resolve("narrative", rulesDecision, nameMatch.score);
    • RulesUtils.escalate("narrative", rulesDecision, nameMatch.score);
    • RulesUtils.escalate("narrative", rulesDecision, typeMatch.inputTypeConfidenceScore);