How to Build a customer support Agent Using LangChain in TypeScript for wealth management
A customer support agent for wealth management answers client questions about accounts, statements, fees, portfolio basics, onboarding, and service requests without forcing every interaction through a human advisor. It matters because the support layer in this domain is not just a cost center; it is part of the client experience, compliance surface, and audit trail.
Architecture
- •
Chat interface
- •Receives client messages from web, mobile, or advisor portals.
- •Keeps conversation state per client session.
- •
Policy-aware router
- •Classifies whether the request is informational, account-specific, or restricted.
- •Escalates sensitive topics like suitability, tax advice, or trade instructions.
- •
Retrieval layer
- •Pulls answers from approved sources: FAQs, product docs, fee schedules, service playbooks.
- •Uses vector search over controlled content only.
- •
Tool layer
- •Calls internal APIs for account status, case creation, document lookup, or appointment booking.
- •Never exposes raw backend responses directly to the client.
- •
Guardrails and compliance filter
- •Detects PII leakage, disallowed advice, and unsupported claims.
- •Logs every decision for audit and supervision.
- •
Audit and observability
- •Stores prompts, retrieved documents, tool calls, and final responses.
- •Supports replay for compliance review and incident analysis.
Implementation
1. Set up the model and retrieval chain
For wealth management support, keep the model constrained to approved content. Use a retriever backed by curated documents and a chat model that can follow strict system instructions.
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { createStuffDocumentsChain } from "langchain/chains/combine_documents";
import { createRetrievalChain } from "langchain/chains/retrieval";
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { OpenAIEmbeddings } from "@langchain/openai";
import { Document } from "@langchain/core/documents";
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
const docs = [
new Document({
pageContent:
"Wealth Management Support FAQ: Clients can request statements for the last 7 years. Fees are disclosed in the service agreement.",
metadata: { source: "faq", jurisdiction: "US" },
}),
new Document({
pageContent:
"Service Policy: Support cannot provide investment advice or recommendations. Escalate suitability questions to an advisor.",
metadata: { source: "policy", jurisdiction: "US" },
}),
];
const vectorStore = await MemoryVectorStore.fromDocuments(
docs,
new OpenAIEmbeddings()
);
const retriever = vectorStore.asRetriever(4);
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
`You are a wealth management support agent.
Only answer using retrieved context.
If the user asks for investment advice, tax advice, or trade recommendations, refuse and offer escalation.
If you do not know the answer from context, say you need to check with support.`,
],
["human", "{input}"],
]);
const combineDocsChain = await createStuffDocumentsChain({
llm,
prompt,
});
const ragChain = await createRetrievalChain({
retriever,
combineDocsChain,
});
This pattern gives you a controlled RAG setup. The model sees only approved support content instead of free-form internet knowledge.
2. Add a policy gate before answering
Do not send every message straight to retrieval. Wealth management needs a first-pass policy check so you can block restricted requests early.
function classifyRequest(input: string) {
const text = input.toLowerCase();
if (
text.includes("buy") ||
text.includes("sell") ||
text.includes("recommend") ||
text.includes("best fund") ||
text.includes("tax")
) {
return "restricted";
}
return "allowed";
}
export async function handleSupportMessage(input: string) {
const category = classifyRequest(input);
if (category === "restricted") {
return {
answer:
"I can help with account service questions, statements, fees, and document requests. I can’t provide investment or tax advice. I can connect you with an advisor.",
category,
};
}
const result = await ragChain.invoke({ input });
return {
answer: result.answer,
category,
sources: result.context?.map((d: any) => d.metadata?.source ?? "unknown"),
};
}
This is simple on purpose. In production you can replace the keyword gate with a structured classifier chain or policy model, but the control point stays the same.
3. Wire in tools for account servicing
Support agents usually need more than Q&A. Use tools for safe actions like creating cases or looking up document status.
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const createCaseTool = tool(
async ({ topic }: { topic: string }) => {
// Replace with your internal case API call
return `Case created for topic: ${topic}`;
},
{
name: "create_case",
description: "Create a client service case",
schema: z.object({
topic: z.string().min(3),
}),
}
);
Keep tool scope narrow. A wealth support agent should be able to open tickets and fetch approved data, not move money or change beneficiary details unless your controls explicitly allow it.
4. Build an audit log around every response
You need traceability for supervision and dispute handling. Log the user input, policy decision, retrieved sources, tool usage, and final output.
type AuditEvent = {
timestamp: string;
};
async function auditLog(event: Record<string, unknown>) {
};
export async function serveMessage(input: string) {
}
In practice this audit layer should write to immutable storage or your SIEM pipeline. Keep retention aligned with your compliance policy and regional data residency rules.
Production Considerations
- •Deploy in-region
If client data must stay in-country or in-region,
host embeddings storage, vector DBs,
and logs in that same boundary.
- •Monitor refusal rates and escalation rates
High refusal rates usually mean your policy gate is too aggressive or your knowledge base is incomplete. High escalation rates on basic questions usually means retrieval quality is poor.
- •Add response-level guardrails
Run output checks for prohibited advice, missing disclaimers where required by policy, and accidental disclosure of PII like full account numbers or tax IDs.
- •Keep human review on sensitive paths
Any request involving suitability, complaints about advice quality, trade instructions, beneficiary changes, wire transfers, or tax implications should route to a licensed human workflow.
Common Pitfalls
- •Letting the model answer from memory
Do not rely on general LLM behavior for regulated support content. Force retrieval-only answers with strict system prompts and approved documents.
- •Mixing support with advisory workflows
A support agent should not drift into portfolio recommendations. Separate “service” intents from “advice” intents at the router level and escalate immediately when needed.
- •Ignoring auditability
If you cannot reconstruct why an answer was given, you have a governance problem. Log prompts, retrieved chunks IDs/sources metadata if possible), tool calls ,and final outputs per 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