How to Build a compliance checking Agent Using LangGraph in Python for insurance
A compliance checking agent for insurance reviews policy language, claims notes, customer communications, and underwriting decisions against internal rules and regulatory constraints. It matters because a missed disclosure, an unapproved phrase, or a bad escalation path can turn into fines, rework, or a denied claim dispute that should have been caught earlier.
Architecture
- •
Input normalizer
- •Cleans and structures incoming text from emails, PDFs, CRM notes, or claim forms.
- •Extracts the document type, jurisdiction, and line of business before any policy checks run.
- •
Policy rules loader
- •Pulls insurer-specific controls from a versioned store.
- •Keeps rules separate by product line and region so you can enforce different requirements for auto, health, life, or property.
- •
Compliance checker node
- •Evaluates the content against rules like required disclosures, prohibited phrases, retention obligations, and escalation triggers.
- •Returns structured findings instead of free-form prose.
- •
Audit trail writer
- •Stores inputs, rule versions, outputs, and timestamps.
- •This is non-negotiable in insurance when regulators ask why a decision was made.
- •
Human review gate
- •Routes high-risk findings to an underwriter, compliance analyst, or claims supervisor.
- •Prevents the agent from making final decisions on regulated outcomes.
- •
Output formatter
- •Produces a clean result for downstream systems: pass/fail, reasons, severity, and next action.
Implementation
1) Define the state and the checks
Use TypedDict for graph state so every node knows exactly what it receives and returns. Keep the output structured; don’t let the model decide your schema.
from typing import TypedDict, List, Literal
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
class ComplianceState(TypedDict):
text: str
jurisdiction: str
line_of_business: str
findings: List[str]
risk_level: Literal["low", "medium", "high"]
approved: bool
def normalize_input(state: ComplianceState) -> ComplianceState:
text = state["text"].strip()
return {**state, "text": text}
def check_compliance(state: ComplianceState) -> ComplianceState:
findings = []
text = state["text"].lower()
if "guaranteed approval" in text:
findings.append("Prohibited promise detected: guaranteed approval")
if state["jurisdiction"] == "CA" and "privacy notice" not in text:
findings.append("Missing privacy notice reference for California")
risk_level = "high" if findings else "low"
approved = len(findings) == 0
return {**state, "findings": findings, "risk_level": risk_level, "approved": approved}
2) Add a human review branch with LangGraph routing
This is where LangGraph helps more than a plain chain. Use conditional edges to send high-risk cases to review instead of auto-approving them.
def route_after_check(state: ComplianceState):
if state["risk_level"] == "high":
return "human_review"
return END
def human_review(state: ComplianceState) -> ComplianceState:
# Replace this with an actual queue/task assignment in production
findings = state["findings"] + ["Escalated to compliance reviewer"]
return {**state, "findings": findings}
graph = StateGraph(ComplianceState)
graph.add_node("normalize_input", normalize_input)
graph.add_node("check_compliance", check_compliance)
graph.add_node("human_review", human_review)
graph.add_edge(START, "normalize_input")
graph.add_edge("normalize_input", "check_compliance")
graph.add_conditional_edges("check_compliance", route_after_check)
app = graph.compile()
3) Run the graph on an insurance use case
This example checks a customer-facing message before it goes out. In insurance workflows this can sit between CRM drafting and outbound sending.
initial_state = {
"text": """
Thanks for your application.
You are guaranteed approval based on this quote.
Please review our terms.
""",
"jurisdiction": "CA",
"line_of_business": "auto",
"findings": [],
"risk_level": "low",
"approved": False,
}
result = app.invoke(initial_state)
print(result["approved"])
print(result["risk_level"])
print(result["findings"])
4) Make the agent auditable
For insurance you need traceability. Store the input payload, rule version, output state, reviewer action, and timestamp in your logging layer or case management system.
A practical pattern is to wrap app.invoke() with persistence:
- •write the raw input to immutable storage
- •write the final graph state to your audit table
- •include document hash and rule set version
- •keep reviewer overrides separate from model output
If you want multi-step enrichment later, LangGraph supports add_node, add_edge, add_conditional_edges, and compile() cleanly enough that you can extend this into extraction → rules → review → publish without rewriting the orchestration layer.
Production Considerations
- •
Data residency
- •Keep policy documents and customer PII in-region.
- •If you operate across EU/US/APAC lines of business, pin storage and inference endpoints to the correct jurisdiction.
- •
Auditability
- •Persist every decision with a deterministic rule version.
- •Regulators care about what rule fired at the time of decision, not what your current prompt says today.
- •
Guardrails
- •Never let the agent auto-finalize adverse decisions on its own.
- •Use hard-coded thresholds for escalation on high-risk phrases like “denied coverage,” “excluded,” or “non-renewal.”
- •
Monitoring
- •Track false positives by line of business and jurisdiction.
- •A noisy compliance agent gets ignored by operations teams fast.
Common Pitfalls
- •
Using free-form LLM output as the final decision
- •Fix it by forcing structured fields like
approved,risk_level, andfindings. - •Insurance workflows need deterministic downstream behavior.
- •Fix it by forcing structured fields like
- •
Mixing jurisdictions in one rule set
- •Fix it by loading controls per region and product line.
- •California privacy language is not the same as UK FCA disclosure requirements.
- •
Skipping audit metadata
- •Fix it by storing input hash, rule version, graph version, timestamp, and reviewer ID.
- •Without that trail you cannot defend the decision during an internal audit or regulator review.
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