How to Build a compliance checking Agent Using LangChain in TypeScript for pension funds

By Cyprian AaronsUpdated 2026-04-21
compliance-checkinglangchaintypescriptpension-funds

A compliance checking agent for pension funds reviews documents, transactions, and policy decisions against regulatory rules before they go live. It matters because pension operations are high-stakes: a missed contribution rule, a prohibited investment, or a bad disclosure can create regulatory exposure, audit findings, and member harm.

Architecture

  • Document ingestion layer

    • Pulls policy PDFs, investment mandates, contribution schedules, and internal SOPs.
    • Normalizes text for downstream checks.
  • Rules retrieval layer

    • Uses MemoryVectorStore or a managed vector DB to retrieve relevant compliance clauses.
    • Keeps the agent grounded in fund-specific policy and jurisdiction-specific rules.
  • Compliance reasoning agent

    • Uses LangChain’s createOpenAIFunctionsAgent or createReactAgent pattern with tools.
    • Decides which checks to run based on the input type.
  • Deterministic rule engine

    • Handles hard rules that should not be left to an LLM.
    • Examples: contribution caps, blackout periods, concentration limits, required disclosures.
  • Audit logging layer

    • Stores inputs, retrieved evidence, model outputs, and final decisions.
    • Supports regulator review and internal control testing.
  • Human escalation path

    • Routes ambiguous or high-risk cases to a compliance officer.
    • Prevents the agent from making final decisions on edge cases.

Implementation

1) Install the core packages

Use LangChain JS with a model provider and a vector store. For TypeScript projects, keep your tsconfig strict so tool contracts stay typed.

npm install langchain @langchain/openai @langchain/community zod

2) Load pension policy documents into a retriever

This example uses in-memory vectors for clarity. In production, swap this for pgvector, Pinecone, or another store that meets your data residency requirements.

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

const docs = [
  new Document({
    pageContent:
      "Pension fund rule: employer contributions must be posted within 5 business days of payroll.",
    metadata: { source: "policy-contributions", jurisdiction: "ZA" },
  }),
  new Document({
    pageContent:
      "Investment rule: no single issuer may exceed 10% of portfolio market value.",
    metadata: { source: "policy-investments", jurisdiction: "ZA" },
  }),
];

const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorStore = await MemoryVectorStore.fromDocuments(docs, embeddings);
const retriever = vectorStore.asRetriever(4);

3) Define tools for deterministic checks and evidence lookup

The key pattern is this: let the LLM orchestrate, but keep the actual compliance logic in tools. That gives you traceability and avoids turning every rule into prompt text.

import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
import {
  DynamicStructuredTool,
} from "@langchain/core/tools";
import {
  ChatPromptTemplate,
} from "@langchain/core/prompts";
import {
  createOpenAIFunctionsAgent,
} from "langchain/agents";
import {
  AgentExecutor,
} from "langchain/agents";

const checkContributionTiming = new DynamicStructuredTool({
  name: "check_contribution_timing",
  description:
    "Checks whether employer contributions were posted within the required number of business days.",
  schema: z.object({
    daysLate: z.number().int().min(0),
    maxAllowedDays: z.number().int().default(5),
  }),
  func: async ({ daysLate, maxAllowedDays }) => {
    const compliant = daysLate <= maxAllowedDays;
    return JSON.stringify({
      compliant,
      reason: compliant
        ? "Contribution timing is within policy."
        : `Contribution is ${daysLate} business days late; limit is ${maxAllowedDays}.`,
    });
  },
});

const retrievePolicyEvidence = new DynamicStructuredTool({
  name: "retrieve_policy_evidence",
  description:
    "Fetches relevant pension fund policy text for a compliance question.",
  schema: z.object({
    query: z.string(),
  }),
  func: async ({ query }) => {
    const results = await retriever.getRelevantDocuments(query);
    return JSON.stringify(
      results.map((doc) => ({
        text: doc.pageContent,
        source: doc.metadata.source,
        jurisdiction: doc.metadata.jurisdiction,
      }))
    );
  },
});

4) Build the agent and run a compliance review

This uses createOpenAIFunctionsAgent with an AgentExecutor. The output should be treated as a recommendation unless your deterministic tool returns a hard fail.

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

const prompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    [
      "You are a compliance checking agent for pension funds.",
      "Use tools before making conclusions.",
      "If evidence is insufficient, escalate to human review.",
      "Do not invent regulatory requirements.",
      "Return concise findings with evidence references.",
    ].join(" "),
  ],
]);

const tools = [checkContributionTiming, retrievePolicyEvidence];
const agent = await createOpenAIFunctionsAgent({
  llm,
  tools,
  prompt,
});

const executor = new AgentExecutor({
  agent,
  tools,
});

const result = await executor.invoke({
  input:
    "Review this case: employer contributions were posted after 7 business days. Check against policy and summarize the risk.",
});

console.log(result.output);

A practical production flow looks like this:

  1. The user submits a case record or document bundle.
  2. The agent retrieves relevant policy clauses using retrieve_policy_evidence.
  3. Deterministic tools validate hard controls like timing or thresholds.
  4. The final response includes:
    • compliance status
    • cited evidence
    • escalation flag
    • audit trail IDs

Production Considerations

  • Data residency

    • Pension fund records often cannot leave a specific country or region.
    • Keep embeddings, logs, and model calls inside approved infrastructure where possible.
  • Auditability


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