Rule business object and data model
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 business object 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 rule context
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;
}
| Field | Type | Possible values |
|---|---|---|
id | String | Message ID |
type | Enum |
|
subtype | String | 103 |
content | String | Original payment message or null |
contentFormat | Enum |
|
payment | Object | Can be null |
payment.direction | Enum |
|
payment.sender | Object | Can be null |
payment.sender.name | String | Sender name |
payment.sender.type | EntityType Object |
|
payment.sender.bic | String | BIC ID |
payment.sender.accountNumber | String | Sender's account |
payment.sender.otherIdentifications | Map<String, String> | Map of other sender's ID (type or value) |
payment.sender.address | String | Sender's address |
payment.sender.country | String | Sender's country |
payment.receiver | Object | Can be null |
payment.receiver.name | String | Receiver's name |
payment.receiver.type | EntityType Object |
|
payment.receiver.bic | String | BIC ID |
payment.receiver.accountNumber | String | Receiver's account |
payment.receiver.otherIdentifications | Map<String, String> | Map of other receiver's ID (type or value) |
payment.receiver.address | String | Receiver's address |
payment.receiver.country | String | Receiver's country |
payment.amount | Double | For example, 200.25 |
payment.currency | String | For example, USD |
customAttributes | Map<String, String> | Custom values that can be used in rules |
Hit wrapper
A hit wrapper collects all hit information in one object:
public class HitWrapper {
private PaymentMessageHit hit;
private PaymentWatchListEntity wle;
private IdMatch idMatch;
private TypeMatch typeMatch;
private NameMatch nameMatch;
private CountryMatch countryMatch;
private AddressMatch addressMatch;
private DOBMatch dobMatch;
private SecurityLookupData securityLookupData;
}
Hit
A hit is a complex object that contains:
General hit information
Input information: screened entity data
Derived information: data 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,
"codeMap": {
"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;
}
| Field | Type | Possible values |
|---|---|---|
id | String | Unique hit ID |
tagContent | String | Tag value |
tagName | String | Tag name |
tagType | Enum | |
hitText | String | Can be null |
hitStartIndex | Integer | Not used |
hitEndIndex | Integer | Not used |
Payment input object
A payment input object refers to screened input data (can be null).
| Field | Type | Possible values |
|---|---|---|
paymentInput.id | String | Contains an ID value if the hit was on an ID. |
paymentInput.type | Enum |
|
paymentInput.subType of ID | Enum |
|
paymentInput.name | String | Screened name |
paymentInput.dob | String | Screened date of birth |
paymentInput.address | String | Screened address |
paymentInput.country | String | Screened country |
paymentInput.city | String | Screened city |
paymentInput.state | String | Screened state |
paymentInput.zip | String | Screened postal code |
paymentInput.codeMap | Map<String, String> | Map of collected IDs |
paymentInput.locations | Object | Additional set of location data; can be null |
paymentInput.locations.address | String | Address |
paymentInput.locations.country | String | Country |
paymentInput.locations.city | String | City |
paymentInput.locations.state | String | State |
paymentInput.locations.type | String | A free formatted value, for example, residence or business |
Derived object
A derived object refers to data collected after processing.
| Field | Type | Possible values |
|---|---|---|
derived.id | String | NER-detected value |
derived.idSource | Enum |
|
derived.name | String | NER-detected value |
derived.nameConfirmed | String | Always false |
derived.nameScore | Double | NER score for the name detected in free text |
derived.nameSource | Enum |
|
derived.country | String | Can come from parsing ID or lookup |
derived.countryConfirmed | String | Set to true if lookup can confirm the country |
derived.countrySource | Enum |
|
derived.address | String | NER-detected value |
derived.addressConfirmed | String | Set to true if lookup can confirm the address |
derived.addressSource | Enum |
|
derived.zip | String | Not used |
derived.zipConfirmed | String | Always false |
derived.zipSource | Enum | Not used |
derived.type | Enum |
|
derived.subType | String |
|
derived.typeConfirmed | String | Always false |
derived.typeScore | Double | NER score for the detected type |
derived.typeSource | Enum |
|
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;
}
| Field | Type | Possible values |
|---|---|---|
id | String | |
type | EntityType Object |
|
name | String | Sanctioned name or location |
aliases | AliasInfo Object | AKA names |
aliases.name | String | Alias name |
aliases.type | Enum |
|
address | String | WLE address |
country | String | WLE country |
city | String | WLE city |
state | String | WLE state |
zip | String | WLE postal code |
dob | String | WLE date of birth |
codeMap | Map<String, String> | WLE list of IDs |
customAttributes | Map<String, String> | WLE list of custom values that can be used for adjudication |
source | String | WLE sanctioned source like OFAC |
listType | String | WLE listing type |
sourceEntryId | String | WLE unique entry ID |
sourceKeywords | String | WLE keywords |
locations | List<Object> | WLE additional list of location information; can be null |
locations.address | String | Address |
locations.country | String | Country |
locations.city | String | City |
locations.state | String | State |
locations.type | String | A free formatted value, for example, residence or business |
Thresholds
You can define thresholds during the AI Agent configuration. They are also available in the model:
dateMatchingThreshold: integer value in daysnameMatchingThreshold: 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;
}
| Field | Type | Possible values |
|---|---|---|
match | Boolean |
|
input | String | Matched screened value |
wle | String | Matched WLE value |
inputProcessed | String | Processed screened value |
wleProcessed | String | Processed WLE value |
source | SourceType |
|
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;
private List<EntityType> otherInputTypes
}
| Field | Type | Possible values |
|---|---|---|
match | Boolean |
|
input | String | Original screened value |
wle | String | Original best matching WLE value |
inputProcessed | String | Processed screened value |
wleProcessed | String | Processed best matching WLE value |
source | SourceType |
|
inputType | EntityType |
|
inputTypeConfidenceScore | Double | A value between 0 and 1 (probability) reflecting how confident the model is about the predicted type of the input entity |
wleType | EntityType |
|
otherInputTypes | List of EntityType | Possible additional input type: VESSEL (MARIA can be a person or a vessel name) |
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;
}
| Field | Type | Possible values |
|---|---|---|
match | Boolean |
|
input | String | Screened value |
wle | String | WLE value |
score | Double | Matching score between 0 and 1 |
blacklisted | Boolean |
|
blackListedWordStr | String | Blacklisted keyword value |
blacklistedSource | BlacklistedSource Enum |
|
inputProcessed | String | Processed input name |
wleProcessed | String | Processed WLE name |
source | SourceType Enum |
|
inputHasLegalEnding | Boolean |
|
wleHasLegalEnding | Boolean |
|
legalEndingsAreDifferent | Boolean |
|
nameMatcherSource | String | wf-name-matcher |
matchedWLEEntity | MatchedWLEEntity Enum |
|
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;
}
| Field | Type | Possible values |
|---|---|---|
match | Boolean |
|
input | String | Screened value |
wle | String | WLE value |
blacklisted | Boolean | true if a blacklisted country is found; otherwise, false |
blacklistedSource | BlacklistedSource Enum |
|
blackListedStr | String | Blacklisted country value |
inputProcessed | String | Screened ISO2 country (can be multiple pipe-separated values) |
wleProcessed | String | WLE ISO2 country (can be multiple pipe-separated values) |
source | SourceType Enum |
|
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;
}
| Field | Type | Possible values |
|---|---|---|
matcherSource | AddressCompareSource Enum |
|
ComparisonOutput contains details on which part of the address matched. Available in AVSERVICE only; can be null.
| Field | Type | Values in DRL |
|---|---|---|
comparisonOutput.house_number_match | Boolean |
|
comparisonOutput.city_match | Boolean |
|
comparisonOutput.state_match | Boolean |
|
comparisonOutput.country_match | Boolean |
|
comparisonOutput.postal_code_match | Boolean |
|
comparisonOutput.road_match | Boolean |
|
match | Boolean | true if a full match; otherwise, false |
input | String | Matched input value |
inputProcessed | String | Processed matched input value |
wle | String | Processed matched WLE value |
wleProcessed | String | Processed matched WLE value |
source | SourceType |
|
score | Double | Value between 0.0 and 1.0 |
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;
}
| Field | Type | Possible values |
|---|---|---|
match | Boolean |
|
input | String | Screened value |
wle | String | WLE value |
inputProcessed | String | Normalized screened date to mm/dd/yyyy format |
wleProcessed | String | Normalized WLE date to mm/dd/yyyy format |
source | SourceType Enum |
|
Security lookup data
Security lookup data refers to company information lookup by a security ID.
SecurityLookupData object definition
public class SecurityLookupData {
private boolean executed;
private String country;
private String city;
private String address;
private String region;
private String state;
private String postalCode;
private boolean shareHolderHighRiskIndicator;
private boolean highRiskIndicator;
private double totalShareholderOwnership;
private String id;
private String securityType;
private String name;
}
| Field | Type | Possible values |
|---|---|---|
executed | Boolean |
|
country | String | USA |
shareHolderHighRiskIndicator | Boolean |
|
highRiskIndicator | Boolean |
|
totalShareholderOwnership | Double | 49.5 (in %) |
id | String | KW0EQ0601694 |
securityType | String | ISIN |