sumsub-create-kyt-rules
Configure KYT transaction monitoring rules with tags, applicant risk scoring and risk levels. TRIGGER when the user says "create / add / set up KYT rules / TM rules", "configure transaction monitoring", describes scoring logic (flag/block/hold transactions by amount, country, direction, peer, or oth
By sumsub · 651 installs
npx skills add sumsub/agent-skills --skill sumsub-create-kyt-rules
Source repository · Upstream listing
Sumsub — KYT Rules, Applicant Scoring & Risk Levels
Configures the full KYT transaction monitoring stack:
Rules — translates user intent into KytTxnRule payloads and POSTs them one at a time. Supports creating new rules and modifying existing ones (by posting a new revision). New rules always start in testMode ( dryRun: true ) — they appear in dryScore but do not affect the live outcome until activated in the dashboard.
Tags & applicant scoring — creates and configures tags (named risk markers) and the assessment that maps tag weights into a composite applicant risk score.
Risk levels — configures the score thresholds that translate a numeric risk score into a human readable label (e.g. Low / Med / High).
Rules, tags, and risk levels form a single pipeline: a rule fires → applies tags → tags accumulate a weighted score → score maps to a risk level.
Endpoints
Method Path Description Response
GET /resources/api/agent/tm/rules/ /installed List existing rules. Supports ?limit=<n and ?offset=<n . Requires seeKytRules . { list: { items: [...] } }
POST /resources/api/agent/tm/rules Create a new rule or a new revision. For creation omit id and name . For a revision include the existing name slug and "id": null . Requires manageKytRules . 200 rule object · 400 error message
GET /resources/api/agent/tm/rules/ /bundle/{bundleName}/{category} List rules in a bundle by name and installation status. category : installed , available , archived . Requires seeKytRules . { list: { items: [...] } }
GET /resources/api/agent/tm/rules/{id} Read one rule by id. Requires seeKytRules . rule object
GET /resources/api/agent/tm/settings/tags List all KYT tags with their assessment configuration and linked rules. { tags: [...] }
POST /resources/api/agent/tm/settings/tag Create or update a KYT tag. Body: {"tag": {"name": "...", "styleClass": "...", "color": " RRGGBBAA", "scorable": true, "includeInReporting": true, "scoreWeight": 1.0}} . color must be 8 digit hex. Requires manageKytSettings . 200 empty body
GET /resources/api/agent/tm/settings/applicantAssessment Get current applicant assessment scoring configuration (tag weights, hierarchy, company beneficiary weights). assessment settings object
PATCH /resources/api/agent/tm/settings/applicantAssessment Replace applicant assessment scoring configuration. Requires manageKytSettings . 200 updated assessment settings
GET /resources/api/agent/tm/settings/riskLevel Get current applicant risk level thresholds. risk level settings object
PATCH /resources/api/agent/tm/settings/riskLevel Replace risk level thresholds. Body: min 2 items, each with label (≤256), rangeFrom (≥0), styleClass — one of: grey , black , blue , green , cyan , teal , lime , yellow , orange , volcano , red , pink , fuchsia , purple , purpleLight . Requires manageKytSettings . 200 updated risk level settings
GET /resources/api/agent/tm/clientLists/{listName} Fetch a client list by name. 404 if not found. Requires seeClientLists . client list object
POST /resources/api/agent/tm/clientLists/{listName} Create a client list (idempotent). Requires manageClientLists . client list object
See [ references/kyt rule schema.md ](references/kyt rule schema.md) for the full rule SumScript expression field reference and type system.
Auth — App Token + secret (sandbox only)
This skill talks to the public Sumsub API and signs each request per
[the authentication reference](https://docs.sumsub.com/reference/authentication).
The full how it works writeup lives in the [ sumsub api auth ](../sumsub api auth/SKILL.md)
skill — read it if you hit 401 Invalid signature .
⚠️ Sandbox tokens only. Do not accept or use a production App Token
here. If the user offers one, refuse and ask them to generate a sandbox
pair at <https://cockpit.sumsub.com/checkus/home?sbx=true ( Connect
Sumsub to your AI agent Build & configure Generate token ).
Token + secret are shown once — copy both before closing the dialog. The helper script
enforces this — it rejects tokens that don't start with sbx: .
Var Example
SUMSUB APP TOKEN sbx:... — sandbox App Token from the dashboard.
SUMSUB SECRET KEY The paired secret shown once at token creation.
SUMSUB BASE Optional. Defaults to https://api.sumsub.com .
If the user has already supplied credentials in conversation, reuse them;
otherwise ask once before running. Never echo the secret back.
Tenant Entitlements
Entitlements are gated per transaction type , not globally. Each types value needs
any one of the keys listed for it — not all of them. There is no baseline entitlement
that every rule requires: KYT is the entitlement for the finance type, nothing more.
Rule types value Enabled by any one of
finance KYT
travelRule TRAVEL RULE
kyc TM INDIVIDUAL APPLICANT SCORING · TM COMPANY APPLICANT SCORING · KYT ANTI FRAUD · KYT · DEVICE INTELLIGENCE
userPlatformEvent KYT ANTI FRAUD · KYT
scheduledEvent TM SCHEDULED EVENTS · KYT
A tenant that has only TRAVEL RULE can create travelRule rules. A tenant that has only
DEVICE INTELLIGENCE can create kyc rules. Neither needs KYT . Do not require KYT for a
type whose row does not list it.
Before creating or modifying a rule, run bash scripts/check permissions.sh from the
[ sumsub check permissions ](../sumsub check permissions/SKILL.md) skill directory. The response
body is {"allowedChecks": {"<KEY ": "<description ", ...}} — the keys of allowedChecks
are the enabled entitlements. There is no allowed array.
Stop only when the requested type is not enabled — i.e. none of the keys on that type's row
appear in allowedChecks . Do not build or POST that rule. Name the type as the user sees it
(see [Transaction Types]( transaction types) — kyc is "Verification session events", never
"kyc"), list the keys that would enable it joined by "or", and tell the user to contact their CSM
or Sumsub support. Do not offer a
different transaction type as a workaround — if the user wants a travelRule rule, a finance
rule is not a substitute.
If the entitlement request itself fails (non 200, timeout), warn the user that entitlements
could not be verified and proceed anyway. The backend is the authority and enforces the same gate
on POST — see the No allowed transaction types found row in step 6.
Note on scheduled rules. The scheduled trigger mode is licensed by TM SCHEDULED EVENTS
specifically, while the scheduledEvent type is also enabled by KYT . A tenant with only
KYT may therefore pass this gate and still be refused by the backend on noEventTrigger .
Build the rule as usual and surface the backend error verbatim if that happens.
Procedure
0. Fetch tenant entitlements — only when creating or modifying a rule. Run
sumsub check permissions and keep the keys of allowedChecks . Once you know the rule's
types , check that row in [Tenant Entitlements]( tenant entitlements) and abort if none of
its keys are present.
Skip this step entirely for work that is not a rule: tags, applicant assessment, risk
levels, and client lists need no entitlement. Do not look for an entitlements endpoint other
than the one sumsub check permissions calls — there is no other one.
1. Determine mode — create or modify.
Modify mode: the user provides a rule name (immutable slug, e.g. fin ben pep ter list abo thr WoGD ) or enough context to identify one. Run bash ${CLAUDE SKILL DIR}/scripts/get kyt rules.sh , find the rule by name or title , and store the full current document. Show the user the existing conditionEl , score , action , and types , then collect only the fields they want to change. Skip to step 2a.
Create mode: the user describes a new rule. Run bash ${CLAUDE SKILL DIR}/scripts/get kyt rules.sh and check for a title collision — the server creates a duplicate on every POST with no deduplication. If a rule with a matching title already exists, offer to skip creation and modify the existing one instead.
2. Translate user intent to compact specs. For each rule the user wants to create, collect:
title (≤128 chars, required)
types — one or more transaction types (see table below)
A plain English description of the condition (used to generate conditionEl in step 3)
score (integer, default 0), action ( score onHold awaitUser reject )
Optional: desc , tags , bundleName , priority , stopOnMatch , sourceKeys
2a. Ensure client lists exist — if any rule will reference clientLists.<name in its conditionEl ,
verify each list exists before generating or validating expressions:
HTTP 200 → list exists; proceed.
HTTP 404 → list does not exist; create it:
The POST is idempotent — it succeeds even if the list was created in the meantime.
Do not proceed to validation or rule creation until every referenced client list is confirmed.
3. Generate conditionEl . For each rule that needs a condition:
Construct the SumScript boolean expression using the type definitions in
[ references/kyt rule schema.md ](references/kyt rule schema.md).
Do not guess field paths. Only use fields confirmed in the schema — verify the path
from root to leaf before writing the expression.
For default currency amount checks use data.info.amountInDefaultCurrency (normalized amount),
not data.info.amount (source currency amount) — unless the user explicitly asks for
source currency filtering.
Scheduled rules ( types: ["scheduledEvent"] ) do NOT use conditionEl for their trigger —
use noEventTrigger instead (see [references/kyt rule schema.md](references/kyt rule schema.md)).
For multi branch scoring (different score per sub condition), use addScoreIf inside
conditionEl and set the payload level score: 0 , action: "score" (see Scoring section).
3a. Validation is built into POST — the server validates conditionEl syntax during the create call (step 6). No separate pre flight step is needed. If validation fails the server returns HTTP 400 with an error message describing the problem — fix the expression and re POST.
4. Build payload. Assemble the JSON for each rule following these constraints:
Create mode:
Required fields only: title , types (min 1 value).
For eval rules: include conditionEl , score , and action when relevant.
Never send id or name — the server assigns both.
Modify mode (new revision):
Include "name": "<existing slug " — the immutable slug from the existing rule.
Include "id": null — an explicit null. This signals the server to create a new revision rather than a new rule. Do not use "id": "" (empty string) — Jackson will reject it as an invalid ObjectId and return HTTP 400.
Carry over all unchanged fields from the existing rule document. Only change the fields the user asked to modify.
title and types remain required.
Both modes — always apply:
Never send server assigned or audit fields: clientId , actual , revision ,
timestamps ( createdAt , modifiedAt , archivedAt ), author fields.
Never send scope or bgCheckTargets — license control fields managed by the server.
Create mode: never send dryRun or disabled ; the server initialises them to true and false .
Modify mode: carry over dryRun and disabled from the existing rule document — the server uses the sent values to preserve the rule's current activation and test mode state across the revision.
Omit empty optional co