Sumsub Conformance
Check whether a tenant's DEPLOYED Sumsub config actually satisfies a regulation/policy document — tracing each requirement to where it is collected, scored, and ENFORCED, and flagging "collected-but-not-enforced" gaps. TRIGGER when the user has a regulation/policy/requirements doc (PDF or text) and wants to verify the live config matches it, audit a client's setup against compliance rules, "does my config satisfy this regulation", "check conformance / gap analysis", or close the loop after configuring with the create-* skills. SKIP for building config (sumsub-create-*) or for generating a config plan from a regulation (sumsub-analyze-regulation). For pure hygiene linting with no regulation, run this skill's bundled lint_config.py sub-pass directly.
- Skill ID
- sumsub/agent-skills/sumsub-conformance
- Publisher
- sumsub
- Repository
- agent-skills
- Installs
- 0
- Files
- 24
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
sumsub/agent-skills/sumsub-conformanceInstalls these files- SKILL.md
- examples/audit-input-dirty.json
- examples/audit-input.json
- examples/cfd-requirements.json
- examples/fiu-india-requirements.json
- examples/fiu-india-vasp-mapped.json
- examples/sample-graph.json
- examples/sample-requirements.json
- examples/vasp-graph.json
- references/conformance-method.md
- references/lint-rules.md
- references/requirements-schema.md
- references/rules.json
- scripts/artifact_paths.py
- scripts/gen_lint_docs.py
- scripts/graph_summary.py
- scripts/lint_config.py
- scripts/render_regulation.py
- scripts/report.py
- scripts/resolve_graph.sh
- scripts/sumsub_curl.sh
- scripts/test_lint.py
- scripts/test_trace.py
- scripts/trace.py
What this skill tells the agent
Sumsub — Conformance (regulation ↔ deployed config)
Traces every requirement of a regulation through the live config graph and answers, per requirement: collected? → scored? → enforced? The headline finding it surfaces — that nothing else does — is COLLECTED-BUT-NOT-ENFORCED: the config gathers and scores the data a regulation needs, then doesn't act on it (e.g. an appropriateness questionnaire that's scored but never routed).
This is an advisory gap assistant, not a compliance guarantee. It verifies the config-representable parts deterministically and honestly delimits the rest (semantic intent = judgment; SDK/platform outcomes = out of scope). Get a human to sign off.
When to use
- Existing client: "here's our regulation, here's our tenant — what's actually enforced?"
- New client who configured Sumsub with the create- skills: close the generate → verify* loop — did the assembled config end up enforcing the regulation it was built from?
Endpoints (read-only)
All via scripts/sumsub_curl.sh (App-Token HMAC). resolve_graph.sh wraps these:
| Purpose | Method + Path |
|---|---|
| Levels (find target) | GET /resources/applicants/-/levels |
| Workflows (auto-find the one referencing the level) | GET /resources/api/applicantWorkflows + GET /resources/api/applicantWorkflows/{id} |
| Questionnaire content + scores | GET /resources/api/questionnaires/{id} |
| PoA / cross-check preset | GET /resources/api/poaStepSettings/{id} · GET /resources/api/crossCheckPresets/{id} |
Entitlements (allowedChecks keys) | GET /resources/api/agent/settings/bgCheckTargets |
Auth — App Token + secret (sandbox only)
This skill talks to the public Sumsub API and signs each request per the authentication reference. The how-it-works writeup lives in `sumsub-api-auth`.
⚠️ Sandbox tokens only. Read-only, but still: do not accept a production App Token. If the user offers one, refuse and ask for a sandbox pair at <https://cockpit.sumsub.com/checkus/home?sbx=true> (Connect Sumsub to your AI agent -> Build & configure -> Generate token). The helper rejects tokens that don't start with sbx:.| Var | Example |
|---|---|
SUMSUB_APP_TOKEN | sbx:... |
SUMSUB_SECRET_KEY | paired secret |
SUMSUB_BASE / SUMSUB_ENV=dev | optional; dev targets dev-api.sumsub.com (internal). |
Procedure
Use the scripts — do not hand-roll the deterministic steps. The whole point of this skill is that resolution and the verdict are deterministic, not re-derived by eyeball each run: - Resolve the graph ONLY via `resolve_graph.sh`. Do not call/resources/...endpoints directly, list levels by hand, or strip theHTTP <code>trailer yourself — the script does all of that and emits one clean graph. - If the graph can't be resolved, STOP — never work around the failure. A401/403, a404, or0 levels/ "level not found" fromresolve_graph.shmeans the run cannot proceed. Report the failure plainly (likely a bad/non-sandbox token or wrong level name) and stop. Do not editresolve_graph.sh(or any script) to route around the error, add a by-id fallback, retry a different endpoint, or otherwise improvise a graph — and never emit a report, bucket counts, or a CONFORMANT verdict from a partial or substituted graph. No resolved graph → no findings. - Derive the verdict ONLY from `trace.py` / `report.py`. Do not read the workflow/questionnaire JSON by eye and decide "enforced / not enforced" yourself — that re-introduces variance and hallucination. TheCOLLECTED-NOT-ENFORCEDfinding must come from the engine. - If a script already ran, trust its output — do not re-verify it with manual API calls. - To inspect the graph for the Map step, run `python3 scripts/graph_summary.py "$CONFIG"`. Do not hand-iterate the graph JSON:questionnaires/poaPresets/crossCheckPresetsare dicts keyed by id (iterating yields id strings →'str' has no attribute 'get') andentitlementsis a list.graph_summary.pyprints the section/item indices + scores you need, correctly. The agent's judgment belongs to two steps only: ingest (reading the regulation) and map (matching requirements to deployed config elements — questions, docSets, fields, countries, entitlements). Everything else is the scripts.
Artifacts — MANDATORY location & naming. Every run MUST write its artifacts into the same directory as the source regulation file, named from its stem (filename without extension). Never save in the cwd or under improvised names. Derive the exact paths once, up front: ``eval "$(python3 scripts/artifact_paths.py "<path/to/RegFile.pdf>")" # $REQUIREMENTS = <dir>/<stem>_regulations.json (the requirements you build in steps 1+3) # $CONFIG = <dir>/<stem>_config.json (resolve_graph output, step 2) # $REPORT = <dir>/<stem>_report.md (the rendered report, step 6)`e.g.Level4regulations.pdf→Level4regulations_regulations.json,Level4regulations_config.json,Level4regulations_report.md. Use$REQUIREMENTS/$CONFIG/$REPORT` verbatim in the steps below.
- Ingest the regulation (judgment). Just Read the document with the Read tool — it reads PDFs natively (renders pages + extracts text), so nothing needs to be installed. For a PDF over ~10 pages, Read it in page ranges (the Read tool's
pagesparameter, ≤20 pages per call). Reading visually is equal or better than a text extractor — it preserves tables, headings and layout that flat-text extraction loses. Optional, only if already installed and never a blocker:pypdf/pdftotextcan pull a long, text-heavy PDF in one shot, andscripts/render_regulation.py(PyMuPDF) pre-renders a scanned/image-only PDF to PNGs for explicit DPI control — see `references/conformance-method.md` step 1. If a library is absent, just Read the PDF directly. Then extract requirements and write them to `$REQUIREMENTS` (the<stem>_regulations.jsonbeside the source — see the Artifacts rule above), per `references/requirements-schema.md`: each ={id, source, text, type, enforceable, …}. Always capture `source` — the citation into the original document (section number / heading / page, e.g."§5.9.2","Section 2 — Scoring Result","p.21"); the report leads with it so findings trace back to the regulation, not to an artificial id. Mark outcomes that live in SDK/platform/CRM asenforceable: sdk|platform. Show the extracted requirements to the user and confirm before tracing — this is the highest-risk step. - Resolve the deployed graph (deterministic).
bash scripts/resolve_graph.sh <levelNameOrId> > "$CONFIG"(level + questionnaires-with-scores + presets + auto-found workflow + entitlements). This one command replaces any manual level-listing / curl / HTTP-trailer stripping — don't do those by hand. - Map (judgment). First inspect the graph: `python3 scripts/graph_summary.py "$CONFIG"` — it prints questionnaires with
[section]/[item]indices + option scores, docSets, APPLICANT_DATA fields, geo, entitlements, and the workflow (don't hand-iterate the JSON). Then for each requirement pick the righttypeand fill itsmatch— not everything is a questionnaire question. The per-typematchshapes are in `references/requirements-schema.md`:
- questionnaire question/score →
match: {questionnaire, section, item}(+expectScores); - document collected →
match: {docSet: "IDENTITY", types: [...]};
More from sumsub
Use this skill in a project
Open any RiverX project, search the Skills panel for sumsub/agent-skills/sumsub-conformance, and install it in one click.
