title: Regnify Tool: analyze_cert_gap¶
Regnify Tool: analyze_cert_gap¶
Purpose¶
analyze_cert_gap runs CMFAS certification gap analysis for a representative AND persists the per-module status into the Rep Profile. It compares a rep's passed CMFAS modules against the modules required for their declared regulated activities, identifying which modules are still missing and whether the rep is eligible for appointment.
The gap engine is a deterministic rule-based system (CertAnalyzerAgent.analyze()) -- no LLM call. Persistence uses the NestJS GraphQL mutation upsertCmfasModuleStatus with the caller's bearer token, so row-level authorization is preserved.
Signature¶
analyze_cert_gap(ctx, rep: RepProfileRef, activities: list[str], act_type: str, passed_modules: list[str]) -> dict
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
rep |
{"kind": "rep_profile", "id": <int>} |
Yes | Tagged rep-profile reference. id must be the numeric rep_profile_id (not user_id, not UUID). rep.normalised_id converts string IDs to int via int() -- but prefer passing integers. |
activities |
list[str] |
Yes | Regulated activity keys the rep is or will be performing. Examples: ["dealing_in_securities"], ["advising_on_corporate_finance", "fund_management"]. The tool passes these to the CertAnalyzerAgent which maps activities to required module sets. |
act_type |
str |
Yes | Which Act governs the activities. Must be "faa" (Financial Advisers Act) or "sfa" (Securities and Futures Act). This determines the module requirement mapping. |
passed_modules |
list[str] |
Yes | CMFAS module codes the rep has already passed. Examples: ["M1A", "M6A"], ["RES-1A", "RES-2B", "M5"]. Case-sensitive. |
act_type Values¶
| Value | Act | Module Requirement Source |
|---|---|---|
"faa" |
Financial Advisers Act (FAA) | FAA-N26 (Notice on Requirements for Representatives of Licensed Financial Advisers) |
"sfa" |
Securities and Futures Act (SFA) | SFA 04-N22 (Notice on Competency Requirements for Representatives of CMS Licence Holders) |
Passing the wrong act_type will map activities against the wrong module requirement table. If uncertain which Act applies, ask the user or use search_mas_knowledge to determine the correct Act for the rep's activities.
CMFAS Module Codes (Post-2024 RES Regime)¶
The following module codes are recognized by the CertAnalyzerAgent. This is the post-April-2024 vocabulary (SFA 04-N09 superseded by SFA 04-N22):
Core / Legacy Modules (Still Valid)¶
| Code | Full Name | Typical Applies To |
|---|---|---|
| M1A | Rules and Regulations for Dealing in Securities | CMS reps dealing in securities |
| M5 | Rules and Regulations for Financial Advisory Services | FA reps under FAA |
| M6A | Securities Products and Analysis | CMS reps advising on securities |
| M8A | Collective Investment Schemes | CMS/FA reps dealing in CIS |
| M8 | Collective Investment Schemes (legacy, pre-M8/M8A split) | Legacy only |
| M9 | Life Insurance and Investment-Linked Policies | FA reps advising on life insurance |
| M9A | Life Insurance and Investment-Linked Policies II | FA reps (advanced life insurance) |
RES Regime Modules (Post-2024)¶
| Code | Full Name | Typical Applies To |
|---|---|---|
| RES-1A | Capital Markets and Products | CMS reps -- foundational |
| RES-2A | Securities and Futures Product | CMS reps dealing in securities/futures |
| RES-2B | CIS Product | CMS reps dealing in CIS |
| RES-3 | Corporate Finance Advisory | CMS reps advising on corporate finance |
| RES-4 | Fund Management | CMS reps managing funds |
| RES-5 | Leveraged Foreign Exchange Trading | CMS reps trading leveraged FX |
CM-EIP / CM-SIP / CM-CIS Modules¶
| Code | Full Name | Typical Applies To |
|---|---|---|
| CM-EIP | Examinations for Exempt Investment Product Representatives | FA reps exempt from full CMFAS (EIP regime) |
| CM-SIP | Examinations for Specified Investment Product Representatives | FA reps dealing in SIPs |
| CM-CIS | Examinations for CIS Representatives | FA reps under FAA dealing in CIS |
Activity-to-Module Mapping¶
The deterministic CertAnalyzerAgent maintains a mapping from (activity, act_type) pairs to required module sets. The exact mapping is server-side and not exposed to the LLM at the tool level. When you call analyze_cert_gap, the engine:
- Maps each
activities[i]to its required module set based onact_type. - Compares the required modules against
passed_modules. - Returns which modules are still missing (
missinglist) and which are satisfied (passedlist). - Determines
eligible--trueif the rep has all required modules for all declared activities.
Return Shape (Success)¶
{
"passed": ["<module codes that are satisfied>"],
"missing": ["<module codes still required>"],
"eligible": <bool>,
"explanation": "<human-readable explanation of the gap analysis>",
"persisted": true
}
Field Details¶
| Field | Type | Description |
|---|---|---|
passed |
[str] |
Subset of required modules that the rep has already passed (intersection of required modules and passed_modules input). |
missing |
[str] |
Required modules NOT in the passed_modules input. These are the gaps the rep must fill. |
eligible |
bool |
true if the rep has all required modules for all declared activities. true = no gaps = eligible for appointment for those activities. |
explanation |
str |
Human-readable summary of the analysis. Includes which activities require which modules, which are satisfied, and what remains. |
persisted |
bool |
Always true on the success path. The tool unconditionally persists per-module status via upsertCmfasModuleStatus after analysis completes. |
Return Shape (Errors)¶
On input-validation ValueError (e.g., rep.id <= 0), the tool returns:
{"error": "analyze_cert_gap: <ValueError message>"}
On GraphQL transport errors or CertAnalyzerAgent failures, exceptions propagate and are converted to "error: <msg>" tool-result strings by the chatbot loop.
Persistence Behaviour¶
The tool unconditionally persists after each analysis call. It calls upsertCmfasModuleStatus for each module in both passed and missing lists, recording the status against the rep's CmfasModuleStatus rows. This means:
- After calling
analyze_cert_gap, the rep's CMFAS module statuses in the database are updated. - The rep's health badge (GREEN/AMBER/RED) in
get_rep_registerrecomputes server-side immediately -- no separate badge-refresh call is needed. - Persistence uses the caller's bearer token from
ctx.access_token, preserving row-level authorization. Only users with permission to write to the rep's module statuses can successfully persist.
CMFAS Pass Validity¶
CMFAS exam passes do NOT expire by time alone. Once a module is passed, it remains valid indefinitely under normal circumstances. However, module validity can be affected by:
- Regulatory framework changes: When MAS revises the competency framework (as happened with SFA 04-N09 being superseded by SFA 04-N22 in April 2024), existing module mappings may change. Old module codes may no longer satisfy new activity requirements.
- New regime transitions: The RES regime (RES-1A through RES-5) replaced parts of the older M1A/M6A/etc. framework. Reps who passed under the old regime may need to bridge to the new regime.
Post-Role-Change Gap Detection¶
When a rep's role changes (new regulated activities added to their scope), re-run analyze_cert_gap:
- Get the rep's existing passed modules (from a prior
analyze_cert_gapcall or fromget_rep_registerhealth data). - Call
analyze_cert_gapwith the new activities list + existing passed_modules. - The tool compares the new required modules against the existing passed modules.
- Any newly required modules that are not in the passed set appear in
missing.
This detects gaps introduced by role expansion without requiring the user to manually track module requirements.
Use Cases¶
- Pre-appointment check: Before appointing a rep, check if they have all required CMFAS modules for their declared activities.
- Role change gap detection: Rep is taking on new activities -- identify which new modules they need.
- Record exam results: User has new exam results to record -- call with updated
passed_modulesto persist and re-analyze. - Compliance audit: Verify that all RED-flagged reps in
get_rep_registerhave their specific module gaps identified.
Combination Patterns¶
- get_rep_register + analyze_cert_gap: Get the roster, identify RED reps (CMFAS gaps), then for each RED rep, call
analyze_cert_gapto determine exactly which modules are missing. - analyze_cert_gap + search_mas_knowledge: After identifying missing modules, search the KB for exam details, syllabus, and registration procedures for those specific modules.
Important Rules¶
- rep.id must be the numeric rep_profile_id -- not a user_id, not a UUID. Get numeric IDs from
get_rep_register. - act_type must be "faa" or "sfa" -- no other values accepted. If uncertain, ask or search the KB.
- Module codes are case-sensitive -- use the exact codes listed above (e.g.,
"M1A"not"m1a","RES-1A"not"RES1A"). - Persistence is unconditional -- calling this tool writes to the database. Only call when the user intends to record or check module status.
- No LLM in the gap engine -- the analysis is deterministic. The
explanationstring is generated by the rule engine, not the chatbot LLM. - Health badge updates automatically -- after
analyze_cert_gappersists,get_rep_registerreflects the new status immediately.