
sumsub-create-workflow
Create a Sumsub applicant workflow — verification routing (levels, branches, country/age rules, final-rejection or manual-review steps) or an action workflow (post-verification tagging, notes, source-key changes). TRIGGER on requests to create/build/add a workflow or a flowchart-style routing description. Builds, validates, and saves a draft, then publishes it — gated by live traffic — automatically when the workflow's traffic is low, only after explicit confirmation when it's high. Publishing changes LIVE traffic — see the Danger section. SKIP for editing arbitrary fields of an existing revision, or for questionnaires/levels (separate skills).
- Installs
- 543
- Last 24h
- +16
- Trending rank
- #6803
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/sumsub/agent-skills --skill sumsub-create-workflow- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads sumsub-create-workflow automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Sumsub — Create Workflow
Builds an ApplicantWorkflow JSON payload from a compact node/edge spec, validates it (dry-run), POSTs it as a draft, and then — gated by the workflow's current live exposure — publishes it via PUT /{id}/revisionStatus: directly when exposure is low, or only after explicit confirmation when it's high. Reports the resulting name (kind) / revision / revisionStatus / id. Read the Danger section before publishing anything.
Concepts
A workflow routes applicants through levels and branches. There is exactly one workflow
per kind: default (auto-runs for every verification), actions (auto-runs for applicant
actions), test (isolated; runs only from its draft, launched manually per applicant — not
publishable). Each save creates a new revision of that singleton, never a new workflow.
A revision is a draft — editable, routes no traffic, always safe to create / update /
validate — until it is published, which makes it live for all real production traffic
and auto-archives the previously published revision. test never publishes; it runs from its
draft.
Endpoints
| Method | Path | When |
|---|---|---|
POST | /resources/api/agent/applicantWorkflows | Create (no id) or update a draft by id. Only drafts are editable; a published/archived revisionStatus here is rejected. Always safe — drafts route no traffic. |
POST | /resources/api/agent/applicantWorkflows/-/validate | Dry-run validation. Returns notices[] without persisting. Read-only. |
GET | /resources/api/agent/applicantWorkflows | List workflows (every revision, all statuses). Response is flat: { "items": [...], "totalItems": N, "pageInfo": { "limit", "offset" }, "error": {...}? } — items is top-level (no list wrapper). |
GET | /resources/api/agent/applicantWorkflows/{id} | Read one revision (the id is a specific revision, not the workflow name). |
GET | /resources/api/agent/applicantWorkflows/{id}/traffic | Applicants recently on this revision's levels: {"applicantCount": N}. Read-only; the input to the publish exposure gate. Level-derived, not workflow-routed — see Danger. |
POST | /resources/api/agent/applicantWorkflows/{id}/draft | Fork a new draft from a published/archived revision — the way to iterate on a live workflow without touching it. |
PUT | /resources/api/agent/applicantWorkflows/{id}/revisionStatus | Publish / archive a revision. Body {"revisionStatus":"published"|"archived"|"draft"}. Publishing requires zero error notices and auto-archives the prior published revision. ⚠️ Affects live traffic — see Danger. |
Permission required on the App Token: manageWorkflows. Sandbox tokens typically have it; if you hit 403 Unauthorized (atd), regenerate the token with the right scopes.
⚠️ Danger — publishing affects LIVE production traffic
Workflow revisions are shared across live and sandbox; only applicants are
isolated. Publishing changes the workflow that handles all real production
traffic — a sandbox sbx: token does not make this safe. This is the single
most important fact about this skill. (Drafts, by contrast, route no traffic —
create / update / validate them freely.)
Publishing default/actions is gated by the workflow's current live exposure
— the recent applicant traffic on the revision that is currently published (the
one a publish auto-archives), measured by the workflow_api.py traffic subcommand. The
threshold is 400 recent applicants (override: SUMSUB_PUBLISH_TRAFFIC_THRESHOLD):
Workflow name | Current live exposure | Publishing |
|---|---|---|
default / actions | > 400 recent applicants, or unreadable | Fully guarded: clean validate · diff vs current published · explicit user "yes" · SUMSUB_ALLOW_WORKFLOW_PUBLISH=1 latch |
default / actions | ≤ 400, or no published revision yet | Low-exposure: publish directly — no confirmation, no latch (still report what you did) |
test | — | Not publishable — revisionStatus is immutable (the API rejects the call); it runs from its draft |
The exposure count is level-derived — it counts applicants recently seen on the level names the published revision contains (so revisions sharing level names report overlapping counts), reflecting how busy this workflow's levels are now, not the new revision's blast radius. Phrase it to the user as "the levels in this revision have N recent applicants," never "this workflow handled N." Rules that hold regardless of exposure:
- Publishing is the default end of a build, not a separate request — the gate above decides what it costs (low → direct; high → confirm + latch). The only thing that keeps a build at a draft is the user explicitly opting out ("just save a draft").
- Fail safe on unknown exposure. If the live revision's traffic can't be read (API error), treat it as over-threshold and run the full guarded flow.
- Never switch kinds to dodge the gate. A publish request can't be made "safer"
by retargeting to
test(the API rejects it anyway). Publish the requested kind. workflow_api.py publishis the backstop: it independently re-measures exposure and requiresSUMSUB_ALLOW_WORKFLOW_PUBLISH=1only when exposure is over-threshold or unreadable — letting a low-exposure publish through unlatched.
Auth — App Token + secret (sandbox only)
Each request is signed with App Token + secret (HMAC-SHA256). Full signing details
and 401 debugging: sumsub-api-auth.
⚠️ Sandbox only. A workflow routes real applicants, so production tokens are refused — the scripts reject anything not prefixed
sbx:. Mint a sandbox pair in the dashboard (switch the workspace to Sandbox → App tokens → Create; both are shown once).
| 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.
Not a credential: publishing a high-exposure
default/actionsrevision (live traffic above the threshold, or unreadable) is armed bySUMSUB_ALLOW_WORKFLOW_PUBLISH=1, but that is not a configured env var — it is a per-command arming token you type inline on the publish call (step 8), nothing else. Never add it tosettings.local.jsonor any persistent env: doing so leaves the gate permanently open, which defeats its only purpose. It belongs on exactly one command line, at the moment you publish, and nowhere else.
Principles
These three govern every step below; the procedure points back here where each one bites. They share one spine — the user's intent and the workspace's real entities are the ground truth; your job is to wire them faithfully, never to invent or improve.
- Build exactly what the user specified. Their level names, node structure, branch logic, and chosen
kindare fixed constraints — not raw material to improve. If your own reasoning concludes a choice is redundant or suboptimal — often resting on a wrong assumption about how levels or the engine behave (e.g. chained levels don't re-capture already-collected data — see references/workflow-patterns.md) — build it literally and flag the concern in your report, never silently substitute a design you prefer. Validation catches what's invalid; "suboptimal" is not "invalid," and is never license to change their design. - Wire entities; don't own them. Every level, client list, and tag a node references must resolve to something real before you build on it — a name the user gave you, one you confirmed via
GET /resources/applicants/-/levels, or one explicitly being created (by you, a companion skill, or the user). An ungrounded reference is a stop, not a blank to fill: reuse what exists, get it created, or mark it explicitly pending — never invent a plausible name to make the graph look complete (that a missing reference blocks only publish, not the draft, is no license to fabricate one). Ground proactively — read the existing levels and reuse a real one before asking or inventing. - Aim at the reference, not the green checkmark. Structural/builder errors are yours to fix — iterate until clean. But a missing-entity error (
levelNotFound,tagDoesNotExist, unknown client list) is cleared only by grounding the reference — never by repointing it at a convenient entity to make validation pass. And report the territory, not the map you wish were true: a draft with unresolved references is unfinished, and structure you bent to fit an existing entity is a change to the user's policy — surface both plainly, never as a clean success.
Procedure
-
Resolve the workflow
kindfrom the user's own words, and state it back. If the user named no kind, it isdefault(the spec default). Usetestoractionsonly when the user explicitly names them. Never infer, default to, or substitute a kind the user didn't ask for. State the kind as an assumption and proceed — say e.g. "treating this asdefaultsince you didn't specify a kind" so it's visible and correctable; don't turn the kind into a multiple-choice question. Never offertestas a "safe place to build" adefaultworkflow to avoid touching an existing draft:testis for manual, per-applicant test runs, has its own separate draft, cannot be published, and has no promotion path intodefault. An existingdefaultdraft is never a reason to build elsewhere — just overwrite it (step 3). -
Translate the user's flowchart into the compact spec (below). One node per box / decision diamond, one edge per arrow. Use
ids that read like labels (country-check,route,idv,reject-region). If the user gives a policy rather than a flowchart ("build me a KYC/KYB workflow"), don't start from a blank page — decompose it with the canonical pipeline spine and primitives in references/workflow-patterns.md, then stamp that spine per segment. Build only what the user specified, and ground every level / list / tag reference before building on it (Principles 1–2). -
Validate the graph: every edge
from/toresolves to a node id; everyapplicantLevel/actionApplicantLevelreferences a real level by name; everyexclusiveChoicehas ≥1 branching out-edge (condition:oron:); final-rejection nodes carrylabelsorbuttonIds. (A level — and every non-choice node — has a single, unconditional out-edge; only anexclusiveChoicemay branch — see Edgeon:.) The graph is a directed acyclic forest: edges point only forward (no cycles/back-edges — document resubmission is not a back-edge; the engine retries in place), while fan-in and shared downstream nodes are fine and several entry levels may root independent flows. Never bridge different applicant types (KYC individual vs KYB company) with an edge — an applicant's type can't change. Full graph rules: Constraints in references/workflow-schema.md; resubmission in references/workflow-patterns.md. -
Check current state with
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py state <name>for the target workflowname, then pick the write mode: no revisions → create (POST withoutid); a draft already exists → update it in place (POST with thatid; a no-idPOST would409); a published revision but no draft → seed a draft with${CLAUDE_SKILL_DIR}/scripts/workflow_api.py fork <id>, or just POST a fresh one. Overwriting an existing draft is the normal, expected operation — do it silently. There is no "free slot" to look for: one draft per kind is the whole model, so a409on a no-idPOST means retry with the draft'sid— never ask the user to delete or archive a draft, and never hop to another kind to find room. The draft is a scratch surface the skill evolves across multiple runs, so don't ask before overwriting and don't back it up by default. Only if the user explicitly asks to preserve their current draft, first read it with${CLAUDE_SKILL_DIR}/scripts/workflow_api.py get <id>and save the JSON body to a file (the command appends a trailingHTTP <code>line — keep only the JSON), then overwrite. When editing, preserve existing node and edge ids —get <id>the revision you're basing on and carry its ids through, minting new ids only for new nodes/edges (the engine matches in-flight runs on those ids; rationale in Revision continuity, references/workflow-schema.md). -
Generate payload with
${CLAUDE_SKILL_DIR}/scripts/build_workflow.py— spec on stdin → full payload on stdout. The builder assembles the payload from the real node types and edgeconditionASTs, and validates node types, operators, and actiontargetTypeagainst its built-in known sets — so typos and unsupported constructs error here, before any network call (the API's validate is authoritative for the rest — levels, client lists, labels). Set the draft'sidin the spec when updating in place (step 3). -
Validate (dry-run, stores nothing). Pipe the payload to
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py validate→notices[].info= advisory;warning= non-blocking but usually a real bug;error= publish-blocker. Look up any notice's meaning, severity, params, and how to act in references/workflow-notices.md. Clear a missing-entity error by grounding the reference, not by repointing it to pass validation (Principle 3). Always validate before persisting. -
POST via
${CLAUDE_SKILL_DIR}/scripts/workflow_api.py post— create (noid) or update in place (with theidfrom step 3). Response carries the persisted draft withid,clientId,notices[]. -
Build the dashboard link from
clientIdin the response body:https://cockpit.sumsub.com/checkus/sdkIntegrations/workflows/active/applicant?clientId=<clientId>&sbx=truesbx=truetargets the Sandbox workspace. ⚠️ Not a per-iddeep link — it shows the current draft; tell the user to click promptly. -
Publish — the default end of a build, gated by exposure. Skip only if the user opted out ("just save a draft") — a draft routes no traffic, so it's not a useful end state on its own. The draft must have last validated clean (step 5) — the API refuses to publish a revision with any
errornotice. Run${CLAUDE_SKILL_DIR}/scripts/workflow_api.py publish <draft-id>; it owns the live-exposure gate (defined in Danger) and does one of two things:- Low exposure → it publishes directly; you're done.
- High exposure → it refuses before changing anything, printing the exposure count and the currently-published revision's
id(your one-command rollback point). To proceed, run the guarded flow: diff the draft against that published revision, disclose the change and that count to the user ("makes revision N live for ALL real production traffic; the current published revision — whose levels have ~M recent applicants — will be auto-archived"), get an explicit "yes", then re-run prefixed withSUMSUB_ALLOW_WORKFLOW_PUBLISH=1.
Rollback: re-publish the previously-published
id—SUMSUB_ALLOW_WORKFLOW_PUBLISH=1 ${CLAUDE_SKILL_DIR}/scripts/workflow_api.py publish <previous-published-id>(keep the latch — once it's live again, the revision you're replacing may itself be over-threshold).testis never published — see Danger. -
Report (lead with the human-readable identity) — and report the territory, not the map you wish were true: flag any unresolved reference or bent structure plainly, never as a clean success (Principle 3). Lead with the workflow
name(default/actions/test) andrevision— e.g. «default» revision 14 — thenrevisionStatus; node/edge counts and the sorted unique level names referenced (so misspellings show); the dashboard link (step 7) as a clickable markdown link. If you published, say so, name the now-publishedrevision, note the auto-archived previous revision, and give its id as the rollback point. End with a singleWorkflow ID: <id>line — the one place a raw id belongs. On failure, surface Sumsub'sdescription/errorNameverbatim (builder validation errors already print a precise message).
Compact spec format (JSON or YAML on stdin)
kindselects which workflow you're editing (see Concepts for what each kind means and how revisions/drafts work). It is set only by the user's explicit request (see step 0); the default isdefault. ⚠️default/actionsintercept real traffic once published — see the Danger section. (The schema has atitlefield, but the engine ignores it — the skill neither sets nor relies on it.)
Nodes use the real schema node-type in type; edges carry the real Sumsub
condition AST directly (no expression mini-language). on: is a shorthand for
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)
Node types
A node is { id, type, name?, <body> }, where type is the real schema node
type. Body fields may be flattened (shown below) or written in the real nested
form (applicantLevel: { levelName }).
Standard verification workflow (kind: default|test):
type | Body |
|---|---|
applicantLevel | levelName (string); optional disableGoBack |
exclusiveChoice | — (branches via outgoing edges) |
actions | actions: list (see below) |
manualReview | — |
finalRejection | labels OR buttonIds |
Action workflow (kind: actions only): each action* type mirrors its standard counterpart — actionApplicantLevel, actionExclusiveChoice, actionActions, actionManualReview, actionFinalRejection take the same body as the names without the action prefix. Plus one extra: actionApplicantTransition (levelName — the default-workflow level to hand the verification back into; it must exist in the published default workflow, or validate raises missingLevelsForTransition).
action* types are valid only inside an action workflow (a graph that runs after a primary verification — typically tagging / noting / changing source key, or transitioning the applicant back into default); standard types only in default/test. Mixing them is rejected; the builder catches it before POST.
Actions block
Inside an actions or actionActions node:
- 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
Each item must contain exactly one of: tag, note, sourceKey. Tag/note also take a
richer object form for the niche cases:
- tag: { add: ["VIP"], remove: ["pending"], target: applicantAction }
- note: { text: "Auto-note", target: applicantAction }
target(targetType) isapplicantby default.applicantActiontargets the triggering action and is only valid in an action workflow (kind: actions).- Not supported:
kytCase(postponed — no public API for itsblueprintIdyet),riskScore,recheck. (The oldriskLevelaction never existed — removed.)
Edge conditions (condition:)
An edge may carry a condition: — the real Sumsub condition AST, written directly (there is no expression mini-language):
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>"}— an expression path, verbatim. Anything the engine accepts works, including bracket/quoted segments:applicant.metadata["balance"],clientLists["luhansk_people's_republic"]. It's the left side of a comparison, and also the right side for field-to-field and client-list checks ({exp: "clientLists.high_risk"}).{lit: "<json>"}— a literal, supplied already JSON-encoded as a string (the form the API stores):"\"USA\"","3","true","[\"UZB\", \"DEU\"]". An un-encoded literal ({lit: "USA"}) is rejected by the API withsyntaxError, so the encoding is required.opis one of the comparison operators (eq ne lt lte gt gte in notIn contains notContains containsAny containsAll startsWith endsWith match empty notEmpty eqIgnoreCase …; full set in references/workflow-schema.md). The builder validates everyopagainst its known set and rejects unknown or reserved ones (call).- Negation is expressed with the
not*operators (notIn,notContains,ne,notEmpty, …) — do not set anegateflag; a top-levelCondition.negateis rejected (UI-unsupported).
Client lists (
clientLists.<name>) are tenant-defined named lists, used as an expression RHS within/notIn/containsAny. This skill does not create or populate them — that'ssumsub-manage-client-lists. An unknown list validates as aninvalidExpressionerror notice (a missing-entity error, likelevelNotFound) — the construct is valid, the list just isn't defined in that workspace.
The full Condition/And/Criterion AST, literal-encoding rules, and operator list live in references/workflow-schema.md; valid exp paths are in references/workflow-expressions.md.
Edge on: (review-decision routing)
on: approved gates a transition on a level's review decision (approved / rejected / resubmission; pass an array for several) — a shorthand for the real reviewDecisions: field. on:/condition: are honored only on edges leaving an exclusiveChoice (or actionExclusiveChoice in an action workflow; the reviewDecisions match the upstream level's decision); a level's own out-edge is a single, unconditional transition. So to branch on a level's outcome you author the choice yourself: point the level at an exclusiveChoice with one plain edge, then put the on:/condition: branches on the choice's out-edges (evaluated in declared order, first match wins). The builder does not synthesize choices — it rejects on:/condition: on a level edge (and a level with >1 out-edge), with a message telling you to insert the choice. on: and condition: can coexist on a choice's out-edge.
Two primitives govern omitted decisions: (1) omitting on: makes an edge decision-agnostic — it doesn't check the decision; (2) a resubmitter stays on its level unless some branch on the immediate post-level choice names resubmission. Together, a no-on: edge in practice serves approved + rejected while resubmission retries by default (it's a deduction from these two, not a stored default set). Leave resubmission to the engine: don't name resubmission anywhere unless the user explicitly asks to cap or otherwise act on repeated attempts. It is not part of a standard workflow — the engine's automatic retry is what almost everyone wants. Only if asked, see Iteration without cycles: the resubmission gate in references/workflow-patterns.md (and note: naming resubmission on a choice changes how its other edges behave — that section explains the interlock).
Worked examples
examples/country-routing.json— entry level → eligibility gate (region-reject vs IDV) → IDV → a second choice → manual-review on a rejected IDV. Two choices, because a level sits between them (the most common topology).examples/action-workflow.json— small action-workflow that tags and notes after a level completes.examples/aml-routing.json— client-list geo gate + post-AML routing onapplicant.review.rejectLabels(PEP / SANCTIONS / ADVERSE_MEDIA) withcontainsAnyand tag-driven fan-in (mirrors real-world AML topologies).
See also
- references/workflow-schema.md — reference for every node type's body, the action model, the
ConditionAST + operators, the lifecycle, and the live-traffic guard. - references/workflow-expressions.md — the expression-path lookup dictionary.
- references/workflow-notices.md — the validation-notice catalog: every
notices[]key thevalidate/postendpoints return, with severity, params, and how to act (ground a reference vs. fix the spec). Look up any notice you get here. - references/workflow-patterns.md — composition patterns: how to decompose a KYC/KYB policy into the canonical pipeline spine and reusable primitives (strategy, not schema). Start here when the ask is "build me a workflow" rather than "fix this node".
sumsub-manage-client-lists— create and populate theclientLists.<name>sets a condition references
FAQ
What does the sumsub-create-workflow skill do?
Create a Sumsub applicant workflow — verification routing (levels, branches, country/age rules, final-rejection or manual-review steps) or an action workflow (post-verification tagging, notes, source-key changes). TRIGGER on requests to create/build/add a workflow or a flowchart-style routing description. Builds, validates, and saves a draft, then publishes it — gated by live traffic — automatically when the workflow's traffic is low, only after explicit confirmation when it's high. Publishing changes LIVE traffic — see the Danger section. SKIP for editing arbitrary fields of an existing revision, or for questionnaires/levels (separate skills).
How do I install sumsub-create-workflow?
Run npx skills add https://github.com/sumsub/agent-skills --skill sumsub-create-workflow in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/sumsub-create-workflow/ (personal) or .claude/skills/sumsub-create-workflow/ (project).
Which AI agents can use sumsub-create-workflow?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is sumsub-create-workflow safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains sumsub-create-workflow?
It is published by sumsub in sumsub/agent-skills. It has 543 recorded installs.
More from sumsub/agent-skills
sumsub-api-auth
sumsub/agent-skills
Authenticate to the Sumsub API with an App Token + secret key (HMAC-SHA256 request signing). TRIGGER when the user asks to "call / sign / authenticate Sumsub API requests", debugs 401 Unauthorized / signature errors against api.sumsub.com, or needs a working request example with X-App-Token / X-App-Access-Sig / X-App-Access-Ts headers. SKIP only when a more specific skill in this repo (questionnaire/level/workflow/POA-preset/generic) already covers the user's actual task — those skills sign requests the same way and only need this one for auth deep dives.
sumsub-api-generic
sumsub/agent-skills
Catch-all fallback for any Sumsub API task that does NOT match a more specific skill (e.g. create-sumsub-level, sumsub-create-questionnaire, sumsub-api-auth). TRIGGER when the user wants to call, inspect, or debug a Sumsub API endpoint not otherwise covered — fetching applicants, listing levels, reviewing AML hits, exporting data, generating SDK tokens, anything against api.sumsub.com. The procedure — locate the right endpoint in the OpenAPI schema, read its request/response shape, build the payload, sign with App Token, and validate. SKIP whenever a narrower Sumsub skill already covers the request.
sumsub-check-skills-version
sumsub/agent-skills
Verify that the locally installed Sumsub agent-skills package is compatible with the published version before doing any Sumsub work. TRIGGER at the start of any task that touches Sumsub — Sumsub Dev MCP tools (mcpSumsubDev), KYC/AML workflows, applicants, checks, transactions, verification levels, verification links, questionnaires, fraud network, VASP lists, or anything Sumsub-related — so the user is warned before a stale skills package produces wrong results. Also use this skill when the user explicitly asks "are my Sumsub skills up to date / current", "is there a newer version of the Sumsub skills", or similar. Skip the actual update (the user runs npx skills add sumsub/agent-skills --all themselves) and skip any other Sumsub API or entity task — those have their own skills.
sumsub-create-poa-preset
sumsub/agent-skills
Create or update a Sumsub Proof-of-Address (POA) preset. POST /resources/api/agent/poaStepSettings to create new, PATCH same path to update (id in body), GET /resources/api/agent/poaStepSettings/{id} to read one back. TRIGGER when the user asks to "create / add / build / configure / update / edit a POA preset" or "PoA step settings", configure which proof-of-address document types are accepted (utility bills, bank statements, tax bills, etc.), set validity periods per provider type, enable POI-as-POA (accept identity doc as proof of address), tune the cross-validator (name/address fuzzy match between POI and POA), or add per-country POA overrides. SKIP for attaching a preset to a level (set poaStepSettingsId on the level instead, via sumsub-create-level), or for non-POA presets (cross-check presets, permission presets, etc.).
sumsub-manage-webhooks
sumsub/agent-skills
Manage Sumsub clientWebhooks (event subscriptions for applicantReviewed / applicantPending / kytTxn / etc.) — reads via /resources/api/clientWebhooks, writes via /resources/api/agent/clientWebhooks. Sandbox only — production webhooks must be created by a human directly in the Sumsub dashboard. TRIGGER when the user asks to "list / retrieve / show webhooks", "create / add / register a webhook", or "update / edit / change a webhook target / event list / secret / signature algorithm" against their sandbox tenant. SKIP for production webhook setup (refer the user to the dashboard), for unrelated webhook surfaces (Stripe / videoIdent / Fireblocks / NFC / partner-specific receive paths under /resources/webhooks/...), for testing one-off delivery (use the inspectionCallbacks/testWebhook endpoint directly), and for KYT-only webhook routing (that's managed in the Sumsub dashboard's KYT section). The public API does not expose delete or per-webhook delivery stats — for those, refer
sumsub-integrate-websdk
sumsub/agent-skills
End-to-end recipe for adding Sumsub KYC to a website or web app via the Sumsub WebSDK. TRIGGER when the user asks to "integrate / embed / add Sumsub", "show the KYC widget", "add WebSDK", "verify users with Sumsub on the frontend", supplies an existing levelName they want to plug into a page, or asks how to wire up access tokens / lifecycle events / webhooks for Sumsub verification in an arbitrary project. Covers the whole loop — level setup, server-side access-token signing, snsWebSdk init (vanilla canonical, React recipe), client lifecycle events, token refresh, source-of-truth via webhooks + applicant GET, sandbox testing, go-live checklist. SKIP for building the level/questionnaire/POA-preset payload itself (use the sibling skills), or for backend-only API calls with no frontend (use sumsub-api-generic).
Popular productivity & automation skills
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
lark-doc
open.feishu.cn
飞书云文档(Docx / Wiki)内容操作:读取、创建、编辑文档,插入或下载图片附件,以及操作思维笔记。用户提供文档 URL/token(包括 doubao.com 的 /docx/、/wiki/)时使用;按 URL 路径/token 而非域名路由;/page/ 是妙搭应用,非飞书云文档。文档内嵌资源按读取参考中的统一规则分流。独立评论操作走 lark-drive;随正文读取评论使用 docs +fetch。表格或 Base 内部数据操作不在本 skill。
lark-base
open.feishu.cn
飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、应用模式(BaseApp/AppMode 页面与组件)、Workspace 目录、workflow、角色权限、模板中心(多维表格模板分类/列表/搜索);遇到 Base/多维表格/bitable、BaseApp/AppMode、/base/ 或 /app/ 链接时使用。BaseApp 不走 lark-apps;文件导入/导出转 lark-drive,认证/授权转 lark-shared。
lark-drive
open.feishu.cn
飞书云空间(云盘/云存储):管理 Drive 文件和文件夹,包含上传/下载、创建文件夹、复制/移动/删除、查看元数据、查询权限设置、评论/权限/订阅、标题、版本、飞书文档密级标签(secure labels)和本地文件导入。用户需要整理云盘目录、处理云空间资源 URL/token、判断链接类型/真实 token/标题,或导入 Word/Markdown/Excel/CSV/PPTX/.base 为 docx/sheet/bitable/slides 时使用;doubao.com 云空间 URL/token 也按资源路径和 token 路由,不回退 WebFetch。不负责:文档内容编辑(走 lark-doc)、表格/Base 表内数据操作(走 lark-sheets/lark-base)、知识空间节点/成员管理(走 lark-wiki)、原生 Markdown 文件读写/patch/diff(走 lark-markdown)。
lark-shared
open.feishu.cn
Use for lark-cli setup/auth tasks: auth login/status/logout, user vs bot identity, business-domain permissions (--domain, including all/docs/drive), missing scopes, revoking authorization, or handling notice JSON.
lark-im
open.feishu.cn
飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件、管理表情回复、发送应用内/短信/电话加急、发送和处理交互卡片(Interactive Card)、监听卡片按钮回调(card.action.trigger)。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据、管理 Feed 置顶(添加/移除/查询置顶会话)、管理标签数据、处理卡片回调时使用。