How to Build a fraud detection Agent Using LangChain in TypeScript for retail banking
A fraud detection agent in retail banking watches transaction streams, customer context, and policy rules, then decides whether a payment should be allowed, challenged, or escalated. It matters because the bank needs to stop fraud fast without blocking legitimate customers, while keeping every decision auditable for compliance teams.
Architecture
- •
Transaction ingestion layer
- •Receives card payments, ACH transfers, P2P transfers, login events, and device signals.
- •Normalizes raw events into a single fraud-check input shape.
- •
Customer context retriever
- •Pulls recent account history, usual geographies, merchant patterns, device fingerprints, and prior alerts.
- •Keeps the agent grounded in bank-owned data instead of guessing.
- •
Risk scoring toolchain
- •Combines deterministic rules with LLM-assisted classification.
- •Uses explicit thresholds for high-risk actions like blocking or step-up authentication.
- •
LangChain agent
- •Orchestrates the decision flow using
ChatOpenAI,createToolCallingAgent, andAgentExecutor. - •Calls tools for policy lookup, customer history lookup, and case creation.
- •Orchestrates the decision flow using
- •
Audit and case management sink
- •Stores the input, output, tool calls, and final rationale.
- •Feeds downstream SIEM/SOC or fraud operations queues.
- •
Guardrail layer
- •Enforces PII redaction, jurisdiction checks, and action constraints.
- •Prevents the model from making unsupported decisions outside policy.
Implementation
1. Define the fraud event schema and tools
Keep the agent narrow. It should not “detect fraud” from free text; it should evaluate a structured event with bank-approved tools.
import { z } from "zod";
import { tool } from "@langchain/core/tools";
export const FraudEventSchema = z.object({
customerId: z.string(),
transactionId: z.string(),
amount: z.number().positive(),
currency: z.string().length(3),
merchantCategory: z.string(),
country: z.string(),
deviceId: z.string(),
});
type FraudEvent = z.infer<typeof FraudEventSchema>;
const getCustomerHistory = tool(
async ({ customerId }: { customerId: string }) => {
// Replace with real data access layer
return JSON.stringify({
avgDailySpend: 120,
usualCountries: ["US"],
recentDeclines: 1,
openFraudCases: 0,
});
},
{
name: "get_customer_history",
description: "Fetch recent customer behavior and fraud-relevant account signals",
schema: z.object({ customerId: z.string() }),
}
);
const createFraudCase = tool(
async ({ transactionId, reason }: { transactionId: string; reason: string }) => {
// Replace with case management API call
return JSON.stringify({ caseId: `FC-${transactionId}`, status: "created", reason });
},
{
name: "create_fraud_case",
description: "Create a fraud investigation case when risk is high",
schema: z.object({
transactionId: z.string(),
reason: z.string(),
}),
}
);
2. Build the LangChain agent with explicit policy instructions
Use an LLM only as a decision helper. The model should classify into allowed actions like approve, challenge, or escalate, not invent policy.
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { createToolCallingAgent } from "langchain/agents";
import { AgentExecutor } from "langchain/agents";
const llm = new ChatOpenAI({
modelName: "gpt-4o-mini",
temperature: 0,
});
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
[
"You are a retail banking fraud triage agent.",
"Use only the provided tools and the supplied transaction fields.",
"Return one of these actions only: approve, challenge, escalate.",
"If country is outside the customer's usual countries or amount is far above normal spend, prefer challenge or escalate.",
"Never expose sensitive personal data in your final response.",
"Every decision must be explainable using observed signals and tool output.",
].join(" "),
],
]);
const tools = [getCustomerHistory, createFraudCase];
const agent = await createToolCallingAgent({
llm,
tools,
prompt,
});
const executor = new AgentExecutor({
agent,
tools,
});
3. Run the decision flow and map it to bank actions
The output should drive deterministic downstream behavior. Don’t let a model directly block accounts without your own policy gate.
async function evaluateFraud(eventInput: unknown) {
const event = FraudEventSchema.parse(eventInput);
const result = await executor.invoke({
input: JSON.stringify(event),
customerId: event.customerId,
transactionId: event.transactionId,
amount: event.amount.toString(),
currency: event.currency,
country: event.country,
merchantCategory: event.merchantCategory,
deviceId: event.deviceId,
// Tool inputs are passed through context; keep them structured in your app layer too.
});
const decisionText = String(result.output).toLowerCase();
if (decisionText.includes("escalate")) {
return {
action: "escalate",
nextStep: "create_case_and_hold_payment",
auditNote: result.output,
};
}
if (decisionText.includes("challenge")) {
return {
action: "challenge",
nextStep: "step_up_authentication",
auditNote: result.output,
};
}
return {
action:"approve",
nextStep:"release_payment",
auditNote:String(result.output),
};
}
evaluateFraud({
customerId:"C123",
transactionId:"T999",
amount:"4500" as unknown as number,
currency:"USD",
merchantCategory:"electronics",
country:"NG",
deviceId:"D456"
}).then(console.log);
Why this pattern works
The agent is not making an unconstrained judgment call. It is combining:
- •structured inputs
- •bank-owned customer history
- •explicit action labels
- •deterministic post-processing
That gives you an auditable control point before any payment is blocked or challenged.
Production Considerations
- •
Compliance and auditability
- •Persist every prompt, tool call, model output, and final action with timestamps.
- •Store enough context for auditors to reconstruct why a payment was challenged or escalated.
- •
Data residency
- •Keep PII and transaction data inside approved regions.
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