How to Build a fraud detection Agent Using CrewAI in TypeScript for wealth management
A fraud detection agent for wealth management watches account activity, client instructions, transfer requests, and portfolio changes, then flags patterns that look like impersonation, unauthorized trading, account takeover, or social-engineering-driven wire fraud. In wealth management, the cost of missing one bad instruction is not just financial loss; it is regulatory exposure, client trust damage, and a messy audit trail.
Architecture
- •
Input collector
- •Pulls in events from CRM notes, order management systems, wire request queues, email metadata, and authentication logs.
- •Normalizes each event into a single fraud-review payload.
- •
Risk classification agent
- •Uses an LLM-backed
Agentto score the request and explain why it looks suspicious. - •Produces structured output: risk level, reasons, recommended action.
- •Uses an LLM-backed
- •
Policy and compliance layer
- •Enforces wealth-management rules before any recommendation is acted on.
- •Checks for KYC/AML flags, restricted jurisdictions, advisor-client mismatch, and approval thresholds.
- •
Audit logger
- •Stores every input, model output, tool call, and final decision.
- •Required for internal review and regulator-facing evidence.
- •
Escalation workflow
- •Routes high-risk cases to a human investigator or operations queue.
- •Prevents the agent from auto-blocking legitimate client activity without review.
Implementation
1) Install dependencies and define the fraud review schema
CrewAI’s TypeScript support is straightforward: define agents and tasks in code, then run them through a Crew. For fraud detection, keep outputs structured so downstream systems can consume them without parsing free-form text.
npm install crewai zod dotenv
import { z } from "zod";
export const FraudReviewSchema = z.object({
riskLevel: z.enum(["low", "medium", "high"]),
decision: z.enum(["approve", "review", "block"]),
reasons: z.array(z.string()).min(1),
recommendedActions: z.array(z.string()).min(1),
auditSummary: z.string().min(20),
});
export type FraudReview = z.infer<typeof FraudReviewSchema>;
export interface WealthEvent {
clientId: string;
accountId: string;
requestType: "wire" | "trade" | "address_change" | "beneficiary_update";
amount?: number;
currency?: string;
channel: "advisor_portal" | "email" | "phone" | "mobile_app";
ipRiskScore: number;
geoMismatch: boolean;
recentLoginFailures: number;
kycStatus: "verified" | "pending" | "expired";
}
2) Build the agent with wealth-management guardrails
The agent should not be a generic fraud bot. It needs instructions that reflect wealth workflows: high-value transfers, advisor authorization chains, and strict auditability.
import "dotenv/config";
import { Agent } from "crewai";
export const fraudAgent = new Agent({
name: "Wealth Fraud Detection Agent",
role: "Detect suspicious client instructions and transaction patterns",
goal:
"Identify likely fraud in wealth management workflows and return a structured review recommendation",
backstory:
"You are a senior fraud analyst for a private wealth platform. You understand account takeover patterns, impersonation attempts, wire fraud red flags, advisor impersonation, and compliance constraints.",
verbose: true,
});
3) Create a task that forces structured output
Use a Task with explicit output requirements. In production I prefer JSON-only responses because they are easier to validate and log.
import { Task } from "crewai";
import { FraudReviewSchema } from "./schema";
import type { WealthEvent } from "./schema";
export function buildFraudTask(event: WealthEvent) {
return new Task({
description: `
Review this wealth management event for fraud risk.
Event:
${JSON.stringify(event, null, 2)}
Rules:
- Flag wire requests with geo mismatch + login failures as high risk.
- Treat beneficiary changes followed by transfers as suspicious.
- Escalate expired KYC or advisor-channel mismatches.
- Do not approve if evidence suggests impersonation or account takeover.
- Return JSON only with keys:
riskLevel, decision, reasons, recommendedActions, auditSummary
`,
expectedOutput:
'Valid JSON matching { riskLevel, decision, reasons[], recommendedActions[], auditSummary }',
agent: fraudAgent,
async callback(result) {
const parsed = FraudReviewSchema.parse(JSON.parse(result as string));
return parsed;
},
});
}
4) Run the crew and persist the result for audit
For a single-review workflow you can use one agent plus one task. If you want stronger controls later, add a second agent for compliance validation or an explicit human-review routing step.
import { Crew } from "crewai";
import { buildFraudTask } from "./task";
import type { WealthEvent } from "./schema";
async function main() {
const event: WealthEvent = {
clientId: "C12345",
accountId: "A99881",
requestType: "wire",
amount: 250000,
currency: "USD",
channel: "email",
ipRiskScore: 92,
geoMismatch: true,
recentLoginFailures: 4,
kycStatus: "verified",
};
const crew = new Crew({
agents: [fraudAgent],
tasks: [buildFraudTask(event)],
verbose: true,
});
const result = await crew.kickoff();
console.log("Fraud review:", result);
}
main().catch(console.error);
Production Considerations
- •
Deploy close to your data boundary
- •Wealth data often has residency requirements.
- •Keep the agent in-region if client data cannot leave a specific jurisdiction.
- •
Log everything needed for audit
- •Store input payloads, model version, prompt version, task output, timestamps, and final disposition.
- •Regulators care about why a decision was made months later.
- •
Add hard guardrails before action
- •The agent should recommend; policy engines should decide whether to block or hold.
- •Use deterministic rules for thresholds like large wires after beneficiary changes.
- •
Monitor false positives by segment
- •Private banking clients behave differently from retail brokerage clients. Track rates by region, advisor team, transaction type, and channel so you do not create operational noise.
Common Pitfalls
- •
Letting the LLM make final decisions
- •Don’t auto-block based only on model output.
- •Use the agent for triage; use policy rules and human review for enforcement.
- •
Sending raw sensitive data into prompts
- •Avoid dumping full account statements or personal identifiers into the model context.
- •Redact unnecessary PII and pass only fields required for risk analysis.
- •
Ignoring workflow context
- •A $500k wire is normal in some private wealth books and abnormal in others.
- •Include client profile context such as historical transfer size, advisor relationship length, and expected geography.
- •
Skipping schema validation
- •Free-form LLM output will break downstream systems.
- •Validate every response with
zodbefore it reaches case management or alerting systems.
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