关于 sumsub-create-workflow
根据节点和边的规格构建并验证 Sumsub 申请人工作流的技能。它创建草稿,并依据当前线上流量设置发布门槛,因为已发布版本会影响生产流量。
主要功能
- 01按节点和边构建工作流 JSON
- 02保存前验证草稿
- 03查看工作流版本与流量
- 04依据线上流量限制发布
适用场景
- 01创建申请人路由工作流草稿
- 02发布前验证工作流结构
- 03完成流量检查后发布版本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sumsub/ agent-skills --skill sumsub-create-workflow安装后在 Claude Code 中输入/sumsub-create-workflow确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/action-workflow.jsonaml-routing.jsoncountry-routing.jsonrisk-routing.jsonreferences/workflow-expressions.mdworkflow-notices.mdworkflow-patterns.mdworkflow-schema.mdscripts/build_workflow.pypost_workflow.shpublish_workflow.shworkflow_api.py详细介绍
Sumsub — 创建工作流
根据精简的节点/边规格构建 ApplicantWorkflow JSON 负载,对其进行验证(试运行),并将其作为 draft 发送 POST 请求;随后根据工作流的当前线上流量暴露情况,通过 PUT /{id}/revisionStatus 发布:暴露较低时直接发布,暴露较高时则仅在明确确认后发布。报告最终的 name(类型)/revision/revisionStatus/id。发布任何内容前,请阅读 Danger 部分。
概念
工作流会将申请人导向各个级别和分支。每种类型恰好只有一个工作流:default(自动用于每次验证)、actions(自动用于申请人操作)、test(隔离运行;仅从其草稿运行,需针对每位申请人手动启动——不可发布)。每次保存都会为这个单例创建一个新修订版本,而不是新建工作流。修订版本是一个草稿——可编辑,不会引导任何流量,创建/更新/验证始终安全——直至其被发布;发布后,它会对所有真实的生产流量生效,并自动将先前已发布的修订版本归档。test 永不发布;它从自己的草稿运行。
端点
| 方法 | 路径 | 适用时机 |
|---|---|---|
POST | /resources/api/agent/applicantWorkflows | 创建(没有 id)或通过 id 更新一个草稿。只有草稿可编辑;此处传入 published/archived 的 revisionStatus 会被拒绝。始终安全——草稿不会引导流量。 |
POST | /resources/api/agent/applicantWorkflows/-/validate | 试运行验证。返回 notices[],不持久化数据。只读。 |
GET | /resources/api/agent/applicantWorkflows | 列出工作流(所有修订版本和状态)。响应为扁平结构:{ "items": [...], "totalItems": N, "pageInfo": { "limit", "offset" }, "error": {...}? }——items 位于顶层(没有 list 包装层)。 |
GET | /resources/api/agent/applicantWorkflows/{id} | 读取一个修订版本(id 指向特定修订版本,而不是工作流名称)。 |
GET | /resources/api/agent/applicantWorkflows/{id}/traffic | 查看最近处于此修订版本各级别的申请人:{"applicantCount": N}。只读;这是发布暴露检查的输入。根据级别推导,而非根据工作流路由——请参阅 Danger。 |
POST | /resources/api/agent/applicantWorkflows/{id}/draft | 从已发布/已归档的修订版本分叉创建新草稿——在不触碰线上工作流的情况下迭代的方式。 |
PUT | /resources/api/agent/applicantWorkflows/{id}/revisionStatus | 发布/归档一个修订版本。请求体为 {"revisionStatus":"published"|"archived"|"draft"}。发布要求 error 通知为零,并会自动归档先前已发布的修订版本。⚠️ 会影响线上流量——请参阅 Danger。 |
App Token 必须具有 manageWorkflows 权限。Sandbox 令牌通常具备此权限;如果遇到 403 Unauthorized (atd),请使用正确的作用域重新生成令牌。
⚠️ 危险 — 发布会影响线上生产流量
工作流修订版本在生产环境和沙盒环境之间共享;只有 申请人 是隔离的。发布会更改处理所有真实生产流量的工作流 — 沙盒 sbx: 令牌并不能让这项操作变得安全。这是使用此技能时最重要的一点。(相比之下,草稿不会路由任何流量 — 可随意创建、更新和验证。)
发布 default/actions 是否需要通过门槛,取决于工作流的当前线上曝光量 — 即当前 published 修订版本(发布操作会自动将其归档)近期处理的申请人流量,由 workflow_api.py traffic 子命令测量。阈值为 400 名近期申请人(覆盖设置:SUMSUB_PUBLISH_TRAFFIC_THRESHOLD):
工作流 name | 当前线上曝光量 | 发布 |
|---|---|---|
default / actions | > 400 名近期申请人,或无法读取 | 全面防护:通过验证 · 与当前已发布版本比较差异 · 用户明确回复“是” · SUMSUB_ALLOW_WORKFLOW_PUBLISH=1 许可标记 |
default / actions | ≤ 400,或尚无已发布版本 | 低曝光:直接发布 — 无需确认,也无需许可标记(仍须报告操作结果) |
test | — | 不可发布 — revisionStatus 不可变(API 会拒绝调用);它使用草稿运行 |
曝光量根据等级推算 — 统计近期出现在已发布修订版本所含等级 名称 中的申请人(因此,共用等级名称的修订版本可能会报告重叠人数),反映的是该工作流各等级当前的繁忙程度,而非新修订版本的影响范围。向用户描述时应说 “此修订版本中的等级近期有 N 名申请人”,绝不要说 “此工作流处理了 N 名申请人”。无论曝光量如何,以下规则始终适用:
- 发布是构建流程的默认终点,而非单独的请求 — 上述门槛决定发布所需的操作(低曝光 → 直接发布;高曝光 → 确认 + 许可标记)。只有用户明确选择不发布(“只保存为草稿”),构建结果才会保留为草稿。
- 曝光量未知时采取故障安全策略。 如果无法读取线上修订版本的流量(API 错误),则视为超过阈值,并执行完整的防护流程。
- 绝不要为了绕过门槛而切换类型。 不能通过将发布目标改为
test来让发布请求“更安全”(API 也会拒绝这种操作)。应发布用户请求的类型。 workflow_api.py publish是最后一道防线:它会独立重新测量曝光量,且仅在曝光量超过阈值或无法读取时,要求设置SUMSUB_ALLOW_WORKFLOW_PUBLISH=1— 低曝光时无需许可标记即可发布。
身份验证 — App Token + 密钥(仅限沙盒)
每个请求都使用 App Token + 密钥进行签名(HMAC-SHA256)。完整的签名说明和 401 错误排查方法:sumsub-api-auth。
**⚠️ 仅限沙盒。**工作流会路由真实申请人,因此不接受生产令牌 — 脚本会拒绝任何不以
sbx:开头的令牌。在控制面板中创建一对沙盒凭据(将工作区切换到 Sandbox → App tokens → Create;这两项信息只会显示一次)。
| 变量 | 示例 |
|---|---|
SUMSUB_APP_TOKEN | sbx:... — 控制面板中的沙盒 App Token。 |
SUMSUB_SECRET_KEY | 创建令牌时仅显示一次的配对密钥。 |
SUMSUB_BASE | 可选。默认为 https://api.sumsub.com。 |
如果用户已在对话中提供凭据,则重复使用;否则,在运行前询问一次。绝不要复述密钥。
不是凭据:发布高曝光的
default/actions修订版本(线上流量超过阈值或无法读取)时,需要通过SUMSUB_ALLOW_WORKFLOW_PUBLISH=1启用许可,但它不是已配置的环境变量 — 而是仅在发布调用(步骤 8)中以内联形式输入的一次性命令许可令牌,不作其他用途。绝不要将其添加到settings.local.json或任何持久环境配置中:这样会导致门槛永久开放,违背它唯一的用途。它只能出现在发布时的那一条命令行中,不能出现在其他任何地方。
原则
以下三条原则贯穿下面的每个步骤;流程会在需要之处再次提及。它们有一个共同核心——用户的意图和工作区中的真实实体才是事实依据;你的职责是忠实地将它们连接起来,而不是凭空编造或擅自改进。
- 严格按照用户的要求构建。 用户指定的级别名称、节点结构、分支逻辑和
kind选项都是固定约束,不是供你改进的原材料。如果你经过推理后认为某个选择多余或欠佳——这通常源于对级别或引擎行为的错误假设(例如,串联的级别不会重新采集已收集的数据——参见 references/workflow-patterns.md)——就按原样构建,并在报告中指出问题,绝不要悄悄换成你偏好的设计。验证会捕获无效的内容;“欠佳”不等于“无效”,也绝不是擅自更改用户设计的理由。 - 连接实体,不要擅自创建实体。 每个级别、客户端列表和节点引用的标签,在你基于它们构建之前都必须确实存在——可以是用户提供的名称、你通过
GET /resources/applicants/-/levels确认的名称,或明确正在创建的名称(由你、配套技能或用户创建)。未经确认的引用意味着必须停止,而不是留白待填:复用现有内容、创建该实体,或明确标记为待处理——绝不要为了让图看起来完整而编造一个似乎合理的名称(缺失引用只会阻止发布,而不会阻止草稿,并不意味着你可以捏造名称)。主动确认依据——先读取现有级别,并复用真实存在的级别,再考虑询问或编造。 - 以实际情况为准,而不是只追求绿色勾选。 结构或构建器错误由你负责修复——反复迭代,直到没有错误。但缺失实体错误(
levelNotFound、tagDoesNotExist、未知客户端列表)只能通过确认引用的真实依据来消除——绝不要把引用改指向一个方便的实体,只为让验证通过。并且,报告实际情况,而不是你希望成立的情况:存在未解决引用的草稿就是未完成;为适配现有实体而扭曲结构,就是对用户策略的更改——必须明确指出这两点,绝不能把它们说成圆满成功。
流程
-
根据用户自己的措辞确定工作流
kind,并明确说明。 如果用户没有指定kind,则为default(规范默认值)。只有在用户明确指定时,才使用test或actions。绝不要推断、默认使用或替换为用户未要求的kind。将kind作为假设说明,并继续操作——例如说 “由于你没有指定kind,我将按default处理”,让用户看见并有机会纠正;不要把kind变成多选题。绝不要为了避免触碰现有草稿,而提议将test作为构建default工作流的“安全场所”:test用于按申请人手动运行测试,有自己独立的草稿,无法发布,而且没有晋升到default的途径。现有的default草稿绝不是在别处构建的理由——直接覆盖它(第 3 步)。 -
将用户的流程图转换为精简规范(见下文)。每个方框或判断菱形对应一个节点,每条箭头对应一条边。使用易读、类似标签的
id(如country-check、route、idv、reject-region)。如果用户给出的是一项策略而非流程图(“帮我构建一个 KYC/KYB 工作流”),不要从空白开始——使用 references/workflow-patterns.md 中的规范管线主干和基本结构进行拆解,再针对每个环节套用该主干。只构建用户指定的内容,并在构建之前核实每一级别、列表和标签的引用(原则 1–2)。 -
验证图结构: 每条边的
from/to都必须对应一个节点id;每个applicantLevel/actionApplicantLevel都必须引用一个真实级别名称;每个exclusiveChoice都必须至少有一条分支出边(condition:或on:);最终拒绝节点必须包含labels或buttonIds。(级别节点及所有非选择节点都只有一条无条件出边;只有exclusiveChoice可以分支——参见边的on:。)该图是有向无环森林:边只能向前(不能有环或回边——文档重新提交不属于回边;引擎会在原处重试);允许多条边汇入同一节点,也允许共享下游节点,并且多个入口级别可以各自作为独立流程的根节点。绝不要用边连接不同的申请人类型(KYC 个人与 KYB 公司)——申请人的类型不能改变。完整图规则见 references/workflow-schema.md 中的 Constraints;重新提交规则见 references/workflow-patterns.md。 -
检查当前状态:针对目标工作流
name,运行${CLAUDE_SKILL_DIR}/scripts/workflow_api.py state <name>,然后选择写入方式:没有任何版本 → 创建(POST 时不带id);已有草稿 → 原位更新(POST 时带上该草稿的id;不带id的 POST 会返回409);已有已发布版本但没有草稿 → 使用${CLAUDE_SKILL_DIR}/scripts/workflow_api.py fork <id>创建草稿,或者直接 POST 一个新的。覆盖现有草稿是正常且预期的操作——直接静默执行。 没有需要寻找的“空位”:每种kind只有一个草稿,因此不带id的 POST 返回409时,意味着应使用该草稿的id重试——绝不要要求用户删除或归档草稿,也绝不要换用其他kind来腾出位置。 草稿是此技能在多次运行中不断演进的工作区,因此覆盖前不要征求同意,也不要默认备份。只有当用户明确要求保留当前草稿时,才先运行${CLAUDE_SKILL_DIR}/scripts/workflow_api.py get <id>读取,并将 JSON 正文保存到文件(该命令末尾会追加一行HTTP <code>——只保留 JSON),然后再覆盖。编辑时,保留现有节点和边的id——运行get <id>获取所依据的版本,并沿用其中的id;仅为新节点或边生成新id(引擎会根据这些id匹配正在运行的流程;原因见 references/workflow-schema.md 中的 Revision continuity)。 -
生成载荷:使用
${CLAUDE_SKILL_DIR}/scripts/build_workflow.py——将规范通过标准输入传入,完整载荷从标准输出返回。构建器会根据真实节点类型和边的conditionAST 组装载荷,并通过内置的已知集合验证节点类型、运算符和操作targetType,因此拼写错误和不受支持的结构会在此处报错,不会发起网络调用(其余部分以 API 的 validate 为准,包括级别、客户端列表和标签)。原位更新时,在规范中设置草稿的id(第 3 步)。 -
验证(试运行,不保存任何内容)。 将载荷通过管道传给
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py validate→notices[]。info= 提示性信息;warning= 不阻断操作,但通常表示真实问题;error= 阻止发布。有关通知的含义、严重程度、参数及处理方式,请查阅 references/workflow-notices.md。缺少实体的错误应通过核实引用来解决,而不是改换引用对象以通过验证(原则 3)。持久化之前务必先验证。 -
使用
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py post执行 POST——创建时不带id,原位更新时带上第 3 步中的id。响应会包含已持久化的草稿及其id、clientId、notices[]。 -
使用响应正文中的
clientId构建仪表板链接:https://cockpit.sumsub.com/checkus/sdkIntegrations/workflows/active/applicant?clientId=<clientId>&sbx=truesbx=true指向 Sandbox 工作区。⚠️ 这不是指向特定id的深层链接——它会显示当前草稿;请提醒用户尽快点击。 -
发布——构建的默认终点,受曝光量门控。 仅当用户选择不发布(“只保存草稿”)时才跳过——草稿不会接收流量,因此单独作为终态并无意义。草稿必须在最近一次验证时通过(步骤 5)——如果存在任何
error通知,API 会拒绝发布该修订版本。运行${CLAUDE_SKILL_DIR}/scripts/workflow_api.py publish <draft-id>;该命令负责实时曝光量门控(定义见 Danger),并执行以下两种操作之一:- 低曝光量 → 直接发布;操作完成。
- 高曝光量 → 在更改任何内容之前拒绝操作,并打印曝光数量以及当前已发布修订版本的
id(这是可通过单条命令回滚的目标)。若要继续,请运行受保护流程:将草稿与该已发布修订版本进行差异比较,向用户说明变更及曝光数量(“将修订版本 N 应用于所有真实生产流量;当前已发布修订版本涉及的级别近期约有 M 名申请人,将自动归档”),取得用户明确的“同意”,然后使用SUMSUB_ALLOW_WORKFLOW_PUBLISH=1作为前缀重新运行。
回滚: 重新发布之前已发布的
id——SUMSUB_ALLOW_WORKFLOW_PUBLISH=1 ${CLAUDE_SKILL_DIR}/scripts/workflow_api.py publish <previous-published-id>(保留该授权开关——重新上线后,要替换的修订版本本身可能也会超过阈值)。test永远不会发布——参见 Danger。 -
报告(先说明便于人理解的身份信息)——报告实际情况,而不是你希望看到的情况:如有未解决的引用或偏离预期的结构,必须明确指出,不能将其描述为成功(原则 3)。先说明工作流
name(default/actions/test)和revision——例如 «default» 修订版本 14——然后说明revisionStatus;节点/边数量以及引用的去重排序后的级别名称(以便发现拼写错误);再提供可点击的 Markdown 仪表板链接(步骤 7)。如果已发布,请说明这一点,指出当前已发布的revision,注明自动归档的先前修订版本,并提供其id作为回滚目标。最后单独一行写出Workflow ID: <id>——原始id只能出现在这里。失败时,原样展示 Sumsub 的description/errorName(构建器验证错误已会打印精确消息)。
精简规范格式(通过 stdin 输入 JSON 或 YAML)
kind用于选择要编辑的工作流类型(各类型的含义以及修订版本/草稿的工作方式,参见 概念)。只有用户明确提出请求时才会设置该值(参见步骤 0);默认值为default。⚠️ 发布后,default/actions会拦截真实流量——参见 Danger 部分。(架构包含title字段,但引擎会忽略它——本技能既不设置也不依赖该字段。)
节点的 type 使用实际架构中的节点类型;边直接携带真实的 Sumsub condition AST(不使用表达式迷你语言)。on: 是 reviewDecisions 的简写。
kind: default # optional — default | test | actions (the workflow to edit)
revisionStatus: draft # optional; only `draft` on create. Publishing is a separate, gated step (see Danger).
nodes:
- id: country-check
type: applicantLevel
levelName: "Country Selector"
- id: route
type: exclusiveChoice
name: "Country router"
- id: idv
type: applicantLevel
levelName: "IDV"
- id: idv-result
type: exclusiveChoice
name: "IDV result"
- id: reject-region
type: finalRejection
labels: ["WRONG_USER_REGION"]
- id: manual
type: manualReview
edges:
# A level's out-edge is single & unconditional — branch only at an explicit exclusiveChoice.
- { from: country-check, to: route } # plain: level → choice
- from: route # embargo first (any decision)
to: reject-region
condition: { or: [ { and: [ { op: in, args: [ {exp: "applicant.country"}, {lit: "[\"UZB\", \"DEU\"]"} ] } ] } ] }
- from: route # approved & allowed → IDV
to: idv
on: approved
condition: { or: [ { and: [ { op: eq, args: [ {exp: "applicant.country"}, {lit: "\"USA\""} ] } ] } ] }
- { from: idv, to: idv-result } # plain: level → choice
- { from: idv-result, to: manual, on: rejected } # resubmission unhandled → engine retries (the default)
节点类型
节点的形式为 { id, type, name?, <body> },其中 type 是真实的架构节点类型。主体字段可以扁平化(如下所示),也可以使用真实的嵌套形式(applicantLevel: { levelName })。
标准验证工作流(kind: default|test):
type | 主体 |
|---|---|
applicantLevel | levelName(字符串);可选的 disableGoBack |
exclusiveChoice | —(通过出边分支) |
actions | actions: 列表(见下文) |
manualReview | — |
finalRejection | labels 或 buttonIds |
操作工作流(仅限 kind: actions):每种 action* 类型都对应一种标准类型——actionApplicantLevel、actionExclusiveChoice、actionActions、actionManualReview、actionFinalRejection 接受与去掉 action 前缀后的类型相同的主体。此外还有一种类型:actionApplicantTransition(levelName — 将验证交还给的 default 工作流级别;该级别必须存在于已发布的 default 工作流中,否则 validate 会抛出 missingLevelsForTransition)。
action* 类型只能用于操作工作流(在主要验证之后运行的图,通常用于添加标签/备注/更改来源键,或将申请人转回 default);标准类型只能用于 default/test。混用会被拒绝;构建器会在 POST 前捕获此问题。
操作块
在 actions 或 actionActions 节点内:
- id: tag-and-note
type: actions
actions:
- tag: ["High risk", "Manual review"] # adds tags
- note: "Flagged by workflow" # adds applicant note
- sourceKey: "manual-flow" # overrides applicant source key
每个项目必须且只能包含以下之一:tag、note、sourceKey。在一些特殊情况下,标签/备注也可以使用更丰富的对象形式:
- tag: { add: ["VIP"], remove: ["pending"], target: applicantAction }
- note: { text: "Auto-note", target: applicantAction }
target(targetType)默认值为applicant。applicantAction的目标是触发该操作的操作,且只能用于操作工作流(kind: actions)。- 不支持:
kytCase(暂缓支持 —blueprintId尚无公开 API)、riskScore、recheck。(旧版riskLevel操作从未存在 — 已移除。)
边条件(condition:)
边可以带有 condition: — 直接书写真实的 Sumsub 条件 AST(没有表达式小语言):
condition:
or: # OR of AND-groups; branches evaluated in order, first match wins
- and:
- { op: eq, args: [ {exp: "applicant.country"}, {lit: "\"USA\""} ] }
- { op: in, args: [ {exp: "poi.country"}, {exp: "clientLists.high_risk"} ] }
{exp: "<path>"}— 原样填写的表达式路径。引擎接受的任何形式都可使用,包括方括号/引号分段:applicant.metadata["balance"]、clientLists["luhansk_people's_republic"]。它是比较的左侧,也可以作为字段间比较和客户列表检查的右侧({exp: "clientLists.high_risk"})。{lit: "<json>"}— 字面量,必须以已编码为 JSON 的字符串形式提供(即 API 存储的形式):"\"USA\"","3"、"true"、"[\"UZB\", \"DEU\"]"。未编码的字面量({lit: "USA"})会被 API 以syntaxError拒绝,因此必须编码。op是比较运算符之一(eq ne lt lte gt gte in notIn contains notContains containsAny containsAll startsWith endsWith match empty notEmpty eqIgnoreCase …;完整集合见 references/workflow-schema.md)。构建器会根据已知集合验证每个op,并拒绝未知或保留的运算符(call)。- 否定使用
not*运算符表示(notIn、notContains、ne、notEmpty等)— 不要设置negate标记;顶层的Condition.negate会被拒绝(UI 不支持)。
客户列表(
clientLists.<name>)是由租户定义的命名列表,用作in/notIn/containsAny的表达式右侧。本技能不会创建或填充这些列表 — 请使用sumsub-manage-client-lists。未知列表会验证为invalidExpression错误提示(类似levelNotFound的实体缺失错误)— 该结构有效,只是该工作区尚未定义此列表。
完整的 Condition/And/Criterion AST、字面量编码规则和运算符列表见 references/workflow-schema.md;有效的 exp 路径见 references/workflow-expressions.md。
Edge on:(审核决定路由)
on: approved 会根据某个级别的审核决定(approved / rejected / resubmission)来控制转换(多个决定可传入数组)——这是实际字段 reviewDecisions: 的简写。on:/condition: 仅在离开 exclusiveChoice 的边上生效(在 action 工作流中则为 actionExclusiveChoice;reviewDecisions 匹配上游级别的决定);级别自身的出边是单条、无条件的转换。因此,要根据级别的结果进行分支,必须自行编写 choice:将级别指向一个 exclusiveChoice,并使用一条普通边,然后在 choice 的出边上添加 on:/condition: 分支(按声明顺序求值,匹配第一项即生效)。构建器不会自动生成 choice——它会拒绝级别边上的 on:/condition:(以及拥有多个出边的级别),并提示你插入 choice。on: 和 condition: 可以同时用于 choice 的出边。
两个规则决定了省略决定时的行为:(1) 省略 on: 会使边不受决定影响——不会检查决定;(2) 重新提交者会停留在其所在级别,除非紧接级别之后的 choice 上有某个分支指定了 resubmission。综合来看,实际上,不带 on: 的边适用于 approved + rejected,而重新提交默认会重试(这是从这两条规则推导出的结果,不是存储的默认集合)。将重新提交交由引擎处理:除非用户明确要求限制或以其他方式处理重复尝试,否则不要在任何地方指定 resubmission。 它不属于标准工作流——引擎自动重试才是绝大多数人想要的行为。只有在用户提出要求时,才查看 references/workflow-patterns.md 中的 无需循环的迭代:重新提交门控(并注意:在 choice 上指定 resubmission 会改变其其他边的行为;该章节会解释这种联动)。
示例
examples/country-routing.json— 入口级别 → 资格门控(地区拒绝 vs IDV)→ IDV → 第二个 choice → IDV 被拒绝时进入人工审核。由于两个 choice 之间有一个级别,因此需要两个 choice(这是最常见的拓扑)。examples/action-workflow.json— 一个简短的 action 工作流,在级别完成后添加标签和备注。examples/aml-routing.json— 客户名单地理门控 + 基于applicant.review.rejectLabels的 AML 后路由(PEP / SANCTIONS / ADVERSE_MEDIA),使用containsAny和基于标签的汇入(与真实世界的 AML 拓扑相似)。
另请参阅
- references/workflow-schema.md — 每种节点类型的主体、action 模型、
ConditionAST + 运算符、生命周期和实时流量防护的参考。 - references/workflow-expressions.md — 表达式路径查询字典。
- references/workflow-notices.md — 验证通知目录:
validate/post端点返回的每个notices[]键,及其严重性、参数和处理方式(补充引用依据还是修复规范)。遇到通知时可在此查找。 - references/workflow-patterns.md — 组合模式:如何将 KYC/KYB 策略分解为规范的流水线主干和可复用的基本构件(策略而非架构)。如果需求是“帮我构建一个工作流”,而不是“修复这个节点”,请从这里开始。
sumsub-manage-client-lists— 创建并填充条件所引用的clientLists.<name>集合