Sanctions and watchlist screening
Compares a customer or payment party with a single sanctions or watchlist entry. Returns match, possible match or no match.
Example
Context
- watch_list_entry
- Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person. Date of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.
Input
Customer: Victor Morozan. Party type: person. Date of birth: 2 September 1991. Nationality: Canada. Occupation: dental hygienist, Toronto. Customer since 2019.
- Answer (JSON)
- value no_match, confidence 1
- Top options
- no_match 1
- possible_match 0
- match 0
The name is close to the listed person's, but the date of birth and nationality differ, so the answer is no_match.
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person.\nDate of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.", }) decision = decide("Customer: Victor Morozan. Party type: person. Date of birth: 2 September 1991.\nNationality: Canada. Occupation: dental hygienist, Toronto. Customer since 2019.") print(decision.value, decision.confidence)
More examples
Same name, birth date and nationalityanswer match · confidence 0.996
Context
- watch_list_entry
- Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person. Date of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.
Input
Customer: Viktor A. Morozan. Party type: person. Date of birth: 14 June 1968. Nationality: Moldova. Occupation: company director. Customer since 2024.
- Answer (JSON)
- value match, confidence 0.996
- Top options
- match 0.996
- no_match 0.003
- possible_match 0
The name, date of birth and nationality all agree with the listed person, so the answer is
match.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person.\nDate of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.", }) decision = decide("Customer: Viktor A. Morozan. Party type: person. Date of birth: 14 June 1968.\nNationality: Moldova. Occupation: company director. Customer since 2024.") print(decision.value, decision.confidence)
Name matches, no birth date on fileanswer possible_match · confidence 0.998
Context
- watch_list_entry
- Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person. Date of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.
Input
Payment beneficiary: Victor Morozan. Party type: person. Date of birth: not recorded. Nationality: not recorded. Address: not recorded.
- Answer (JSON)
- value possible_match, confidence 0.998
- Top options
- possible_match 0.998
- match 0.001
- no_match 0.001
The name matches an alias on the list but the record holds no date of birth or nationality to decide it, so the answer is
possible_match.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person.\nDate of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.", }) decision = decide("Payment beneficiary: Victor Morozan. Party type: person. Date of birth: not recorded.\nNationality: not recorded. Address: not recorded.") print(decision.value, decision.confidence)
A clearly different personanswer no_match · confidence 1
Context
- watch_list_entry
- Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person. Date of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.
Input
Customer: Valentina Moroz. Party type: person. Date of birth: 3 March 1990. Nationality: Poland. Occupation: architect, Gdansk. Customer since 2018.
- Answer (JSON)
- value no_match, confidence 1
- Top options
- no_match 1
- possible_match 0
- match 0
Valentina Moroz is a different name, born in another year, with another nationality, so the answer is
no_match.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "Name: Viktor Aleksandrovich Morozan. Aliases: Victor Morozan; V. A. Morozan. Type: person.\nDate of birth: 14 June 1968. Nationality: Moldova. Lists: an asset-freeze list.", }) decision = decide("Customer: Valentina Moroz. Party type: person. Date of birth: 3 March 1990.\nNationality: Poland. Occupation: architect, Gdansk. Customer since 2018.") print(decision.value, decision.confidence)
Listed shipping companyanswer match · confidence 0.997
Context
- watch_list_entry
- Name: Kestrel Bay Shipping Ltd. Aliases: Kestrel Bay Shipping Company. Type: entity. Registration: registered 2011, number 448190. Country: Belize. Lists: an asset-freeze list.
Input
Counterparty: Kestrel Bay Shipping Company Ltd. Party type: entity. Registered 2011, company number 448190, Belize. Role in the payment: beneficiary.
- Answer (JSON)
- value match, confidence 0.997
- Top options
- match 0.997
- possible_match 0.003
- no_match 0
The company's name, registration number, year and country agree with the listed entity, so the answer is
match.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "Name: Kestrel Bay Shipping Ltd. Aliases: Kestrel Bay Shipping Company. Type: entity.\nRegistration: registered 2011, number 448190. Country: Belize. Lists: an asset-freeze list.", }) decision = decide("Counterparty: Kestrel Bay Shipping Company Ltd. Party type: entity.\nRegistered 2011, company number 448190, Belize. Role in the payment: beneficiary.") print(decision.value, decision.confidence)
Use when
- You have candidate watchlist entries and need to assess each customer-entry pair.
- You need to distinguish definite matches from cases that require further information and human review.
Avoid when
- You need to search an entire watchlist; retrieve candidate entries first.
- You need a final decision without human review; screening decisions have legal consequences.
- You plan commercial use; the adapter is licensed CC BY-NC 4.0 (non-commercial use only), because its training data includes data licensed for non-commercial use only.
Context and input
| Field | Kind | Description |
|---|---|---|
customer_record | input | The customer, or a party named in a payment, as text: name, party type, date of birth, nationality and other details the bank holds (some may be "not recorded"). |
watch_list_entry | context | One sanctions or watch-list entry, as text: the listed name and aliases, type (person or entity), date of birth or registration, countries and the lists it is on. |
Functions
| Key | Interface | Instructions | Labels |
|---|---|---|---|
| screening | equivalent | A bank checks each customer, or each party named in a payment, against one entry from a sanctions list or another watch list. Is the customer the party on the list? Names agree when the customer's name is the listed name or one of its aliases, allowing for other spellings or transliterations, a different order of the names, initials, a missing middle name and small typing mistakes. The deciding detail is the date of birth for a person, the country of registration for a company or organisation, and the IMO number for a ship. A year of birth alone cannot confirm a person, but a different year rules them out. A different kind of party, such as a ship instead of a person, is never the listed party. Nationality, occupation and the other details do not decide. | match, possible_match, no_match |
How it was measured
Test accuracy: the share of test rows whose top answer was right.
- 100.0% on the held-out test (4,909 rows). test-set kind not recorded
When confident
From the calibration set: at or above the threshold confidence, how often the answer is right, and how often the adapter is that confident. Below it, escalate.
| Function | Right when confident | Confident on | Threshold | Calibration rows |
|---|---|---|---|---|
| screening | 99.8% | 100.0% | 0.95 | 1,012 |
Base: Jeff v1.4. Adapter trained: 25 October 2026.
Base
jeff-base v1.4
Call it
jeff.compliance.sanctions.screening, with placeholders for its input and context.
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.compliance.sanctions.screening", context={ "watch_list_entry": "<watch_list_entry>", }) decision = decide("<customer_record>") print(decision.value, decision.confidence)
Download
Weights: mstrasser/jeff-adapter-sanctions (v1.4)
Licence: CC-BY-NC-4.0