How to Build a underwriting Agent Using LlamaIndex in Python for healthcare

By Cyprian AaronsUpdated 2026-04-21
underwritingllamaindexpythonhealthcare

A healthcare underwriting agent takes patient, plan, and policy data, then helps determine eligibility, risk tiering, and coverage recommendations based on your underwriting rules. It matters because healthcare decisions are high-stakes: you need traceable outputs, policy consistency, and strict handling of PHI/PII across compliance boundaries.

Architecture

  • Policy knowledge base

    • Store underwriting guidelines, plan documents, clinical exclusions, and internal SOPs in a vector index.
    • Use VectorStoreIndex so the agent can retrieve grounded policy passages before making a recommendation.
  • Structured intake layer

    • Normalize applicant data into a consistent schema: age, diagnosis codes, medications, prior claims, geography, and plan type.
    • Keep raw PHI out of prompts unless it is required for the decision.
  • Retrieval + reasoning layer

    • Use RetrieverQueryEngine or an agent tool over the index to answer underwriting questions with citations.
    • Force the model to explain which rule triggered a decision.
  • Decision engine

    • Convert retrieved evidence into a structured output such as approve / review / deny / refer-to-human.
    • Use Pydantic models for deterministic downstream processing.
  • Audit logging

    • Persist input hashes, retrieved sources, model version, and final recommendation.
    • This is mandatory for healthcare audits and internal review.
  • Guardrails

    • Add PHI redaction, confidence thresholds, and human escalation paths for edge cases.
    • Do not let the model auto-finalize adverse decisions without review if your compliance team requires it.

Implementation

1) Build the policy index

Start by loading underwriting documents from disk and indexing them with LlamaIndex. For healthcare use cases, keep policy docs separate from patient records so you can enforce access controls cleanly.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.settings import Settings
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI

# Configure models
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)

# Load underwriting policies
documents = SimpleDirectoryReader("./underwriting_policies").load_data()

# Build the index
index = VectorStoreIndex.from_documents(documents)

# Create a query engine for grounded answers
query_engine = index.as_query_engine(similarity_top_k=4)

2) Define the underwriting decision schema

You want structured output, not free-form prose. A Pydantic model gives you predictable fields for workflow routing and audit logs.

from pydantic import BaseModel, Field
from typing import Literal

class UnderwritingDecision(BaseModel):
    decision: Literal["approve", "manual_review", "deny"]
    risk_band: Literal["low", "medium", "high"]
    rationale: str = Field(description="Short explanation tied to policy evidence")
    cited_policy_section: str = Field(description="Policy section used in the decision")

3) Query policy evidence and generate the decision

Use as_query_engine() to ground the response in your indexed policy docs. Then map that response into your structured underwriting output.

from llama_index.core.prompts import PromptTemplate

prompt = PromptTemplate(
    """You are a healthcare underwriting assistant.
Use only the provided policy context to make a decision.

Applicant profile:
{profile}

Policy context:
{context}

Return a concise underwriting recommendation with:
- decision: approve | manual_review | deny
- risk_band: low | medium | high
- rationale: one or two sentences
- cited_policy_section: exact section name or quote"""
)

def underwrite(profile: str):
    response = query_engine.query(prompt.format(profile=profile, context="{context}"))
    return response.response

applicant_profile = """
Age: 54
Condition: Type 2 diabetes
Medication: metformin
Location: California
Requested plan: PPO Gold
"""

result_text = underwrite(applicant_profile)
print(result_text)

For production, you usually want one more step: parse the generated text into your schema and reject malformed outputs. If you prefer tighter control, use PydanticOutputParser with your LLM call path so the model emits valid JSON-like structure every time.

4) Add an agent tool for human escalation

In healthcare underwriting, not every case should be auto-decided. Wrap retrieval in an agent tool so borderline cases can escalate to a human reviewer with full context.

from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.agent.workflow import AgentWorkflow

underwriting_tool = QueryEngineTool.from_defaults(
    query_engine=query_engine,
    name="underwriting_policy_lookup",
    description="Look up healthcare underwriting rules and exclusions."
)

agent = AgentWorkflow.from_tools_or_functions(
    tools=[underwriting_tool],
    llm=Settings.llm,
    system_prompt=(
        "You are a healthcare underwriting assistant. "
        "If policy evidence is ambiguous or confidence is low, route to manual review."
    )
)

# Example execution pattern depends on your app runtime,
# but the tool-based workflow is what you want in production.

Production Considerations

  • Compliance

    • Treat all applicant data as PHI unless your legal team has explicitly classified it otherwise.
    • Log access to policy docs and applicant records separately for HIPAA audit trails.
  • Data residency

    • Keep embeddings, indexes, and traces inside approved regions if your contracts require it.
    • If you serve multiple geographies, build per-region indexes instead of one global store.
  • Monitoring

    • Track denial rates, manual-review rates, retrieval quality, and hallucination incidents.
    • Alert when the model cites missing sections or produces decisions without matching policy evidence.
  • Guardrails

    • Redact sensitive fields before prompting when they are not needed for underwriting.
    • Force human review for high-risk cases like cancer history, transplant history, or incomplete records.

Common Pitfalls

  1. Mixing patient data into the policy index

    • Don’t embed PHI into your knowledge base alongside static rules.
    • Keep policies immutable; keep applicant records ephemeral and access-controlled.
  2. Letting the model decide without citations

    • A naked “approve/deny” is not enough in healthcare.
    • Require cited policy sections in every output so reviewers can verify the basis of the decision.
  3. Ignoring jurisdiction-specific rules

    • Underwriting rules vary by state, payer type, and product line.
    • Partition your retrieval corpus by jurisdiction and plan type so California PPO logic does not bleed into Medicare Advantage or another state’s rules.

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