How to Build a compliance checking Agent Using AutoGen in TypeScript for insurance

By Cyprian AaronsUpdated 2026-04-21
compliance-checkingautogentypescriptinsurance

A compliance checking agent for insurance reviews policy language, underwriting notes, claims correspondence, or customer-facing messages against internal rules and regulatory constraints before they go out. It matters because one bad sentence can create a regulatory issue, a claim dispute, or a recordkeeping problem that costs real money and time.

Architecture

  • Policy intake layer

    • Accepts the text to review: email drafts, policy wording, claim summaries, call-center notes.
    • Normalizes input into a structured payload with product line, jurisdiction, and document type.
  • Compliance rules store

    • Holds insurer-specific rules plus jurisdictional controls.
    • Should support versioning so every decision can be traced to the exact rule set in force.
  • AutoGen agent group

    • A primary reviewer agent checks the content.
    • A secondary verifier agent challenges borderline decisions.
    • A coordinator agent produces the final compliance verdict.
  • Audit logger

    • Persists prompts, outputs, rule versions, timestamps, and reviewer identity.
    • Required for exam readiness and internal audit trails.
  • Human escalation path

    • Routes ambiguous or high-risk cases to compliance staff.
    • Prevents the system from auto-approving regulated content it should not decide alone.

Implementation

1) Install AutoGen and define your compliance inputs

Use the TypeScript AutoGen package and keep your review payload explicit. For insurance, the agent needs jurisdiction, line of business, document type, and a stable ruleset version.

npm install @microsoft/autogen openai zod
import { z } from "zod";

export const ComplianceInputSchema = z.object({
  documentId: z.string(),
  jurisdiction: z.string(), // e.g. "NY", "CA", "UK"
  lineOfBusiness: z.enum(["life", "health", "auto", "property", "casualty"]),
  documentType: z.enum(["policy", "endorsement", "claim_letter", "customer_email"]),
  content: z.string(),
  rulesVersion: z.string(), // e.g. "2026-01"
});

export type ComplianceInput = z.infer<typeof ComplianceInputSchema>;

2) Create agents with AssistantAgent and wire a group chat

The pattern below uses one agent to review for violations and another to verify edge cases. GroupChat plus GroupChatManager gives you a clean orchestration layer without hardcoding turn-taking in application code.

import { OpenAIChatCompletionClient } from "@microsoft/autogen";
import {
  AssistantAgent,
  GroupChat,
  GroupChatManager,
} from "@microsoft/autogen";

const modelClient = new OpenAIChatCompletionClient({
  model: process.env.OPENAI_MODEL ?? "gpt-4o-mini",
  apiKey: process.env.OPENAI_API_KEY!,
});

const reviewer = new AssistantAgent({
  name: "compliance_reviewer",
  modelClient,
  systemMessage: `
You are an insurance compliance reviewer.
Check content for prohibited promises, misleading coverage language,
missing disclosures, unfair claims handling language, and jurisdiction issues.
Return only structured findings with severity and rationale.
`,
});

const verifier = new AssistantAgent({
  name: "compliance_verifier",
  modelClient,
  systemMessage: `
You are a strict verifier for insurance compliance decisions.
Challenge weak findings. If evidence is insufficient, mark as needs_human_review.
Do not invent regulations. Use only the provided content and rule summary.
`,
});

const groupChat = new GroupChat({
  agents: [reviewer, verifier],
  messages: [],
  maxRounds: 4,
});

const manager = new GroupChatManager({
  groupChat,
});

3) Run a review request and parse the result

Keep the prompt deterministic. In insurance workflows, you want repeatability more than creativity. The output should be machine-readable so downstream systems can block release or route to legal/compliance.

async function runComplianceCheck(input: ComplianceInput) {
  const prompt = `
Review this insurance document for compliance issues.

Document ID: ${input.documentId}
Jurisdiction: ${input.jurisdiction}
Line of Business: ${input.lineOfBusiness}
Document Type: ${input.documentType}
Rules Version: ${input.rulesVersion}

Content:
${input.content}

Return:
{
  "verdict": "pass" | "fail" | "needs_human_review",
  "findings": [
    {
      "severity": "low" | "medium" | "high",
      "issue": string,
      "evidence": string,
      "recommended_fix": string
    }
  ]
}
`;

  const result = await manager.run(prompt);
  return result;
}

4) Add guardrails before release

Do not let the model directly approve customer-facing content without checks around sensitive classes of data and jurisdictional routing. Use schema validation on both input and output, then persist everything needed for audit.

import fs from "node:fs/promises";

async function auditAndDecide(rawInput: unknown) {
  const input = ComplianceInputSchema.parse(rawInput);
  
  const result = await runComplianceCheck(input);

  await fs.appendFile(
    "./audit-log.jsonl",
    JSON.stringify({
      timestamp: new Date().toISOString(),
      documentId: input.documentId,
      jurisdiction: input.jurisdiction,
      rulesVersion: input.rulesVersion,
      result,
    }) + "\n"
  );

  return result;
}

Production Considerations

  • Data residency

    • Keep EU/UK policyholder data in-region if your regulatory obligations require it.
    • Route documents by jurisdiction before they hit the model client.
  • Auditability

    • Store prompt, response, model version, rules version, and operator action.
    • Regulators care about why a decision was made, not just whether it was made.
  • Human-in-the-loop thresholds

    • Auto-block high-risk outputs like coverage guarantees or claims denials with legal implications.
    • Send ambiguous cases to licensed compliance staff instead of forcing an LLM verdict.
  • Monitoring

    • Track false positives by product line and jurisdiction.
    • Watch for drift when policy templates or regulations change; re-run golden test sets on every prompt update.

Common Pitfalls

  • Using one generic prompt for all insurance lines

    • Life insurance disclosures are not auto claim letters.
    • Split prompts by line of business and document type so the agent checks the right obligations.
  • Skipping versioned rules

    • If you do not pin rulesVersion, you cannot explain which policy or regulation drove the outcome.
    • Version your rule summaries like application code.
  • Letting the model free-form its output

    • Unstructured prose is hard to validate and harder to audit.
    • Force JSON output with explicit fields like verdict, severity, evidence, and recommended_fix.

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