How to Build a transaction monitoring Agent Using LangChain in TypeScript for investment banking

By Cyprian AaronsUpdated 2026-04-21
transaction-monitoringlangchaintypescriptinvestment-banking

A transaction monitoring agent in investment banking reviews payment and trade activity, flags suspicious patterns, and routes cases for human review. It matters because banks need to detect AML, sanctions, fraud, and market abuse signals quickly without drowning compliance teams in false positives.

Architecture

  • Ingestion layer

    • Pulls transactions from Kafka, S3, a database, or an internal API.
    • Normalizes fields like amount, currency, counterparty, booking entity, and timestamps.
  • Rules engine

    • Applies deterministic controls first: threshold breaches, sanctioned jurisdictions, velocity checks, structuring patterns.
    • Keeps obvious hits out of the LLM path.
  • LangChain decision agent

    • Uses ChatOpenAI plus tools to explain why a transaction is suspicious.
    • Produces structured outputs for alert severity, rationale, and next action.
  • Case context retriever

    • Fetches customer KYC, historical alerts, account profile, and prior SAR/STR notes.
    • Usually implemented with VectorStoreRetriever or a SQL-backed lookup tool.
  • Audit logger

    • Stores every input, tool call, model output, and final decision.
    • Required for model governance and regulator review.
  • Human review queue

    • Sends high-risk cases to compliance analysts.
    • The agent should recommend; analysts should decide.

Implementation

1) Install dependencies and define the case schema

Use LangChain JS packages that are actually maintained for TypeScript. For a production agent, keep outputs structured from the start so downstream systems do not parse free text.

npm install langchain @langchain/openai zod
import { z } from "zod";

export const TransactionSchema = z.object({
  transactionId: z.string(),
  customerId: z.string(),
  amount: z.number(),
  currency: z.string(),
  counterpartyCountry: z.string(),
  bookingEntity: z.string(),
  timestamp: z.string(),
});

export const AlertSchema = z.object({
  riskScore: z.number().min(0).max(100),
  severity: z.enum(["low", "medium", "high"]),
  reasons: z.array(z.string()),
  recommendedAction: z.enum(["monitor", "review", "escalate"]),
});

export type Transaction = z.infer<typeof TransactionSchema>;
export type Alert = z.infer<typeof AlertSchema>;

2) Add deterministic pre-screening before the LLM

Do not send every transaction to the model. In investment banking, rules catch known bad patterns cheaply and create a defensible first line of control.

import { Transaction } from "./schema.js";

const SANCTIONED_COUNTRIES = new Set(["IR", "KP", "SY", "RU"]);

export function preScreen(tx: Transaction) {
  const reasons: string[] = [];

  if (tx.amount >= 1000000) reasons.push("High-value transfer above internal threshold");
  if (SANCTIONED_COUNTRIES.has(tx.counterpartyCountry)) {
    reasons.push(`Counterparty country ${tx.counterpartyCountry} is restricted`);
  }
  if (tx.bookingEntity === "offshore_spv") reasons.push("Booking entity is offshore SPV");

  return {
    hit: reasons.length > 0,
    reasons,
    riskScore: Math.min(90, reasons.length * 30),
  };
}

3) Build the LangChain agent with structured output

Use ChatOpenAI and withStructuredOutput() so the model returns machine-readable alerts. This is the core pattern for production monitoring workflows.

import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage } from "@langchain/core/messages";
import { AlertSchema, TransactionSchema } from "./schema.js";

const model = new ChatOpenAI({
  model: "gpt-4o-mini",
  temperature: 0,
});

const alertModel = model.withStructuredOutput(AlertSchema);

export async function analyzeTransaction(rawTx: unknown) {
  const tx = TransactionSchema.parse(rawTx);
  const precheck = preScreen(tx);

  if (precheck.hit) {
    return {
      ...precheck,
      source: "rules",
      transactionId: tx.transactionId,
    };
    }

  const prompt = `
You are a transaction monitoring analyst for an investment bank.
Assess whether this transaction should be monitored, reviewed, or escalated.
Focus on AML, sanctions exposure, unusual size, and booking structure.
Return only structured output matching the schema.

Transaction:
${JSON.stringify(tx)}
`;

  const result = await alertModel.invoke([new HumanMessage(prompt)]);
  
  return {
    ...result,
    source: "llm",
    transactionId: tx.transactionId,
    auditTrail: {
      model: "gpt-4o-mini",
      temperature: 0,
      timestamp: new Date().toISOString(),
    },
    };
}

4) Wrap it in a simple service endpoint

In real deployments this sits behind an internal API that writes to your case management system. Keep the response deterministic enough for downstream workflow engines.

import express from "express";
import { analyzeTransaction } from "./agent.js";

const app = express();
app.use(express.json());

app.post("/monitor", async (req, res) => {
  try {
    const alert = await analyzeTransaction(req.body);
    res.json(alert);
  } catch (error) {
    res.status(400).json({
      error: "Invalid transaction payload or analysis failure",
    });
  }
});

app.listen(3000);

Production Considerations

  • Data residency

    • Keep customer data in-region. If your bank requires EU-only processing or on-prem deployment, use a private model endpoint or self-hosted inference.
    • Do not send raw PII to external services unless legal and vendor controls are already signed off.
  • Auditability

    • Log the original transaction payload hash, rule hits, prompt version, model version, and final disposition.
  • Human-in-the-loop controls

    • Auto-escalate only when policy allows it.
  • Monitoring

Common Pitfalls

  • Sending everything to the LLM

  • Using free-text outputs

  • Ignoring jurisdiction-specific controls


Keep learning

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

Related Guides