How to Build a customer support Agent Using LangChain in TypeScript for fintech

By Cyprian AaronsUpdated 2026-04-21
customer-supportlangchaintypescriptfintech

A customer support agent for fintech handles account questions, payment status, card disputes, KYC follow-ups, and policy explanations without exposing sensitive data or making unsafe promises. It matters because support in this domain is not just about speed; it has to be auditable, compliant, and tightly scoped to approved knowledge and actions.

Architecture

  • User interface layer

    • Web chat, in-app support widget, or internal agent console.
    • Sends the user message plus session metadata like customer segment and locale.
  • LangChain orchestration layer

    • A ChatPromptTemplate that constrains tone, scope, and refusal behavior.
    • A RunnableSequence or RunnablePassthrough pipeline that routes the request.
  • Knowledge retrieval layer

    • A vector store backed by approved fintech documents: fee schedules, dispute policies, onboarding steps, SLA docs.
    • Retrieval via VectorStoreRetriever so answers come from controlled sources.
  • Policy and guardrail layer

    • Pre-checks for PII leakage, regulated advice, and unsupported actions.
    • Post-checks for response format, citations, and escalation triggers.
  • Audit and observability layer

    • Structured logs with conversation ID, retrieved document IDs, model version, and final action taken.
    • Required for compliance review and incident investigation.
  • Human handoff layer

    • Escalates to a live agent when confidence is low or the request touches fraud, legal disputes, or account closure.

Implementation

1) Install dependencies and create the model client

Use a chat model that LangChain supports directly. For this example, ChatOpenAI is enough to show the actual orchestration pattern.

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

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

2) Load approved support content into a retriever

For fintech support, only index content that compliance has signed off on. That usually means policy PDFs converted into text chunks, FAQ articles, and internal runbooks.

import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "@langchain/openai";
import { Document } from "@langchain/core/documents";

const docs = [
  new Document({
    pageContent:
      "Card dispute timeline: customers must report unauthorized transactions within 60 days. Refunds are provisional pending investigation.",
    metadata: { source: "disputes-policy", docId: "dp-001" },
  }),
  new Document({
    pageContent:
      "SEPA transfers typically settle within one business day. Weekend submissions are processed on the next banking day.",
    metadata: { source: "payments-faq", docId: "pay-014" },
  }),
];

const vectorStore = await MemoryVectorStore.fromDocuments(
  docs,
  new OpenAIEmbeddings()
);

export const retriever = vectorStore.asRetriever(3);

3) Build the support chain with a strict prompt

The key is to force grounded answers. The agent should answer only from retrieved context and escalate when the context is missing or the request is sensitive.

import { ChatPromptTemplate } from "@langchain/core/prompts";
import {
  RunnablePassthrough,
  RunnableLambda,
} from "@langchain/core/runnables";
import type { Document } from "@langchain/core/documents";
import { llm } from "./llm";
import { retriever } from "./retriever";

const prompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    [
      "You are a fintech customer support agent.",
      "Answer only using the provided context.",
      "If the context does not contain the answer, say you need to escalate to a human agent.",
      "Do not provide legal advice, investment advice, or instructions that expose sensitive data.",
      "Keep responses concise and include cited source IDs when available.",
    ].join(" "),
  ],
  ["human", "{question}\n\nContext:\n{context}"],
]);

function formatDocs(docs: Document[]) {
  return docs
    .map((doc) => `[${doc.metadata.docId}] ${doc.pageContent}`)
    .join("\n\n");
}

export const supportChain = RunnablePassthrough.assign({
  context: async (input: { question: string }) => {
    const docs = await retriever.invoke(input.question);
    return formatDocs(docs);
  },
})
.pipe(prompt)
.pipe(llm)
.pipe(
  RunnableLambda.from(async (message) => {
    return {
      answer: message.content,
      timestamp: new Date().toISOString(),
    };
  })
);

4) Add an escalation check before returning output

In fintech, “I don’t know” is better than hallucinating a policy. Add a simple guardrail that routes risky cases to humans.

const escalationKeywords = [
  "fraud",
  "chargeback",
  "lawsuit",
  "account closure",
  "sanction",
];

export async function handleSupportQuestion(question: string) {
  const needsEscalation = escalationKeywords.some((k) =>
    question.toLowerCase().includes(k)
  );

  if (needsEscalation) {
    return {
      answer:
        "I’m escalating this to a human support specialist because it involves a sensitive account issue.",
      escalated: true,
    };
}

return await supportChain.invoke({ question });
}

Use it like this:

const result = await handleSupportQuestion(
  "How long does a card dispute take?"
);

console.log(result);

Production Considerations

  • Audit every decision path

    • Log the original user question, retrieved document IDs, model name, prompt version, and whether the request escalated.
    • Store logs in an immutable system if your compliance team requires tamper evidence.
  • Control data residency

    • Keep embeddings, vector stores, and model inference in approved regions.
    • If customer data must stay in-country, do not send raw transcripts to external services outside that boundary.
  • Add response validation

    • Enforce JSON schemas or strict output formats where possible.
    • Reject answers containing prohibited phrases like “guaranteed refund” or “approved immediately” unless your policy engine explicitly allows them.
  • Monitor deflection vs. escalation

    • Track how often the bot resolves issues versus handing off to humans.
    • In fintech support, high deflection is useless if it increases complaint rates or regulatory risk.

Common Pitfalls

  1. Indexing unapproved documents

    • If your vector store contains outdated fee tables or draft policies, the bot will confidently serve bad information.
    • Fix it by versioning documents and only indexing compliance-approved sources.
  2. Letting the model answer without retrieval

    • A generic chat model will hallucinate timelines for settlements or dispute handling.
    • Fix it by forcing every answer through retrieval and refusing to answer when no relevant context exists.
  3. Ignoring sensitive-intent routing

    • Questions about fraud recovery, chargebacks, sanctions screening, or account freezes should not be handled like normal FAQ traffic.
    • Fix it with keyword rules first, then add classifier-based routing once you have labeled production traffic.
  4. Skipping audit fields

    • If you cannot explain why the agent answered something after an incident review, you will have a compliance problem.
    • Fix it by storing source IDs and prompt/model versions with every interaction.

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