How to Build a customer support Agent Using AutoGen in TypeScript for pension funds
A customer support agent for pension funds answers member questions, drafts responses for service teams, and routes sensitive cases to the right human queue. It matters because pension operations sit under strict compliance, audit, and data residency requirements, so the agent has to be useful without ever becoming a liability.
Architecture
- •
Member intake layer
- •Receives chat, email, or portal messages.
- •Normalizes them into a single support request shape with member ID, topic, jurisdiction, and urgency.
- •
Policy retrieval layer
- •Pulls approved pension policy snippets from a controlled knowledge base.
- •Restricts answers to fund rules, contribution limits, retirement options, beneficiary changes, and service SLAs.
- •
AutoGen orchestration layer
- •Uses
AssistantAgentfor response drafting. - •Uses
UserProxyAgentfor tool execution and human-in-the-loop approval on risky cases.
- •Uses
- •
Case triage layer
- •Classifies requests like address change, contribution query, retirement estimate, complaint, or fraud suspicion.
- •Escalates regulated topics to a human advisor instead of letting the model freewheel.
- •
Audit and logging layer
- •Stores prompts, retrieved sources, tool calls, and final outputs.
- •Keeps an immutable trail for compliance review and dispute handling.
- •
Security and residency controls
- •Redacts PII before model calls where possible.
- •Keeps data in-region if the pension fund has residency constraints.
Implementation
1) Install AutoGen and define a support request shape
Use the TypeScript AutoGen package and keep your request payload explicit. Pension support gets messy when everything is just “chat text”; you want structured fields from day one.
npm install @autogen/core zod
import { z } from "zod";
export const SupportRequestSchema = z.object({
memberId: z.string(),
jurisdiction: z.string(),
channel: z.enum(["web", "email", "phone"]),
topic: z.enum([
"contribution",
"benefit_estimate",
"beneficiary",
"address_change",
"complaint",
"fraud",
"other",
]),
message: z.string(),
});
export type SupportRequest = z.infer<typeof SupportRequestSchema>;
2) Create an assistant agent with constrained behavior
The key pattern is to make the assistant good at drafting but bad at improvising. For pension funds, that means no legal advice, no promises about benefits, and no acting on high-risk requests without approval.
import { AssistantAgent } from "@autogen/core";
export const supportAgent = new AssistantAgent({
name: "pension_support_agent",
systemMessage: `
You are a customer support agent for a pension fund.
Answer only using approved policy context provided in the conversation.
If the request involves complaints, fraud, withdrawals, tax treatment, legal interpretation,
or changes to member records, escalate to a human advisor.
Do not invent benefit figures or eligibility rules.
Always mention when information is general guidance and not final advice.
`,
});
3) Add a human proxy for approvals and tool execution
For production support flows you want the model to draft; you want a person or deterministic service to execute. UserProxyAgent is the right control point for escalation and manual approval.
import { UserProxyAgent } from "@autogen/core";
export const opsProxy = new UserProxyAgent({
name: "ops_proxy",
});
Now wire the agents together with a simple triage function. This is where you keep regulated topics out of autonomous execution.
import { SupportRequest } from "./schema";
import { supportAgent } from "./agents";
import { opsProxy } from "./proxy";
function needsHumanReview(req: SupportRequest): boolean {
return ["complaint", "fraud"].includes(req.topic) ||
/withdraw|transfer|tax|legal|court/i.test(req.message);
}
export async function handleSupportRequest(req: SupportRequest) {
const safeReq = req;
if (needsHumanReview(safeReq)) {
return {
route: "human_review",
reason: "regulated_or_high_risk_topic",
summary: `Member ${safeReq.memberId} requested ${safeReq.topic}`,
};
}
const result = await supportAgent.run(
[
{
role: "user",
content:
`Jurisdiction: ${safeReq.jurisdiction}\n` +
`Topic: ${safeReq.topic}\n` +
`Message: ${safeReq.message}\n\n` +
`Draft a concise support reply using only approved policy context.`,
},
],
{ maxTurns: 1 }
);
return {
route: "auto_draft",
reply: result.messages.at(-1)?.content ?? "",
approvedBy: opsProxy.name,
};
}
4) Add retrieval and audit logging around the agent call
AutoGen should never answer pension questions from memory alone. Feed it approved policy snippets from your internal store and log what it saw so compliance can reconstruct the decision later.
type PolicySnippet = {
id: string;
title: string;
text: string;
};
async function fetchPolicySnippets(topic: string): Promise<PolicySnippet[]> {
// Replace with your internal search service or vector store lookup.
return [
{
id: "POL-0142",
title: "Member Address Changes",
text:
"Address changes must be completed through authenticated member portal or verified call center workflow.",
},
{
id: "POL-0201",
title: "Benefit Estimates",
text:
"Benefit estimates are indicative only and depend on salary history, service years, and plan rules.",
},
].filter((p) => p.title.toLowerCase().includes(topic.replace("_", " ").toLowerCase()));
}
async function auditLog(entry: Record<string, unknown>) {
console.log(JSON.stringify(entry));
}
export async function answerWithPolicy(req: SupportRequest) {
const snippets = await fetchPolicySnippets(req.topic);
await auditLog({
event: "support_request_received",
memberIdHash: req.memberId.slice(-4),
topic: req.topic,
jurisdiction: req.jurisdiction,
policyIds: snippets.map((s) => s.id),
timestamp: new Date().toISOString(),
});
const prompt = [
...snippets.map(
(s) => `Policy [${s.id}] ${s.title}: ${s.text}`
),
`Member message: ${req.message}`,
`Write a short reply. If policy is insufficient, ask for human follow-up.`,
].join("\n\n");
const response = await supportAgent.run([{ role: "user", content: prompt }], {
maxTurns: 1,
});
return response.messages.at(-1)?.content ?? "";
}
Production Considerations
- •
Keep residency boundaries explicit
If your pension fund operates in-country data centers or region-specific clouds, pin retrieval storage and model endpoints to that region. Don’t send member identifiers to external services unless your legal basis and vendor terms allow it.
- •
Log for audit, not just observability
Store prompt version, retrieved policy IDs, model output, escalation reason, and final human edit. Auditors care about why an answer was produced more than raw token counts.
- •
Use hard guardrails on regulated topics
Block autonomous actions on withdrawals, beneficiary updates, complaints handling, tax advice, fraud claims, and identity changes. The agent should draft guidance only; humans should approve any action that affects entitlements or records.
- •
Monitor answer drift by topic
Track hallucination rates separately for contribution questions vs benefit estimates vs complaint handling. Pension funds usually discover that one narrow topic fails first because its policy language is ambiguous or outdated.
Common Pitfalls
- •
Letting the model answer from general knowledge
This is how you get incorrect benefit estimates or policy statements. Always inject approved policy context and reject responses that can’t cite it.
- •
Treating all requests as low risk
A “simple” address change can become an identity fraud incident if you skip verification. Route anything touching member records through authenticated workflows or human review.
- •
Ignoring jurisdiction differences
Pension rules vary by country and sometimes by plan section. Include jurisdiction in every request object and retrieve only policies valid for that region.
- •
Skipping immutable logs
If you can’t reconstruct what was asked, what policy was used, and who approved it afterward, compliance will treat the agent as ungoverned automation. Write logs as part of the flow, not as an afterthought.
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