How to Build a KYC verification Agent Using CrewAI in TypeScript for wealth management
A KYC verification agent for wealth management takes client identity data, checks it against policy and external sources, and returns a structured decision: pass, fail, or needs human review. It matters because onboarding delays kill conversion, and weak KYC creates compliance exposure under AML, sanctions, suitability, and record-keeping rules.
Architecture
- •
Client intake layer
- •Collects name, DOB, address, tax ID, source-of-funds fields, and beneficial ownership data.
- •Normalizes inputs before the agent sees them.
- •
Verification tools
- •Calls your internal CRM, document service, sanctions screening API, PEP/adverse media provider, and address validation service.
- •Each tool should return typed JSON, not free text.
- •
CrewAI agent
- •Uses a focused
Agentwith strict instructions for KYC decisioning. - •Produces a structured assessment and escalation rationale.
- •Uses a focused
- •
Workflow orchestration
- •Uses a
Crewwith one or more agents to separate extraction, verification, and compliance review. - •Keeps the process auditable.
- •Uses a
- •
Audit and evidence store
- •Persists every input, tool call, model output, timestamp, and final decision.
- •Required for wealth management exams and internal QA.
- •
Human review queue
- •Routes edge cases to compliance analysts.
- •Prevents the model from making unsupported approvals.
Implementation
1) Install CrewAI for TypeScript and define your types
You want strong typing around KYC outcomes. In wealth management, “almost correct” is useless if you cannot defend the decision later.
// types/kyc.ts
export type KycDecision = "approved" | "rejected" | "manual_review";
export interface KycInput {
fullName: string;
dateOfBirth: string;
address: string;
taxId?: string;
countryOfResidence: string;
sourceOfFunds?: string;
}
export interface KycResult {
decision: KycDecision;
riskScore: number;
reasons: string[];
missingFields: string[];
}
2) Create tools for screening and evidence retrieval
CrewAI agents should not hallucinate verification results. They should call tools that return deterministic data from your systems of record.
// tools/kyc-tools.ts
import { Tool } from "@crewai/types";
export const sanctionsScreenTool = new Tool({
name: "sanctions_screen",
description: "Checks the client against sanctions lists",
execute: async (input: { fullName: string; dateOfBirth?: string }) => {
// Replace with real API integration
return {
match: false,
listHits: [],
checkedAt: new Date().toISOString(),
};
},
});
export const pepScreenTool = new Tool({
name: "pep_screen",
description: "Checks the client against PEP and adverse media sources",
execute: async (input: { fullName: string; countryOfResidence: string }) => {
return {
pepMatch: false,
adverseMediaRisk: "low",
checkedAt: new Date().toISOString(),
};
},
});
export const crmLookupTool = new Tool({
name: "crm_lookup",
description: "Fetches existing client onboarding records",
execute: async (input: { fullName: string; taxId?: string }) => {
return {
existingClient: false,
priorKycStatus: null,
checkedAt: new Date().toISOString(),
};
},
});
3) Build the agent and crew
Use a narrow system instruction. The agent should classify based on evidence only. Do not let it invent missing identity attributes or override policy thresholds.
// kyc-agent.ts
import { Agent, Crew } from "@crewai/core";
import { sanctionsScreenTool, pepScreenTool, crmLookupTool } from "./tools/kyc-tools";
import type { KycInput } from "./types/kyc";
export function buildKycCrew(input: KycInput) {
const kycAgent = new Agent({
role: "KYC Verification Analyst",
goal:
"Verify client identity and produce an auditable KYC recommendation for wealth management onboarding.",
backstory:
"You assess identity data using only provided evidence. You must flag missing fields, policy conflicts, sanctions risk, PEP risk, and any need for manual review.",
tools: [sanctionsScreenTool, pepScreenTool, crmLookupTool],
verbose: true,
allowDelegation: false,
memory: false,
maxIter: 3,
instructions:
"Return a concise assessment with decision, risk score from 0 to 100, reasons array, and missingFields array.",
});
const crew = new Crew({
agents: [kycAgent],
tasks: [],
verboseOutput: true,
});
return crew;
}
4) Execute the workflow and persist the result
This is where you wire the agent into your onboarding service. Save both raw evidence and final output so compliance can reconstruct the path later.
// run-kyc.ts
import { buildKycCrew } from "./kyc-agent";
import type { KycInput } from "./types/kyc";
async function run() {
const input: KycInput = {
fullName: "Amina Patel",
dateOfBirth": "1988-04-11",
address": "10 King Street, London",
taxId": "GB123456789",
countryOfResidence": "GB",
sourceOfFunds": "Salary and investment income",
};
const crew = buildKycCrew(input);
const result = await crew.kickoff({
input,
});
console.log(JSON.stringify(result.output ?? result.raw ?? result, null ,2));
// Persist result to your audit store here.
// Store input snapshot + tool outputs + model output + timestamp + reviewer id if escalated.
}
run().catch((err) => {
console.error(err);
process.exit(1);
});
If you want a cleaner production pattern, wrap kickoff() in a service that validates inputs with Zod before execution. That keeps malformed onboarding payloads out of the agent entirely.
Production Considerations
- •
Deploy in-region
- •Wealth clients often have residency constraints around personal data.
- •Keep model execution and evidence storage in approved regions only.
- •
Log every decision path
- •Capture tool inputs/outputs, prompt version, model version, timestamps, and final recommendation.
- •Auditors will ask why a case was approved or escalated.
- •
Add hard guardrails
- •Never let the agent approve when sanctions screening returns a hit or when required fields are missing.
- •Encode those as deterministic pre-checks outside the LLM.
- •
Monitor drift by segment
- •Track manual-review rate by country, entity type, net worth band, and source-of-funds category.
- •A sudden shift usually means either bad upstream data or prompt regression.
Common Pitfalls
- •
Letting the model make policy decisions
If policy says “sanctions hit equals reject,” do that in code before calling the agent. The agent should explain outcomes, not invent them.
- •
Passing raw documents without normalization
PDFs OCR’d into messy text will produce noisy results. Extract structured fields first; feed the agent clean JSON with explicit nulls for missing values.
- •
Skipping audit persistence
A final “approved” label without evidence is not usable in wealth management. Store every intermediate artifact so compliance can replay the case end to end.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit