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 を報告します。公開する前に「危険性」のセクションをお読みください。
概念
ワークフローは、レベルや分岐を通じて申請者を振り分けます。種別ごとにワークフローは1つだけ存在します。default(すべての検証で自動実行)、actions(申請者のアクションで自動実行)、test(分離されており、ドラフトからのみ実行され、申請者ごとに手動で起動 — 公開不可)です。保存するたびに、この単一ワークフローの新しいリビジョンが作成され、新しいワークフローが作成されることはありません。リビジョンはドラフトであり、公開されるまでは編集可能で、トラフィックを振り分けず、いつでも安全に作成/更新/検証できます。公開すると、実際の本番トラフィックすべてに対して有効になり、以前に公開されていたリビジョンは自動的にアーカイブされます。test は公開されず、ドラフトから実行されます。
エンドポイント
| メソッド | パス | タイミング |
|---|---|---|
POST | /resources/api/agent/applicantWorkflows | id がない場合は作成し、id がある場合はドラフトを更新します。編集できるのはドラフトのみです。ここで revisionStatus が published/archived の場合は拒否されます。常に安全です — ドラフトはトラフィックを振り分けません。 |
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} | 1つのリビジョンを読み取ります(id はワークフロー名ではなく、特定のリビジョンを指します)。 |
GET | /resources/api/agent/applicantWorkflows/{id}/traffic | このリビジョンのレベルを最近利用した申請者:{"applicantCount": N}。読み取り専用で、公開時の露出度ゲートへの入力です。ワークフローによる振り分けではなく、レベルから算出されます。「危険性」を参照してください。 |
POST | /resources/api/agent/applicantWorkflows/{id}/draft | 公開済み/アーカイブ済みのリビジョンから新しいドラフトを分岐させます。稼働中のワークフローに触れずに反復作業を行う方法です。 |
PUT | /resources/api/agent/applicantWorkflows/{id}/revisionStatus | リビジョンを公開/アーカイブします。リクエストボディは {"revisionStatus":"published"|"archived"|"draft"} です。公開には error 通知がゼロである必要があり、以前に公開されていたリビジョンは自動的にアーカイブされます。⚠️ ライブトラフィックに影響します — 「危険性」を参照してください。 |
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や永続的な環境変数に決して追加しないでください。ゲートが常に開いたままになり、唯一の目的が損なわれます。このトークンを指定するのは、公開する瞬間のコマンドライン上の一度だけであり、それ以外の場所では指定しないでください。
原則
以下の3つの原則は、以降のすべての手順を支えています。それぞれが問題となる箇所では、手順からここに立ち返ります。3つに共通する根幹は、ユーザーの意図とワークスペース内の実在するエンティティが真実であり、あなたの役割はそれらを忠実につなぐことであって、決して創作したり改善したりすることではないということです。
- ユーザーが指定したものを、正確に構築します。 レベル名、ノード構造、分岐ロジック、選択された
kindは、変更の余地がない制約であり、改善のための素材ではありません。自分の推論で、ある選択が冗長または最適でないと判断した場合(多くの場合、レベルやエンジンの挙動に関する誤った前提に基づいています。たとえば、連続するレベルで収集済みのデータが再取得されることはありません。詳しくはreferences/workflow-patterns.mdを参照してください)、指定どおりに構築し、その懸念を報告に記載してください。自分が好む設計に黙って置き換えてはいけません。検証で検出するのは「無効」なものです。「最適でない」ことは「無効」ではなく、設計を変更する許可にはなりません。 - エンティティをつなぎ、所有しないでください。 参照されるすべてのレベル、クライアントリスト、タグは、それを使って構築する前に実在するものとして確認できなければなりません。つまり、ユーザーが指定した名前、
GET /resources/applicants/-/levelsで確認した名前、または(あなた、関連スキル、ユーザーのいずれかによって)明示的に作成される名前である必要があります。根拠のない参照は補完すべき空欄ではなく、停止の理由です。既存のものを再利用するか、作成してもらうか、明示的に保留中としてください。グラフを完成しているように見せるために、もっともらしい名前を決して創作してはいけません(欠落した参照がブロックするのは公開のみで、下書きではないとしても、捏造してよい理由にはなりません)。事前に根拠を確認してください。既存のレベルを読み、質問や名前の創作をする前に実在するものを再利用してください。 - 緑のチェックマークではなく、参照先を目指してください。 構造やビルダーのエラーはあなたが修正し、問題がなくなるまで繰り返してください。ただし、エンティティの欠落エラー(
levelNotFound、tagDoesNotExist、不明なクライアントリスト)を解消できるのは、参照の根拠を確認することだけです。検証を通すために、都合のよいエンティティへ参照先を変更してはいけません。そして望む地図ではなく、実際の状況を報告してください。未解決の参照がある下書きは未完成です。また、既存のエンティティに合わせて変更した構造は、ユーザーのポリシーを変更したことになります。どちらも明確に伝え、問題なく完了したかのように報告してはいけません。
手順
-
ユーザー自身の言葉からワークフローの
kindを特定し、明示してください。 ユーザーがkindを指定していない場合は、仕様のデフォルトであるdefaultです。testまたはactionsを使うのは、ユーザーが明示的に指定した場合に限ります。ユーザーが求めていないkindを推測したり、デフォルトとして選んだり、代わりに指定したりしてはいけません。kindを前提として明示し、そのまま進めてください。たとえば、「kindの指定がないため、defaultとして進めます」 と伝え、ユーザーが確認・修正できるようにしてください。kindを複数選択式の質問にしてはいけません。既存のドラフトに触れないための「安全な場所」として、defaultワークフローの代わりにtestを提案してはいけません。testは申請者ごとの手動テスト実行用で、独立したドラフトを持ち、公開できず、defaultへの昇格経路もありません。既存のdefaultドラフトがあっても、別の場所で作成する理由にはなりません。そのまま上書きしてください(手順 3)。 -
ユーザーのフローチャートを簡潔な仕様に変換します(以下を参照)。ボックス/判断ダイヤモンドごとにノードを 1 つ、矢印ごとにエッジを 1 つ作成します。
idはラベルとして読める名前(country-check、route、idv、reject-regionなど)にします。ユーザーがフローチャートではなくポリシー(「KYC/KYB ワークフローを作成して」など)を提示した場合は、白紙から始めないでください。references/workflow-patterns.md にある標準パイプラインの骨格とプリミティブに沿って分解し、セグメントごとにその骨格を適用します。ユーザーが指定した内容のみを構築し、その上に構築する前に、あらゆるレベル/リスト/タグの参照先を確認してください(原則 1~2)。 -
グラフを検証します: 各エッジの
from/toがノード ID に解決されること、すべてのapplicantLevel/actionApplicantLevelが実在するレベル名を参照していること、すべてのexclusiveChoiceに 1 つ以上の分岐する出エッジ(condition:またはon:)があること、最終拒否ノードにlabelsまたはbuttonIdsがあることを確認します。(レベルと、すべての選択ノード以外のノードには、条件のない出エッジが 1 つだけあります。分岐できるのはexclusiveChoiceのみです。Edge のon:を参照してください。)グラフは有向非巡回フォレストです。エッジは前方にのみ向かい(循環/逆向きエッジは禁止。書類の再提出は逆向きエッジではありません。エンジンがその場で再試行します)、合流や下流ノードの共有は許可され、複数のエントリレベルから独立したフローを開始できます。異なる申請者タイプ(KYC の個人と KYB の企業)をエッジでつないではいけません。申請者のタイプは変更できません。グラフの全ルールは references/workflow-schema.md の Constraints、再提出については references/workflow-patterns.md を参照してください。 -
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py state <name>で対象ワークフローnameの現在の状態を確認し、書き込み方法を選びます: リビジョンがない → 作成(idなしで POST)。ドラフトがすでにある → そのドラフトをその場で更新(そのidを指定して POST。idなしの POST は409になります)。公開済みリビジョンはあるがドラフトがない →${CLAUDE_SKILL_DIR}/scripts/workflow_api.py fork <id>でドラフトを作成するか、新規に POST します。既存のドラフトを上書きするのは通常想定されている操作です。確認せずに行ってください。 空きを探す必要はありません。各kindにドラフトは 1 つだけという仕組みなので、idなしの POST で409が返った場合は、ドラフトのidを指定して再試行してください。ドラフトの削除やアーカイブをユーザーに求めてはいけません。空きを作るために別のkindに移ってはいけません。ドラフトはスキルが複数回の実行を通じて更新していく作業領域です。上書き前に確認を求めず、デフォルトでバックアップを取ることもありません。ユーザーが現在のドラフトを保持するよう明示的に求めた場合に限り、まず${CLAUDE_SKILL_DIR}/scripts/workflow_api.py get <id>で読み取り、JSON 本文をファイルに保存してから上書きします(コマンド末尾にHTTP <code>の行が追加されるため、JSON のみを残してください)。編集する場合は、既存のノード ID とエッジ ID を保持してください。基にするリビジョンをget <id>で取得し、その ID を引き継いで、新しいノード/エッジにのみ新しい ID を割り当てます(エンジンはこれらの ID を使って実行中の処理を照合します。理由は references/workflow-schema.md の Revision continuity を参照してください)。 -
${CLAUDE_SKILL_DIR}/scripts/build_workflow.pyでペイロードを生成します。標準入力に仕様を渡すと、標準出力に完全なペイロードが出力されます。ビルダーは実際のノード型とエッジのconditionAST からペイロードを組み立て、組み込みの既知セットに照らしてノード型、演算子、アクションのtargetTypeを検証します。そのため、誤字や未対応の構成はネットワーク呼び出しの前にここでエラーになります(残りの項目、すなわちレベル、クライアントリスト、ラベルについては、API の検証が正式な判定となります)。その場で更新する場合は、手順 3 に従い、仕様にドラフトのidを設定します。 -
検証します(ドライラン。何も保存されません)。 ペイロードを
${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通知が1つでもあるリビジョンは、API によって公開が拒否されます。${CLAUDE_SKILL_DIR}/scripts/workflow_api.py publish <draft-id>を実行してください。このコマンドが本番露出のゲート(「危険」の項で定義)を管理し、次のいずれかを実行します。- 露出度が低い場合 → 直接公開されます。これで完了です。
- 露出度が高い場合 → 何も変更する前に拒否し、露出数と現在公開中のリビジョンの
id(1コマンドでロールバックできるポイント)を出力します。続行するには、保護されたフローに従います。ドラフトと公開中のリビジョンを比較し、変更内容とその数をユーザーに伝え(「リビジョン 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は決して公開されません。「危険」を参照してください。 -
報告(人が読める識別情報を先に示します)— こうあってほしいと思う姿ではなく、実際の状態を報告してください。未解決の参照や不正な構造があれば明確に示し、正常に完了したかのように報告してはいけません(原則 3)。ワークフローの
name(default/actions/test)とrevisionを先に示します(例:«default» revision 14)。続いてrevisionStatus、ノード数とエッジ数、参照されているレベル名の重複を除いてソートした一覧(スペルミスがわかるようにします)、そしてクリック可能なマークダウンリンクとしてダッシュボードのリンク(ステップ 7)を示します。公開した場合は、その旨と、現在publishedのリビジョン名、自動アーカイブされた以前のリビジョンを記載し、ロールバック用のidを示してください。最後にWorkflow ID: <id>の1行を記載します。生のidを記載するのはここだけです。失敗した場合は、Sumsub のdescription/errorNameをそのまま提示してください(ビルダーの検証エラーでは、すでに正確なメッセージが出力されます)。
コンパクトな仕様形式(標準入力の JSON または YAML)
kindは編集するワークフローを選択します(各種別の意味やリビジョン/ドラフトの仕組みについては 概念 を参照してください)。kindはユーザーの明示的なリクエスト(ステップ 0 を参照)によってのみ設定され、デフォルトはdefaultです。⚠️ 公開後のdefault/actionsは実際のトラフィックを処理します。「危険」の項を参照してください。(スキーマには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 のいずれか1つだけを含める必要があります。ニッチなケースでは、タグ/メモにより詳細なオブジェクト形式も使用できます。
- 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 から出るエッジ(アクションワークフローでは actionExclusiveChoice。reviewDecisions は上流レベルの判断と照合されます)だけです。レベル自身の出辺遷移は、単一かつ無条件です。したがって、レベルの結果に応じて分岐させるには、選択肢を自分で作成します。レベルから exclusiveChoice へ通常のエッジを1本だけつなぎ、on:/condition: による分岐を選択肢の出辺に設定します(宣言順に評価され、最初に一致した分岐が選ばれます)。ビルダーが選択肢を自動生成することはありません。レベルのエッジに on:/condition: が設定されている場合(またはレベルに出辺が2本以上ある場合)は、選択肢を挿入するよう促すメッセージとともに拒否されます。選択肢の出辺では、on: と condition: を併用できます。
判断を省略した場合の動作は、2つのルールで決まります。(1) on: を省略すると、そのエッジは判断を問わず、判断をチェックしません。(2) 分岐直後の選択肢に resubmission を指定する分岐がない限り、再提出者は現在のレベルにとどまります。つまり、実際には on: のないエッジは approved と rejected の両方に対応し、再提出はデフォルトで再試行されます(これはこの2つのルールから導かれる動作であり、保存されたデフォルトのセットではありません)。**再提出の扱いはエンジンに任せてください。ユーザーが繰り返しの試行を制限したい、または別の処理を求めた場合を除き、resubmission を指定しないでください。**標準的なワークフローでは指定しません。エンジンによる自動再試行が、ほとんどのケースで望ましい動作です。指定を求められた場合に限り、references/workflow-patterns.md の サイクルのない反復:再提出ゲート を参照してください(なお、選択肢で resubmission を指定すると、他のエッジの動作が変わります。この相互作用については該当セクションで説明しています)。
例
examples/country-routing.json— エントリーレベル → 適格性ゲート(地域による拒否と IDV に分岐)→ IDV → 2つ目の選択肢 → IDV が拒否された場合の手動レビュー。レベルが2つの選択肢の間にあるため、選択肢を2つ配置する一般的な構成です。examples/action-workflow.json— レベルの完了後にタグとメモを追加する、小規模なアクションワークフローです。examples/aml-routing.json— クライアントリストによる地域ゲートと、applicant.review.rejectLabels(PEP/制裁/不利なメディア情報)に基づく AML 後のルーティングを組み合わせています。containsAnyとタグによる合流を使った、実際の AML ワークフロー構成を反映した例です。
関連項目
- references/workflow-schema.md — 各ノード型の本文、アクションモデル、
ConditionAST と演算子、ライフサイクル、実トラフィックのガードのリファレンスです。 - references/workflow-expressions.md — 式のパス検索用辞書です。
- references/workflow-notices.md — 検証通知のカタログです。
validate/postエンドポイントが返すすべてのnotices[]キーについて、重大度、パラメーター、対処方法(参照情報の確認か、仕様の修正か)を説明しています。受け取った通知はここで確認してください。 - references/workflow-patterns.md — 構成パターンの解説です。KYC/KYB ポリシーを標準的なパイプラインの幹と再利用可能なプリミティブに分解する方法を説明しています(スキーマではなく、設計方針を扱います)。「このノードを修正して」ではなく「ワークフローを作って」という依頼の場合は、ここから始めてください。
sumsub-manage-client-lists— 条件から参照するclientLists.<name>セットを作成してデータを登録します。