How to Build a customer support Agent Using LangChain in TypeScript for fintech
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
ChatPromptTemplatethat constrains tone, scope, and refusal behavior. - •A
RunnableSequenceorRunnablePassthroughpipeline that routes the request.
- •A
- •
Knowledge retrieval layer
- •A vector store backed by approved fintech documents: fee schedules, dispute policies, onboarding steps, SLA docs.
- •Retrieval via
VectorStoreRetrieverso 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
- •
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.
- •
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.
- •
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.
- •
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
- •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