mcpField
S
sumsub-create-aml-resolution-rules

sumsub-create-aml-resolution-rules

github.com/sumsub其他7491 次安装4 周前更新
代码仓库

关于 sumsub-create-aml-resolution-rules

为 Sumsub 配置 AML Resolution Rule Chain 的技能,可根据简要规格创建并更新草稿规则,也可按明确要求尝试发布。规则按顺序处理筛查命中,并能设置审核结果或标签。

主要功能

  1. 01读取草稿、已发布版本和规则模板
  2. 02创建、更新、排序或删除草稿规则
  3. 03检查规则提示并按条件发布
  4. 04以标签衔接申请人工作流

适用场景

  1. 01根据筛查策略编写 AML 自动审核规则
  2. 02用标签将筛查结果交给后续工作流路由

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sumsub/agent-skills --skill sumsub-create-aml-resolution-rules

安装后在 Claude Code 中输入/sumsub-create-aml-resolution-rules确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
auto-clear-dob-mismatch.json
minimal.json
reuse-previous-review.json
references/
aml-resolution-rules-schema.md
aml-rules-context-fields.md
aml-rules-enumerations.md
aml-rules-expressions.md
scripts/
aml_rules_api.py
build_aml_rule.py

详细介绍

Sumsub — 创建 AML 处理规则

根据精简规范构建 AML 处理规则,通过 Agent API 将其写入租户的 草稿 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 组装。

端点

所有端点都位于 /resources/api/agent/amlResolutionRules 下。每个租户只有 一条规则链,版本依次为 draft → published → archived。(每一行都对应 aml_rules_api.py 的一个子命令 — 请勿手动调用这些路径。)

方法路径子命令使用时机
GET/draftdraft读取可编辑版本。根据已发布版本(或空内容)自动创建草稿 — 已启用的租户不会返回 404。包含 notices[]。
GET/publishedpublished读取生效版本(尚未发布任何内容时返回 404)。
GET/archivearchive [marker]修订历史,使用 marker 分页。速率限制为每分钟 5 次 — 请勿轮询。
GET/librarylibrary按类别分组的现成规则模板。
POST/draft/rulesupsert写入一条规则:省略 id 以创建规则(追加到规则链末尾);提供现有 id 以替换该规则。响应为重新计算 notices[] 后的完整草稿。
PUT/draft/rules/orderreorder调整顺序:请求体 {"ruleIds": [...]} 必须恰好列出每个规则 ID 一次。
DELETE/draft/rules/{id}delete <id>根据 ID 从草稿中移除一条规则。幂等 — 即使要删除的 ID 不在草稿中,操作仍会成功。请参阅下文的授权政策。
POST/draft/publishpublish发布生效。存在任何 error 级别的通知时,将拒绝发布。之前的已发布版本会自动归档。

通过 API 发布仅适用于集成阶段。 集成被视为已启用后,API 可能会 拒绝发布(返回 4xx);此时必须由人工在 Sumsub 网页界面中审核并发布规则链。此阶段应将发布被拒视为预期行为,而非需要绕过的错误 — 请报告此情况,并引导用户前往网页界面。

除常规要求外,Token 还必须满足以下要求:这些是 Agent 端点,因此 App Token 必须是 AI 专用(在控制面板界面的 AI Token 页面创建),并具有 manageAmlCases + manageClientSettings 权限。配置错误时的表现:

  • 403 "This endpoint is not allowed for this type of token" → 使用的是常规 App Token,而非 AI Token。请让用户创建 AI Token。
  • 所有端点均返回 404 "API is not available" → 此租户未启用 AML Resolution Rules API。立即停止 — 告知用户联系其 CSM 或 Sumsub 支持;不要重试其他端点。

⚠️ 发布会影响 LIVE 生产环境

AML Resolution Rule Chain 由生产环境和沙盒共享——只有 AML 案例 / 申请人彼此隔离,规则链本身并未隔离。发布会更改自动审核真实生产环境 AML 筛查命中项的规则链(清除误报、确认真阳性、加入白名单)——沙盒 sbx: 令牌并不能让此操作变得安全。发布之前的所有操作都安全:读取草稿、插入或更新规则、重新排序以及删除规则都只会修改草稿,草稿发布前不会审核任何内容。

因此,只有在用户明确要求时才发布,并且要知道发布可能会被后端拒绝:规则链激活后——即已经处理了过多申请人 / 集成已完成——API 会拒绝发布(返回 4xx)。这是预期行为,不要尝试绕过:请说明这一情况,并告知用户从 Sumsub 网页界面发布(参见端点说明)。

身份验证 — App Token + 密钥(仅限沙盒)

此技能会调用 Sumsub 公共 API,并根据 身份验证参考文档为每个请求签名。 完整的工作原理说明位于 sumsub-api-auth 技能中——如果遇到 401 Invalid signature,请阅读该文档。

⚠️ 仅限沙盒令牌。 此处不要接受或使用生产环境 App Token——这些规则会自动审核真实 AML 命中项。如果用户提供生产环境令牌,请拒绝并要求他们在 https://cockpit.sumsub.com/checkus/home?sbx=true 生成一组沙盒凭据(Connect Sumsub to your AI agent -> Build & configure -> Generate token——该页面会生成这些端点所需的 AI 令牌,见上文)。令牌和密钥只会显示一次——关闭对话框前请复制两者。aml_rules_api.py 会强制执行此要求——不以 sbx: 开头的令牌都会被拒绝。

变量示例
SUMSUB_APP_TOKENsbx:... — 从仪表板获取的沙盒 AI App Token。
SUMSUB_SECRET_KEY创建令牌时显示一次的配对密钥。
SUMSUB_BASE可选。默认值为 https://api.sumsub.com。

如果用户已在对话中提供凭据,请直接使用;否则,在运行前询问一次。切勿复述密钥。

规则链的执行方式(设计规则时请牢记)

  1. 规则按从上到下的顺序运行——顺序很重要。
  2. 每条规则都会针对所有尚未审核的命中项进行评估。已获得 matchStatus(来自审核操作或前序规则)的命中项会被后续规则跳过。
  3. 效果会在运行过程中体现:前序规则添加的标签,以及重新计算后的 screening.answer / screening.tags / screening.matchStatuses,都会被后续规则看到——这使规则链式执行成为可能(规则 A 添加 match_tin 标签,规则 B 对 screening.tags containsAny ["match_tin"] 作出响应)。
  4. 请将具体且具有决定性的规则(ID 匹配、沿用先前审核结果)放在宽泛的清理规则之前——如果将宽泛的 false_positive 规则放在最前面,它会抢先处理命中项,使其下方更精确的规则无法处理。

前提:AML 筛查必须确实正在运行

此规则链仅针对 AML 筛查产生的命中采取行动。如果筛查未运行,这些规则就不起作用——它们不会评估任何内容。两个相互独立的门槛决定筛查是否会在某个申请人级别运行:

  1. 租户权限 WATCHLISTS — 全有或全无,适用于整个租户。请调用 sumsub-check-permissions 技能进行验证。存在 WATCHLISTS → AML 筛查可用,并且默认在每个级别开启。不存在 WATCHLISTS → AML 筛查在整个租户范围内关闭;任何申请人级别的设置都无法将其开启,而且此规则链将永远不会看到命中。
  2. 按级别选择退出 disableWatchlists — 仅当通过门槛 1 后才相关。除非某个级别设置顶层 disableWatchlists: true(客户端可借此排除不应进行筛查的级别),否则筛查会在该级别运行。这属于 sumsub-create-level 技能的职责,而非本技能的职责。
WATCHLISTS 权限级别 disableWatchlists筛查会在该级别运行吗?规则链会处理其命中吗?
不存在(任意)不会 — 整个租户范围内关闭不会
存在不存在 / false会(默认)会
存在true不会 — 该级别已选择退出不会

每个租户只有一条规则链,它会处理筛查运行的所有级别产生的命中——它不限定于某个级别。因此,在构建规则前(步骤 0)请确认门槛 1。如果缺少 WATCHLISTS,此处编写的任何内容都会一直处于休眠状态,直到启用该权限。

标签连接到申请人工作流

规则标签是通用申请人标签——适用于整个租户,并非仅用于 AML。它们不仅会在 AML 运行中串联:还会作为 checks.personWatchlist.tags(个人)和 checks.companyWatchlist.tags(公司)出现在申请人工作流的条件中。因此,标签是规则链与工作流之间的交接点:规则链标记出复杂情况,工作流据此进行路由。例如:

  1. AML 规则 — 条件为“命中包含 pep 风险标签,且申请人未满 30 岁”,标签操作为 ["youngPep"]。
  2. 工作流边 — 一个 condition 用于测试 checks.personWatchlist.tags 是否包含 youngPep → 指向人工审核节点。

两个技能编写的都是相同的 Condition AST(见下文),因此两部分的结构相似。如果用户的目标包含筛查后的路由或操作,请在此处设置标签,并指引他们使用 sumsub-create-workflow 完成路由部分。

流程

  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 更新,而不是追加重复规则——upsert 不会按名称去重。记录变更前已存在的规则 ID——之后需要依据这些记录遵守删除授权政策。
  3. 先检查库:${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py library。如果现成模板符合用户意图,请从其 rule 定义开始——移除 id,再进行调整。检查模板的 vendors 列表,确认其中包含租户使用的 AML 供应商。
  4. 编写规则规范(如下)。直接将 condition 编写为真实的 Condition AST——不存在表达式迷你语言(参见 编写条件)。通过 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. 向用户展示解析后的负载,并在首次 upsert 前取得明确确认。如果规则的 tags 操作会引入尚不存在的标签,请明确说明:upsert 会创建一个租户范围内的申请人标签(可在仪表板筛选器、工作流等各处看到)——请确认该名称值得保留(清晰、简洁、可复用),或改用现有标签。
  7. 通过 ${CLAUDE_SKILL_DIR}/scripts/build_aml_rule.py < spec.json | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py upsert 执行 upsert → 响应为包含重新计算的 notices[] 的完整草稿。创建多条规则时,每条规则都重复步骤 3–6。记录服务器为每条新建规则分配的 ID——这样才能确认规则归你创建(步骤 9)。
  8. 检查 notices。error 通知(例如 invalidTag、unknownField、unknownFunction)会阻止发布——请修正规则,并使用其 id 重新执行 upsert。warning / info 仅供参考;请告知用户。参见 references/aml-resolution-rules-schema.md 中的通知键表。
  9. **排列规则链顺序。**新规则会添加到末尾。如果需要更改评估顺序,请传入完整排列:echo '{"ruleIds": [...]}' | ${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py reorder。
  10. 仅按下方的授权政策删除规则。${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py delete <ruleId>。
  11. 仅在用户明确要求时发布(参见“发布会影响 LIVE 生产环境”提示):${CLAUDE_SKILL_DIR}/scripts/aml_rules_api.py publish。发布后,规则链会针对生产环境和沙盒环境中的真实 AML 命中生效——切勿在用户未提出要求时发布;在此之前,草稿不会生效。规则链激活后,后端可能会拒绝发布(已处理的申请人过多 / 集成已完成)——此时会返回 4xx。这是预期行为:请报告该情况,并指引用户通过 Sumsub 网页界面发布(参见端点说明)。
  12. 报告(先列规则名称,绝不要只列 ID):
删除规则 — 同意政策

delete 子命令会永久从草稿中移除一条规则(该规则会随修订版本归档,但会从可编辑规则链中消失)。请遵循以下限制:

  • 本次会话中由你创建的规则 — 如果规则有误、用户要求替换,或你正在迭代自己的工作,可以直接删除。(通常按 id 原地更新更好,因为这样可以保留规则的位置;只有在规则确实应该被移除时才选择删除。)
  • 任何非你创建的规则 — 无论是预先存在的规则、来自更早会话的规则,还是由人类编写的规则,只有在用户明确同意删除该特定规则后,才能删除。请说出规则名称(即其 name),并在删除前确认。绝不能以“清理”或“重建”规则链为由,顺带删除他人的规则。
  • 如果不确定规则是否由你创建,请视为非你创建并询问。

删除操作具有幂等性,并会返回重新计算过 notices[] 的完整草稿——之后请重新检查这些通知(移除一条规则可能会改变剩余规则仍能支持哪些标签/字段)。

规则规范格式(JSON,通过 stdin 输入)

{
  "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"]
}

规则必须包含 review 和/或 tags——两者都没有会产生 emptyAction 错误通知。Review 字段可接受标量(构建器会将其编码为 JSON {lit}),也可接受显式的 {"exp": "..."}/{"lit": "..."},用于计算值或直接提供值。

编写条件

规则的 condition 是直接编写的真实 Sumsub Condition AST——其形状和规则与工作流边条件相同,因此两项技能保持一致。不存在表达式迷你语言(旧的 condition: "screening.vendor = …" 字符串和 conditionRaw 键已移除;构建器会拒绝这两种写法,并在此处提供指引)。

⚠️ 请为每条规则指定实体类型范围。 个人和公司匹配会公开不同的字段,读取方式也不同,因此为其中一类构建的规则可能会在另一类上误触发。每条规则都必须包含一个 input.entityType 条件——根据规则意图推断目标类型(个人姓名/出生日期/PEP 信号 → 个人;公司名称/KYB 信号 → 公司);不确定时,默认使用个人:

  • 个人(通常情况):{ "op": "ne", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] } — entityType ≠ company。
  • 公司/组织:{ "op": "eq", "args": [ {"exp": "input.entityType"}, {"lit": "\"company\""} ] }。

只有在规则有意不区分实体类型时(较少见——例如“将来自国家 X 的所有 sanctions 命中列入白名单”),才省略此条件。大多数库模板已包含此条件——改编模板时请保留。

{
  "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>"} — 表达式路径,原样填写(参见 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 [其他标签],因为它会造成漏判:这种写法会默认你已列出整个封闭词汇表(风险标签集合恰好只有六个 — 参见 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 编入索引)。

示例

  • examples/minimal.json — 仅标签规则(对风险标签使用 containsOnly)。
  • examples/auto-clear-dob-mismatch.json — call 函数 + 供应商匹配类型;最常见的自动清除结构。
  • examples/reuse-previous-review.json — 整体审查的 expression 形式,用于沿用先前决定,并带有日期年龄条件。这也是少见的与实体无关的规则(沿用先前决定的方式对个人和公司相同)— 唯一不需要 input.entityType 筛选条件的情况。

另请参阅

评论

支持 Markdown