How to Build a underwriting Agent Using LlamaIndex in TypeScript for insurance

By Cyprian AaronsUpdated 2026-04-21
underwritingllamaindextypescriptinsurance

An underwriting agent turns raw insurance submissions into a structured risk assessment: it reads the application, pulls relevant policy and underwriting rules, checks supporting documents, and drafts a recommendation for a human underwriter. That matters because underwriting is where speed, consistency, and compliance all collide; if you get the agent wrong, you create bad risk decisions, audit gaps, or regulatory exposure.

Architecture

  • Submission intake layer

    • Accepts ACORD forms, broker emails, PDFs, loss runs, and supplemental docs.
    • Normalizes everything into text plus metadata like line of business, jurisdiction, and submission date.
  • Underwriting knowledge index

    • Stores appetite guidelines, referral rules, policy wordings, claims manuals, and jurisdiction-specific constraints.
    • Built with LlamaIndex so the agent can retrieve the exact source passages used in a decision.
  • Document extraction pipeline

    • Uses LlamaIndex readers/loaders to ingest PDFs and text.
    • Extracts fields like insured name, address, limits requested, prior losses, and industry class.
  • Risk reasoning layer

    • Prompts an LLM to classify the submission against underwriting rules.
    • Produces structured output: accept / refer / decline + rationale + missing information.
  • Audit and traceability layer

    • Persists retrieved chunks, model output, and source citations.
    • Required for internal audit, regulator review, and disputes over decisioning.
  • Human-in-the-loop review

    • Routes borderline cases to an underwriter.
    • Keeps the agent as a decision-support system instead of an autonomous authority.

Implementation

1) Install dependencies and define your data model

Use the TypeScript packages from LlamaIndex and keep your output schema strict. For insurance workflows, you want deterministic structure more than creative prose.

npm install llamaindex zod
import { z } from "zod";

export const UnderwritingDecisionSchema = z.object({
  action: z.enum(["accept", "refer", "decline"]),
  confidence: z.number().min(0).max(1),
  reasons: z.array(z.string()),
  missingInformation: z.array(z.string()),
  citedSources: z.array(z.string()),
});

export type UnderwritingDecision = z.infer<typeof UnderwritingDecisionSchema>;

2) Load underwriting documents into a vector index

This example uses SimpleDirectoryReader, VectorStoreIndex, and Settings. In production you would swap the storage backend for something persistent and region-bound.

import {
  Settings,
  SimpleDirectoryReader,
  VectorStoreIndex,
} from "llamaindex";
import { OpenAI } from "@llamaindex/openai";

async function buildIndex() {
  Settings.llm = new OpenAI({
    model: "gpt-4o-mini",
    apiKey: process.env.OPENAI_API_KEY,
  });

  const docs = await new SimpleDirectoryReader().loadData({
    directoryPath: "./underwriting-policies",
  });

  return await VectorStoreIndex.fromDocuments(docs);
}

export { buildIndex };

This gives you a retrieval layer over appetite guides, referral thresholds, excluded classes, and jurisdiction notes. Keep each document chunk small enough that citations point to something an underwriter can actually verify.

3) Create the underwriting agent with retrieval + structured output

The core pattern is: retrieve policy context first, then ask the LLM for a constrained decision. asQueryEngine() is enough for a first pass; if you need tool orchestration later, move to ReActAgent.

import {
  QueryEngineTool,
} from "llamaindex";
import { buildIndex } from "./build-index";
import { UnderwritingDecisionSchema } from "./schema";

async function underwriteSubmission(submissionText: string) {
  const index = await buildIndex();
  const queryEngine = index.asQueryEngine({
    similarityTopK: 5,
    responseMode: "compact",
  });

  const tool = QueryEngineTool.fromDefaults({
    queryEngine,
    name: "underwriting_knowledge_base",
    description:
      "Insurance underwriting guidelines, referral rules, appetite statements, and jurisdiction constraints.",
  });

  const prompt = `
You are an insurance underwriting assistant.
Use only the retrieved underwriting guidance.
Return a strict JSON object matching this schema:
${UnderwritingDecisionSchema.toString()}

Submission:
${submissionText}

Decision rules:
- Decline if the class is explicitly excluded.
- Refer if required information is missing or thresholds are exceeded.
- Accept only if it fits appetite with no material exceptions.
`;

  const response = await tool.queryEngine.query({ query: prompt });

  return response;
}

If you need multiple tools — for example document search plus rating tables plus sanctions screening — use ReActAgent with explicit tools. That gives you controlled tool use instead of stuffing everything into one prompt.

4) Parse the result and persist audit evidence

For insurance workflows, do not just print the answer. Store the submission hash, retrieved sources, model output, timestamp, model version, and reviewer identity.

import fs from "node:fs/promises";
import crypto from "node:crypto";
import { UnderwritingDecisionSchema } from "./schema";

async function run() {
  const submissionText = await fs.readFile("./submissions/sample.txt", "utf8");
  const submissionHash = crypto
    .createHash("sha256")
    .update(submissionText)
    .digest("hex");

  const rawResponse = await underwriteSubmission(submissionText);

  const parsed = UnderwritingDecisionSchema.parse(
    JSON.parse(rawResponse.response ?? "{}")
  );

  await fs.writeFile(
    "./audit-log.json",
    JSON.stringify(
      {
        submissionHash,
        decision: parsed,
        model: process.env.LLM_MODEL ?? "gpt-4o-mini",
        timestamp: new Date().toISOString(),
      },
      null,
      2
    )
  );

  console.log(parsed);
}

run();

That audit record is what lets compliance teams reconstruct why the agent referred or declined a risk. If your regulator asks how a decision was made, “the model said so” is not an answer.

Production Considerations

  • Keep data residency explicit

    Store submissions and indexes in-region. If your policyholder data cannot leave a jurisdiction, do not send raw documents to a hosted model outside that boundary.

  • Log retrieval evidence separately from prompts

    Persist chunk IDs, source document names, page numbers if available, and similarity scores. That makes it possible to prove which underwriting rule influenced the recommendation.

  • Add guardrails around prohibited attributes

    Screen prompts and extracted fields for protected-class data that should not influence decisions. In insurance this includes anything that could trigger unfair discrimination concerns depending on line of business and jurisdiction.

  • Route low-confidence cases to humans

    Set thresholds on confidence or missing-information count. A clean “refer” path is better than forcing an automated yes/no on incomplete submissions.

Common Pitfalls

  1. Using the agent as a black box decision engine

    • Mistake: letting it produce free-form recommendations with no citations.
    • Fix: require structured output plus source references every time.
  2. Mixing regulatory content with general knowledge

    • Mistake: indexing broad internet content alongside actual underwriting manuals.
    • Fix: keep a curated corpus per product line and jurisdiction.
  3. Ignoring versioning of rules and prompts

    • Mistake: changing appetite rules without tracking which version produced which decision.
    • Fix: version your documents, prompts, embedding settings, and model name in every audit record.
  4. Treating PII like normal text

    • Mistake: sending full submissions to logs or third-party services without controls.
    • Fix: redact where possible before indexing or logging; encrypt at rest; restrict access by role.

If you build this way, LlamaIndex gives you the retrieval backbone for underwriting while keeping the system auditable enough for insurance operations. The real goal is not automation for its own sake; it’s faster triage with defensible decisions.


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