sumsub-create-aml-resolution-rules

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sumsub — Create AML Resolution Rules

Sumsub — 创建AML决议规则

Builds AML resolution rules from a compact spec, upserts them into the tenant's draft AML rule chain via the agent API, and (optionally) publishes the draft to make it live. The chain (also called the AML Resolution Rule Chain) auto-reviews incoming AML screening hits: each rule, in order, is evaluated against every not-yet-reviewed hit, and on match sets the hit's review (match status / risk level / whitelisted / note) and/or tags the case.
Every network step goes through one signed client,
${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py
(
draft
,
published
,
archive
,
library
,
upsert
,
reorder
,
delete
,
publish
); rule payloads are assembled by
${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py
.
根据精简规范构建AML决议规则,通过Agent API将其插入到租户的draft(草稿)AML规则链中,并可选择发布草稿使其生效。该规则链(也称为AML决议规则链)会自动审核传入的AML筛查命中结果:每条规则按顺序针对所有尚未审核的命中结果进行评估,匹配时会设置命中结果的审核状态(匹配状态/风险等级/白名单/备注)和/或标记案例。
所有网络步骤均通过一个签名客户端完成,即
${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py
(包含
draft
published
archive
library
upsert
reorder
delete
publish
子命令);规则负载由
${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py
组装。

Endpoints

端点

All under
/resources/api/agent/amlResolutionRules
. There is one rule chain per tenant, versioned as
draft → published → archived
revisions. (Each row maps to an
aml_rules_api.py
subcommand — you never call these paths by hand.)
MethodPathSubcommandWhen
GET
/draft
draft
Read the editable revision. Auto-creates a draft from the published revision (or empty) — never 404s for an enabled tenant. Carries
notices[]
.
GET
/published
published
Read the live revision (404 if nothing published yet).
GET
/archive
archive [marker]
Revision history, marker-paginated. Rate limit 5/min — don't poll.
GET
/library
library
Ready-made rule templates, grouped by category.
POST
/draft/rules
upsert
Upsert one rule: omit
id
to create (appended at the end of the chain), include an existing
id
to replace that rule. Response = full draft with recomputed
notices[]
.
PUT
/draft/rules/order
reorder
Reorder: body
{"ruleIds": [...]}
must list every rule id exactly once.
DELETE
/draft/rules/{id}
delete <id>
Remove one rule from the draft by id. Idempotent — deleting an id not in the draft still succeeds. See the consent policy below.
POST
/draft/publish
publish
Go live. Refused while any
error
-level notice exists. Previous published revision auto-archives.
Publishing via the API is for the integration phase. Once the integration is considered active, the API may refuse to publish (a
4xx
); the chain must then be reviewed and published by a human from the Sumsub web UI. Treat a publish refusal as expected at that stage, not an error to work around — report it and point the user to the web UI.
Token requirements beyond the usual: these are agent endpoints, so the App Token must be AI-purpose (created from the AI token page in the dashboard UI) and carry the
manageAmlCases
+
manageClientSettings
permissions. Symptoms of getting this wrong:
  • 403 "This endpoint is not allowed for this type of token"
    → the token is a regular App Token, not an AI one. Ask the user to mint an AI token.
  • 404 "API is not available"
    on every endpoint → the AML Resolution Rules API is not enabled for this tenant. Stop immediately — tell the user to contact their CSM or Sumsub support; do not retry other endpoints.
所有端点均位于
/resources/api/agent/amlResolutionRules
下。每个租户仅有一条规则链,版本分为
draft → published → archived
(草稿→已发布→已归档)修订版。(每行对应
aml_rules_api.py
的一个子命令——无需手动调用这些路径。)
方法路径子命令使用场景
GET
/draft
draft
读取可编辑的修订版。会自动从已发布修订版(或空版本)创建草稿——对于已启用的租户,永远不会返回404。返回结果包含
notices[]
GET
/published
published
读取生效的修订版(若尚未发布任何内容则返回404)。
GET
/archive
archive [marker]
修订历史,按标记分页。速率限制为5次/分钟——请勿轮询。
GET
/library
library
现成的规则模板,按类别分组。
POST
/draft/rules
upsert
插入或更新一条规则:省略
id
则创建新规则(追加到规则链末尾),包含现有
id
则替换该规则。响应为包含重新计算的
notices[]
的完整草稿。
PUT
/draft/rules/order
reorder
重新排序:请求体
{"ruleIds": [...]}
必须完整列出每一个规则ID,且每个ID仅出现一次。
DELETE
/draft/rules/{id}
delete <id>
通过ID从草稿中删除一条规则。幂等操作——删除草稿中不存在的ID仍会返回成功。请遵循下方的删除同意政策。
POST
/draft/publish
publish
发布生效。若存在任何
error
级别的通知,发布将被拒绝。之前的已发布修订版会自动归档。
通过API发布仅适用于集成阶段。 一旦集成被视为已激活,API可能会拒绝发布(返回
4xx
);此时必须由人工通过Sumsub网页UI审核并发布规则链。将发布拒绝视为该阶段的预期情况,而非需要解决的错误——向用户报告此情况并引导其使用网页UI。
除常规要求外,还需满足令牌要求:这些是Agent端点,因此App Token必须为AI用途(从仪表板UI的AI令牌页面创建),并具备
manageAmlCases
+
manageClientSettings
权限。令牌配置错误的症状:
  • 403 "This endpoint is not allowed for this type of token"
    → 该令牌是常规App Token,而非AI令牌。请用户生成AI令牌。
  • 所有端点均返回
    404 "API is not available"
    → 该租户未启用AML决议规则API。立即停止操作——告知用户联系其客户成功经理(CSM)或Sumsub支持团队;请勿重试其他端点。

⚠️ Publishing affects LIVE production

⚠️ 发布将影响生产环境

The AML Resolution Rule Chain is shared across live and sandbox — only the AML cases / applicants are isolated, not the chain itself. Publishing changes the chain that auto-reviews real production AML screening hits (clearing false positives, confirming true positives, whitelisting) — a sandbox
sbx:
token does not make this safe. Everything up to publish is safe: reading the draft, upserting, reordering, and deleting rules all touch only the draft, which reviews nothing until it's published.
So publish only on explicit user request, and know it can be refused by the backend: once the chain is active — too many applicants have already been processed / the integration is complete — the API rejects the publish (a
4xx
). That is expected, not an error to work around: report it and tell the user to publish from the Sumsub web UI (see the Endpoints note).
AML决议规则链在生产环境和沙箱环境中共享——仅AML案例/申请人是隔离的,规则链本身并非隔离状态。发布操作会更改自动审核真实生产环境AML筛查命中结果的规则链(清除误报、确认真阳性、添加白名单)——沙箱环境的
sbx:
令牌无法保证操作安全。发布之前的所有操作都是安全的:读取草稿、插入/更新、重新排序和删除规则仅涉及草稿,草稿在发布前不会审核任何内容。
因此,仅在用户明确请求时进行发布,并且需注意后端可能拒绝发布:一旦规则链激活(已有大量申请人被处理/集成已完成),API会拒绝发布请求(返回
4xx
)。这是预期情况,而非需要解决的错误:向用户报告此情况并引导其通过Sumsub网页UI发布(请参阅端点部分的说明)。

Auth — App Token + secret (sandbox only)

认证 — App Token + 密钥(仅沙箱环境)

This skill talks to the public Sumsub API and signs each request per the authentication reference. The full how-it-works writeup lives in the
sumsub-api-auth
skill — read it if you hit
401 Invalid signature
.
⚠️ Sandbox tokens only. Do not accept or use a production App Token here — these rules auto-review real AML hits. If the user offers a prod token, 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 — that page mints the AI token these endpoints require, see above). Token + secret are shown once — copy both before closing the dialog.
aml_rules_api.py
enforces this — it rejects tokens that don't start with
sbx:
.
VarExample
SUMSUB_APP_TOKEN
sbx:...
— sandbox AI 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.
本技能与公开的Sumsub API通信,并根据 认证参考文档对每个请求进行签名。 完整的工作原理说明位于
sumsub-api-auth
技能文档中——若遇到
401 Invalid signature
错误,请阅读该文档。
⚠️ 仅支持沙箱令牌。 请勿接受或使用生产环境的App Token ——这些规则会自动审核真实的AML命中结果。若用户提供生产环境令牌,请拒绝并要求其在以下地址生成沙箱令牌对: https://cockpit.sumsub.com/checkus/home?sbx=trueConnect Sumsub to your AI agent -> Build & configure -> Generate token — 该页面会生成这些端点所需的AI令牌,如上所述)。令牌和密钥仅显示一次——关闭对话框前请复制两者。
aml_rules_api.py
会强制执行此限制——它会拒绝不以
sbx:
开头的令牌。
变量示例
SUMSUB_APP_TOKEN
sbx:...
— 来自仪表板的沙箱AI App Token。
SUMSUB_SECRET_KEY
创建令牌时显示的配对密钥,仅显示一次。
SUMSUB_BASE
可选参数,默认值为
https://api.sumsub.com
若用户已在对话中提供凭证,请复用;否则在运行前询问一次。切勿回显密钥。

How the chain executes (keep this in mind while designing rules)

规则链执行逻辑(设计规则时请牢记)

  1. Rules run top to bottom — order matters.
  2. Each rule is evaluated against every hit that is not yet reviewed. A hit that gets a
    matchStatus
    (from moderation or an earlier rule) is skipped by later rules.
  3. Effects are visible mid-run: tags and recomputed
    screening.answer
    /
    screening.tags
    /
    screening.matchStatuses
    from earlier rules are seen by later ones — this enables chaining (rule A tags
    match_tin
    , rule B reacts to
    screening.tags containsAny ["match_tin"]
    ).
  4. Put specific, decisive rules (ID matches, previous-review carry-over) before broad clean-up rules — a broad
    false_positive
    rule placed first steals hits from preciser rules below it.
  1. 规则从上到下执行——顺序至关重要。
  2. 每条规则针对所有尚未审核的命中结果进行评估。已获得
    matchStatus
    (来自人工审核或更早规则)的命中结果会被后续规则跳过。
  3. 效果在执行过程中即可见:早期规则添加的标签以及重新计算的
    screening.answer
    /
    screening.tags
    /
    screening.matchStatuses
    会被后续规则读取——这支持规则链式调用(规则A标记
    match_tin
    ,规则B响应
    screening.tags containsAny ["match_tin"]
    )。
  4. 将具体、明确的规则(ID匹配、沿用之前的审核结果)放在宽泛的清理规则之前——若宽泛的
    false_positive
    规则放在首位,会抢占下方更精确规则的命中结果。

Precondition: AML screening must actually be running

前提条件:必须已启用AML筛查

This chain acts only on hits produced by AML screening. If screening isn't running, the rules are inert — they evaluate against nothing. Two independent gates decide whether screening runs on a given applicant level:
  1. Tenant entitlement
    WATCHLISTS
    — all-or-nothing, tenant-wide. Verify it by invoking the
    sumsub-check-permissions
    skill.
    WATCHLISTS
    present → AML screening is available and on by default on every level.
    WATCHLISTS
    absent → AML screening is off for the entire tenant; no applicant-level setting can turn it on, and this rule chain will never see a hit.
  2. Per-level opt-out
    disableWatchlists
    — only relevant once gate 1 passes. Screening runs on a level unless that level sets the top-level
    disableWatchlists: true
    (how a client carves out levels that shouldn't be screened). This is the
    sumsub-create-level
    skill's concern, not this one.
WATCHLISTS
entitlement
Level
disableWatchlists
Screening runs on that level?Chain acts on its hits?
absent(any)No — off tenant-wideNo
presentabsent /
false
Yes (default)Yes
present
true
No — level opted outNo
The chain is one per tenant and acts on hits from every level where screening runs — it is not scoped to a level. So confirm gate 1 before building rules (step 0). If
WATCHLISTS
is missing, anything you write here stays dormant until the entitlement is enabled.
该规则链仅对AML筛查产生的命中结果生效。若未启用筛查,规则将无效——无任何评估对象。有两个独立的控制项决定是否对特定申请人层级运行筛查:
  1. 租户权限
    WATCHLISTS
    ——全局生效,要么全部启用要么全部禁用。请调用
    sumsub-check-permissions
    技能进行验证。若存在
    WATCHLISTS
    权限→AML筛查可用,且默认对所有层级启用。若不存在
    WATCHLISTS
    权限→AML筛查对整个租户禁用;无法通过申请人层级设置启用,此规则链永远不会处理任何命中结果
  2. 层级级别的退出选项
    disableWatchlists
    ——仅当第一个控制项通过时才相关。除非该层级设置了顶层
    disableWatchlists: true
    (客户用于排除不需要筛查的层级),否则会对该层级运行筛查。这属于
    sumsub-create-level
    技能的范畴,与本技能无关。
WATCHLISTS
权限
层级
disableWatchlists
是否对该层级运行筛查?规则链是否处理其命中结果?
不存在任意值——全局禁用
存在不存在/
false
(默认)
存在
true
——层级已退出
规则链每个租户仅有一条,并对所有启用筛查的层级的命中结果生效——并非针对单个层级。因此,在构建规则前请确认第一个控制项(步骤0)。若
WATCHLISTS
权限缺失,此处编写的所有规则将处于休眠状态,直到权限被启用。

Tags bridge into applicant workflows

标签可对接申请人工作流

Rule tags are common applicant tags — tenant-wide, not AML-only. They don't just chain within the AML run: they also surface in applicant workflow conditions as
checks.personWatchlist.tags
(individuals) and
checks.companyWatchlist.tags
(companies). That makes a tag the hand-off point between the rule chain and a workflow: the rule chain flags a nuanced situation, the workflow routes on it. Example:
  1. AML rule — condition "the hit carries the
    pep
    risk label and the applicant is under 30", tags action
    ["youngPep"]
    .
  2. Workflow edge — a
    condition
    testing that
    checks.personWatchlist.tags
    contains
    youngPep
    → a manual-review node.
Both skills author the same Condition AST (see below), so the two halves read alike. When the user's goal includes routing or actions downstream of screening, set the tag here and point them to
sumsub-create-workflow
for the routing half.
规则标签是通用申请人标签——全局生效,并非仅适用于AML。它们不仅可在AML规则链内链式调用,还会作为
checks.personWatchlist.tags
(个人)和
checks.companyWatchlist.tags
(企业)出现在申请人工作流条件中。这使得标签成为规则链与工作流之间的交接点:规则链标记特殊情况,工作流根据标签进行路由。示例:
  1. AML规则——条件为“命中结果带有
    pep
    风险标签且申请人年龄小于30岁”,标记操作添加
    ["youngPep"]
  2. 工作流分支——条件检查
    checks.personWatchlist.tags
    是否包含
    youngPep
    →跳转至人工审核节点。
两个技能使用相同的Condition AST(如下所示),因此两者的条件语法一致。若用户的目标包含筛查后的路由或操作,请在此处设置标签,并引导其使用
sumsub-create-workflow
技能完成路由部分。

Procedure

操作流程

  1. Confirm AML screening is enabled for the tenant (see Precondition). Invoke the
    sumsub-check-permissions
    skill and verify
    WATCHLISTS
    is among the tenant's allowed entitlements. If it's absent, AML screening is off tenant-wide, so this rule chain will never fire: tell the user plainly (the entitlement is enabled by their CSM / Sumsub support), and get explicit confirmation before proceeding — do not silently build a chain that does nothing. If present, proceed.
  2. Read the draft:
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py draft
    . This is also the availability check — on
    404 "API is not available"
    or
    403
    , stop and report (see Endpoints above). Review the existing rules: if a rule with the same intent already exists, offer to update it by
    id
    instead of appending a duplicate — upsert has no name deduplication. Note which rule ids exist before you make changes — you'll need that to honor the delete consent policy.
  3. Check the library first:
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py library
    . If a ready-made template matches the user's intent, start from its
    rule
    definition — strip the
    id
    , adjust, and continue. Check the template's
    vendors
    list against the AML vendor the tenant uses.
  4. Write the rule spec (below). Author the
    condition
    as the real Condition AST, directly — there is no expression mini-language (see Authoring conditions). Scope the rule to an entity type with an
    input.entityType
    criterion
    (default individual — see Authoring conditions). Verify every
    exp
    path against references/aml-rules-context-fields.md, and any enum-backed field's allowed values against references/aml-rules-enumerations.md — unknown paths produce
    unknownField
    error notices that block publishing.
  5. Assemble the rule payload with
    ${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py
    — compact spec on stdin → full rule JSON on stdout. The builder is a thin assembler: it passes the
    condition
    AST through, assembles the review/tags actions, validates operators / the
    matchStatus
    enum / the emptyAction guard, and errors here (before any network call) on a typo or a malformed AST.
  6. Show the resolved payload to the user and get explicit confirmation before the first upsert. If the rule's
    tags
    action introduces a tag that doesn't exist yet, call that out explicitly: upserting will create it as a tenant-wide applicant tag (visible in dashboard filters, workflows, everywhere) — confirm the name is one worth keeping (clear, concise, reusable) or reuse an existing tag instead.
  7. Upsert via
    ${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py < spec.json | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py upsert
    → response is the full draft with recomputed
    notices[]
    . Repeat steps 3–6 for each rule when creating several. Record the id the server assigns each rule you create — that's how you know it's yours (step 9).
  8. Inspect
    notices
    .
    error
    notices (e.g.
    invalidTag
    ,
    unknownField
    ,
    unknownFunction
    ) block publishing — fix the rule and re-upsert with its
    id
    .
    warning
    /
    info
    are advisory; surface them. See the notice key table in references/aml-resolution-rules-schema.md.
  9. Order the chain. New rules land at the end. If the evaluation order needs changing, pass the full permutation:
    echo '{"ruleIds": [...]}' | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py reorder
    .
  10. Delete rules — only per the consent policy below.
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py delete <ruleId>
    .
  11. Publish only on explicit request (see the "Publishing affects LIVE production" note):
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py publish
    . Publishing makes the chain live against real AML hits across live and sandbox — never publish without the user asking; until then the draft is dormant. The backend may refuse the publish once the chain is active (too many applicants already processed / integration complete) — a
    4xx
    . That's expected: report it and direct the user to publish from the Sumsub web UI (see the Endpoints note).
  12. Report (lead with rule names, never bare ids):
  1. 确认租户已启用AML筛查(请参阅前提条件)。调用
    sumsub-check-permissions
    技能,验证租户的允许权限中包含
    WATCHLISTS
    。若权限缺失,则AML筛查全局禁用,此规则链永远不会触发:明确告知用户(该权限由其CSM/Sumsub支持团队启用),并在继续操作前获得用户明确确认——切勿静默构建无效的规则链。若权限存在,则继续操作。
  2. 读取草稿
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py draft
    。这也是可用性检查——若返回
    404 "API is not available"
    403
    ,则停止操作并报告(请参阅上方端点部分的说明)。查看现有规则:若存在意图相同的规则,建议通过
    id
    更新该规则而非追加重复规则——插入/更新操作不会根据名称去重。记录进行更改前已存在的规则ID——后续需要这些ID来遵守删除同意政策。
  3. 先查看规则库
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py library
    。若存在符合用户意图的现成模板,请从其
    rule
    定义开始——移除
    id
    ,进行调整后继续。检查模板的
    vendors
    列表与租户使用的AML供应商是否匹配。
  4. 编写规则规范(如下所示)。直接以真实的Condition AST编写
    condition
    ——不存在表达式迷你语言(请参阅条件编写部分)。通过
    input.entityType
    条件将规则限定为特定实体类型
    (默认个人——请参阅条件编写部分)。请对照references/aml-rules-context-fields.md验证每个
    exp
    路径,并对照references/aml-rules-enumerations.md验证任何枚举字段的允许值——未知路径会产生
    unknownField
    错误通知,阻止发布。
  5. 使用
    ${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py
    组装规则负载
    ——标准输入为精简规范,标准输出为完整的规则JSON。该构建工具是一个轻量组装器:它会传递
    condition
    AST,组装审核/标记操作,验证运算符/
    matchStatus
    枚举/
    emptyAction
    防护,若存在拼写错误或格式错误的AST,会在此处(网络调用前)报错。
  6. 向用户展示解析后的负载并获得明确确认后,再进行首次插入/更新操作。若规则的
    tags
    操作引入了尚未存在的标签,请明确告知用户:插入/更新操作会自动创建该标签作为全局申请人标签(在仪表板过滤器、工作流等所有位置可见)——请确认标签名称是否清晰、简洁、可复用,或改用现有标签。
  7. 插入/更新:通过
    ${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py < spec.json | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py upsert
    → 响应为包含重新计算的
    notices[]
    完整草稿。创建多条规则时,请重复步骤3–6。记录服务器为每条新创建规则分配的ID——后续可通过这些ID识别自己创建的规则(步骤9)。
  8. 检查
    notices
    error
    级别的通知(如
    invalidTag
    unknownField
    unknownFunction
    )会阻止发布——修复规则并通过其
    id
    重新插入/更新。
    warning
    /
    info
    级别的通知为建议性内容,请向用户展示。请参阅references/aml-resolution-rules-schema.md中的通知键表。
  9. 排序规则链。新规则会添加到末尾。若需要更改评估顺序,请传递完整的规则ID排列:
    echo '{"ruleIds": [...]}' | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py reorder
  10. 删除规则——仅遵循下方的删除同意政策
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py delete <ruleId>
  11. 仅在用户明确请求时发布(请参阅“发布将影响生产环境”部分的说明):
    ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py publish
    。发布后,规则链会针对生产环境和沙箱环境中的真实AML命中结果生效——切勿在用户未请求时发布;发布前草稿处于休眠状态。一旦规则链激活(已有大量申请人被处理/集成已完成),后端可能会拒绝发布(返回
    4xx
    )。这是预期情况:向用户报告此情况并引导其通过Sumsub网页UI发布(请参阅端点部分的说明)。
  12. 报告结果(优先显示规则名称,而非原始ID):

Deleting rules — consent policy

删除规则——同意政策

The
delete
subcommand removes a rule from the draft permanently (it's archived with the revision, but gone from the editable chain). Apply this gate:
  • A rule you created in this session — delete it freely when it was a mistake, the user asked you to replace it, or you're iterating on your own work. (Updating in place by
    id
    is usually better than delete-then-recreate, because it preserves the rule's position; reach for delete when the rule should genuinely go away.)
  • Any rule you did not create — a pre-existing rule, one from an earlier session, or one a human authored — delete only with explicit user consent for that specific rule. Name the rule (by its
    name
    ) and confirm before deleting. Never delete someone else's rule as a side effect of "cleaning up" or "rebuilding" the chain.
  • When unsure whether a rule is yours, treat it as not yours and ask.
Deleting is idempotent and returns the full draft with recomputed
notices[]
— re-inspect them afterward (removing a rule can change which tags/fields the remaining rules still justify).
delete
子命令会永久从草稿中删除规则(规则会随修订版归档,但会从可编辑规则链中移除)。请遵循以下限制:
  • 本次会话中创建的规则——若规则存在错误、用户要求替换,或正在迭代自己的工作内容,可自由删除。(通常通过
    id
    原地更新比删除后重新创建更好,因为这样可以保留规则的位置;仅当规则确实需要移除时才使用删除操作。)
  • 非本次会话创建的规则——预先存在的规则、之前会话创建的规则,或人工编写的规则——仅在获得用户针对该特定规则的明确同意后才能删除。请告知用户规则名称(通过其
    name
    )并确认后再删除。切勿将删除他人规则作为“清理”或“重建”规则链的副作用。
  • 若不确定规则是否为自己创建,请视为非自己创建的规则并询问用户。
删除操作是幂等的,返回包含重新计算的
notices[]
的完整草稿——删除后请重新检查通知(移除规则可能会改变剩余规则仍需使用的标签/字段)。

Rule spec format (JSON on stdin)

规则规范格式(标准输入为JSON)

jsonc
{
  "name": "Auto-clear hits with incompatible date of birth",   // required
  "description": "Optional free-form description",
  "id": "existing-rule-id",            // only when updating an existing rule

  // condition — the real Sumsub Condition AST, authored directly (see below).
  "condition": {
    "or": [
      { "and": [
        { "op": "ne",   "args": [ { "exp": "input.entityType" }, { "lit": "\"company\"" } ] },   // individual-only — scope every rule (see Authoring conditions)
        { "op": "eq",   "args": [ { "exp": "screening.vendor" }, { "lit": "\"complyAdvantageCSOM\"" } ] },
        { "op": "eq",   "args": [ { "exp": "match.dobs.hasData" }, { "lit": "true" } ] },
        { "op": "call", "args": [ { "exp": "dobsIncompatible" }, { "exp": "match.dobs" }, { "exp": "input.dob" }, { "lit": "\"weakContainment\"" } ] }
      ] }
    ]
  },

  // Review action — what to set on matched hits (every field optional):
  "review": {
    "matchStatus": "false_positive",   // unknown | potential_match | false_positive | true_positive
    "riskLevel": "LOW",                // vendor-specific — omit when unsure
    "whitelisted": true,               // accept the risk: allows approval despite the hit
    "note": "Cleared automatically: DoB mismatch"
    // OR the whole-review form (replaces all per-field keys):
    // "expression": "match.previousReview"   // carry over the previous screening's decision
  },

  // Tags added to the AML case when the rule matches. These are common applicant
  // tags (tenant-wide, usable everywhere — not AML-only). A tag that doesn't exist
  // yet is created automatically on upsert: prefer reusing an existing tag, and
  // name new ones clearly and concisely (e.g. "youngPep", not "rule3_tag"):
  "tags": ["auto_cleared_dob"]
}
A rule needs
review
and/or
tags
— neither yields an
emptyAction
error notice. Review fields take a scalar (the builder JSON-encodes it into a
{lit}
) or an explicit
{"exp": "..."}
/
{"lit": "..."}
to compute or supply the value directly.
jsonc
{
  "name": "Auto-clear hits with incompatible date of birth",   // 必填
  "description": "Optional free-form description",
  "id": "existing-rule-id",            // 仅在更新现有规则时填写

  // condition — 直接编写真实的Sumsub Condition AST(如下所示)。
  "condition": {
    "or": [
      { "and": [
        { "op": "ne",   "args": [ { "exp": "input.entityType" }, { "lit": "\"company\"" } ] },   // 仅适用于个人——请为每条规则限定范围(请参阅条件编写部分)
        { "op": "eq",   "args": [ { "exp": "screening.vendor" }, { "lit": "\"complyAdvantageCSOM\"" } ] },
        { "op": "eq",   "args": [ { "exp": "match.dobs.hasData" }, { "lit": "true" } ] },
        { "op": "call", "args": [ { "exp": "dobsIncompatible" }, { "exp": "match.dobs" }, { "exp": "input.dob" }, { "lit": "\"weakContainment\"" } ] }
      ] }
    ]
  },

  // 审核操作——匹配命中结果时设置的内容(所有字段均为可选):
  "review": {
    "matchStatus": "false_positive",   // unknown | potential_match | false_positive | true_positive
    "riskLevel": "LOW",                // 供应商特定——不确定时请省略
    "whitelisted": true,               // 接受风险:允许忽略命中结果进行审批
    "note": "Cleared automatically: DoB mismatch"
    // 或完整审核表单格式(替换所有单个字段键):
    // "expression": "match.previousReview"   // 沿用之前筛查的决策
  },

  // 规则匹配时添加到AML案例的标签。这些是通用申请人
  // 标签(全局生效,可在所有位置使用——并非仅适用于AML)。若标签尚未存在,
  // 插入/更新操作会自动创建:优先使用现有标签,新标签名称请保持清晰简洁(例如"youngPep",而非"rule3_tag"):
  "tags": ["auto_cleared_dob"]
}
规则需要包含
review
和/或
tags
——两者均不提供会产生
emptyAction
错误通知。审核字段可接受标量值(构建工具会将其JSON编码为
{lit}
),或显式的
{"exp": "..."}
/
{"lit": "..."}
来直接计算或提供值。

Authoring conditions

条件编写

A rule's
condition
is the real Sumsub Condition AST, written directly — the same shape and rules as workflow edge conditions, so the two skills stay aligned. There is no expression mini-language (the old
condition: "screening.vendor = …"
string and
conditionRaw
key were removed; the builder rejects both with a pointer here).
⚠️ Scope every rule to an entity type. Individual and company matches expose different fields and read differently, so a rule built for one can misfire on the other. Each rule MUST carry an
input.entityType
criterion
— infer the target from the rule's intent (person name / DoB / PEP signals → individual; company name / KYB signals → company), and default to individual when unsure:
  • Individual (the usual case):
    { "op": "ne", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] }
    — entityType ≠ company.
  • Company / organization:
    { "op": "eq", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] }
    .
Omit it only for a deliberately entity-agnostic rule (rare — e.g. "whitelist every
sanctions
hit from country X"). Most library templates already carry this criterion — keep it when you adapt one.
jsonc
{
  "or": [                                  // OR of AND-groups; first matching branch wins
    { "and": [
      { "op": "eq", "args": [ {"exp": "screening.vendor"}, {"lit": "\"complyAdvantageCSOM\""} ] },
      { "op": "in", "args": [ {"exp": "input.country"},    {"lit": "[\"BRA\", \"ARG\"]"} ] }
    ] }
  ]
}
  • {exp: "<path>"}
    — an expression path, verbatim (from references/aml-rules-context-fields.md). It's the left side of a comparison, and also the right side for field-to-field checks (
    {exp: "match.analysis.parentName"}
    ).
  • {lit: "<json>"}
    — a literal, supplied already JSON-encoded as a string (the form the API stores):
    "\"complyAdvantageCSOM\""
    ,
    "2"
    ,
    "true"
    ,
    "[\"pep\", \"sanctions\"]"
    . An un-encoded literal (
    {lit: "BRA"}
    ) is rejected by the API, so the encoding is required.
  • op
    is one of the comparison operators (
    eq ne lt lte gt gte in notIn contains notContains containsAny notContainsAny containsAll containsOnly startsWith endsWith match empty notEmpty eqIgnoreCase …
    ; full set in references/aml-resolution-rules-schema.md). The builder validates every
    op
    against its known set.
  • Set membership on list fields (
    match.riskLabels
    ,
    screening.tags
    ,
    match.complyAdvantage.matchTypes
    ):
    contains
    /
    containsAny
    = has the value(s);
    containsAll
    = has all of;
    containsOnly
    = has nothing but the listed values
    . To match "only label X" (e.g. adverse-media-only hits) use
    containsOnly ["X"]
    never
    notContainsAny [the-other-labels]
    , which leaks because it silently assumes you enumerated the whole closed vocabulary (the risk-label set is exactly six — see references/aml-rules-enumerations.md).
  • call
    invokes a built-in function — the one operator AML conditions have that workflows don't. The first arg is the function name as
    {exp: "namesIncompatible"}
    , the rest are its arguments:
    {op: "call", args: [{exp: "dobsIncompatible"}, {exp: "match.dobs"}, {exp: "input.dob"}, {lit: "\"strict\""}]}
    . Functions and their signatures: references/aml-resolution-rules-schema.md.
  • Negation is expressed with the
    not*
    operators (
    notIn
    ,
    notContains
    ,
    notContainsAny
    ,
    ne
    ,
    notEmpty
    , …) — do not set a
    negate
    flag; a top-level
    condition.negate
    is rejected (UI-unsupported), matching the workflow skill.
  • Dates: any
    Date
    field (
    input.dob
    ,
    match.previousReview.modifiedAt
    ,
    match.sources.latestEndDate
    ) exposes
    .ageInDays
    /
    .ageInYears
    /
    .year
    etc. — e.g.
    {op: "lt", args: [{exp: "match.previousReview.modifiedAt.ageInYears"}, {lit: "2"}]}
    .
The full
Condition
/
And
/
Criterion
AST, literal-encoding rules, operator list, and built-in function signatures live in references/aml-resolution-rules-schema.md; valid
exp
paths are in references/aml-rules-context-fields.md and enum-field values in references/aml-rules-enumerations.md (both indexed by references/aml-rules-expressions.md).
规则的
condition
直接编写的真实Sumsub Condition AST——与工作流分支条件的结构和规则完全相同,因此两个技能保持一致。不存在表达式迷你语言(旧版的
condition: "screening.vendor = …"
字符串和
conditionRaw
键已被移除;构建工具会拒绝这两种格式并指向此处)。
⚠️ 请为每条规则限定实体类型。 个人和企业匹配结果暴露的字段不同,读取方式也不同,因此为一种实体类型构建的规则可能会在另一种实体类型上误触发。每条规则必须包含
input.entityType
条件
——根据规则意图推断目标实体类型(人名/出生日期/PEP信号→个人;企业名称/KYB信号→企业),不确定时默认选择个人
  • 个人(常见情况):
    { "op": "ne", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] }
    ——实体类型≠企业。
  • 企业/组织:
    { "op": "eq", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] }
仅当规则故意设计为与实体类型无关时(罕见情况——例如“将来自X国的所有
sanctions
命中结果加入白名单”),才可省略该条件。大多数规则库模板已包含此条件——调整模板时请保留该条件。
jsonc
{
  "or": [                                  // AND组的OR逻辑;第一个匹配的分支生效
    { "and": [
      { "op": "eq", "args": [ {"exp": "screening.vendor"}, {"lit": "\"complyAdvantageCSOM\""} ] },
      { "op": "in", "args": [ {"exp": "input.country"},    {"lit": "[\"BRA\", \"ARG\"]"} ] }
    ] }
  ]
}
  • {exp: "<path>"}
    ——表达式路径,与references/aml-rules-context-fields.md中的内容完全一致。它是比较的左侧,也可作为字段间比较的右侧(例如
    {exp: "match.analysis.parentName"}
    )。
  • {lit: "<json>"}
    ——字面量,需以已JSON编码的字符串形式提供(API存储的格式):
    "\"complyAdvantageCSOM\""
    "2"
    "true"
    "[\"pep\", \"sanctions\"]"
    。未编码的字面量(例如
    {lit: "BRA"}
    )会被API拒绝,因此必须进行编码。
  • **
    op
    **为比较运算符之一(
    eq ne lt lte gt gte in notIn contains notContains containsAny notContainsAny containsAll containsOnly startsWith endsWith match empty notEmpty eqIgnoreCase …
    ;完整列表请参阅references/aml-resolution-rules-schema.md)。构建工具会验证每个
    op
    是否属于已知集合。
  • 列表字段的集合成员检查
    match.riskLabels
    screening.tags
    match.complyAdvantage.matchTypes
    ):
    contains
    /
    containsAny
    = 包含指定值;
    containsAll
    = 包含所有指定值;
    containsOnly
    = 仅包含列出的值
    。若要匹配“包含标签X”(例如仅包含负面媒体的命中结果),请使用
    containsOnly ["X"]
    ——切勿使用
    notContainsAny [其他标签]
    ,因为这种方式会假设你已枚举了所有可能的标签(风险标签集合仅有6个——请参阅references/aml-rules-enumerations.md)。
  • **
    call
    **用于调用内置函数——这是AML条件具备但工作流条件不具备的唯一运算符。第一个参数为函数名称,格式为
    {exp: "namesIncompatible"}
    ,其余参数为函数的参数:
    {op: "call", args: [{exp: "dobsIncompatible"}, {exp: "match.dobs"}, {exp: "input.dob"}, {lit: "\"strict\""}]}
    。函数及其签名请参阅references/aml-resolution-rules-schema.md
  • 否定通过
    not*
    运算符表达(
    notIn
    notContains
    notContainsAny
    ne
    notEmpty
    等)——请勿设置
    negate
    标志;顶层
    condition.negate
    会被拒绝(不支持UI),与工作流技能保持一致。
  • 日期:任何
    Date
    字段(
    input.dob
    match.previousReview.modifiedAt
    match.sources.latestEndDate
    )都支持
    .ageInDays
    /
    .ageInYears
    /
    .year
    等属性——例如
    {op: "lt", args: [{exp: "match.previousReview.modifiedAt.ageInYears"}, {lit: "2"}]}
完整的
Condition
/
And
/
Criterion
AST、字面量编码规则、运算符列表、内置函数签名请参阅references/aml-resolution-rules-schema.md;有效的
exp
路径请参阅references/aml-rules-context-fields.md;枚举字段的值请参阅references/aml-rules-enumerations.md(三者均由references/aml-rules-expressions.md索引)。

Worked examples

示例

  • examples/minimal.json
    — tag-only rule (
    containsOnly
    on risk labels).
  • examples/auto-clear-dob-mismatch.json
    call
    functions + vendor match types; the most common auto-clear topology.
  • examples/reuse-previous-review.json
    — whole-review
    expression
    form carrying over a previous decision, with a date-age condition. Also the rare entity-agnostic rule (carrying a prior decision reads the same for individuals and companies) — the one case that needs no
    input.entityType
    filter.
  • examples/minimal.json
    ——仅包含标记的规则(对风险标签使用
    containsOnly
    )。
  • examples/auto-clear-dob-mismatch.json
    ——
    call
    函数+供应商匹配类型;最常见的自动清除规则结构。
  • examples/reuse-previous-review.json
    ——完整审核
    expression
    格式,沿用之前的决策,并包含日期年龄条件。这也是罕见的与实体类型无关的规则(沿用之前的决策对个人和企业的逻辑相同)——唯一无需
    input.entityType
    过滤的情况。

See also

另请参阅

  • references/aml-resolution-rules-schema.md — endpoints with rate limits, every field and enum, condition AST shape, operator list, built-in function signatures, notice message keys, execution model.
  • references/aml-rules-expressions.md — expression-reference index + preamble (root variables,
    applicant
    /
    Date
    shapes, the enum caveat). Points to the two data files below; all three are lookup databases, don't read end-to-end.
  • references/aml-rules-context-fields.md — every legal
    exp
    path with its type (
    ## Types
    /
    ## Index
    /
    ## Functions
    ).
  • references/aml-rules-enumerations.md — allowed values for the closed-enum fields (risk labels, match statuses, PEP institution kinds, match types, …).
  • sumsub-create-workflow
    — authors the same Condition AST in workflow edge conditions; its expressions reference covers the
    applicant
    /
    applicantIdDoc
    shapes.
  • references/aml-resolution-rules-schema.md——包含速率限制的端点、所有字段和枚举、条件AST结构、运算符列表、内置函数签名、通知消息键、执行模型。
  • references/aml-rules-expressions.md——表达式参考索引+前言(根变量、
    applicant
    /
    Date
    结构、枚举注意事项)。指向下方两个数据文件;三者均为查询数据库,无需逐行阅读。
  • references/aml-rules-context-fields.md——所有合法的
    exp
    路径及其类型(
    ## Types
    /
    ## Index
    /
    ## Functions
    )。
  • references/aml-rules-enumerations.md——枚举字段的允许(风险标签、匹配状态、PEP机构类型、匹配类型等)。
  • sumsub-create-workflow
    ——在工作流分支条件中使用相同的Condition AST;其表达式参考部分涵盖
    applicant
    /
    applicantIdDoc
    结构。