How to Build a claims processing Agent Using LangChain in Python for lending
A claims processing agent for lending takes incoming borrower disputes, payment claims, hardship requests, or charge corrections and turns them into structured case decisions. It matters because lending operations live and die on turnaround time, auditability, and consistency; if your agent cannot explain its decision path, you will create compliance risk fast.
Architecture
- •
Input intake layer
- •Accepts emails, portal forms, PDFs, or CRM notes.
- •Normalizes raw text into a single claim payload.
- •
Document retrieval layer
- •Pulls policy docs, loan agreement clauses, servicing rules, and dispute procedures.
- •Usually backed by a vector store plus metadata filters for product, region, and loan type.
- •
LLM reasoning layer
- •Uses LangChain to classify the claim, extract key fields, and draft a recommended action.
- •Must be constrained to the allowed policy scope.
- •
Decision engine
- •Applies deterministic business rules after the model output.
- •Handles thresholds like “auto-approve under $50,” “escalate if fraud indicators exist,” or “manual review for regulated complaints.”
- •
Audit and logging layer
- •Stores inputs, retrieved sources, model output, and final decision.
- •Needed for compliance reviews and dispute traceability.
- •
Human review queue
- •Routes ambiguous or high-risk claims to an operations analyst.
- •Critical for adverse actions and regulated lending exceptions.
Implementation
1) Install the core packages
Use LangChain’s current split packages. For a simple RAG-style claims agent, you need the core runtime plus a chat model integration.
pip install langchain langchain-openai pydantic
Set your API key before running anything:
export OPENAI_API_KEY="your-key"
2) Define the claim schema and build the prompt
For lending workflows, do not let the model freewheel. Force structured output so downstream rules can make deterministic decisions.
from typing import Literal
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
class ClaimDecision(BaseModel):
claim_type: Literal["payment_dispute", "fee_dispute", "hardship_request", "billing_error", "other"]
risk_level: Literal["low", "medium", "high"]
recommended_action: Literal["auto_approve", "request_more_info", "escalate_to_human"]
rationale: str = Field(description="Short explanation grounded in policy text")
missing_information: list[str] = []
prompt = ChatPromptTemplate.from_messages([
("system",
"You are a lending claims processing assistant. "
"Use only the provided policy context. "
"Do not invent policy. "
"Return structured output that matches the schema."),
("human",
"Claim text:\n{claim_text}\n\nPolicy context:\n{policy_context}")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
structured_llm = llm.with_structured_output(ClaimDecision)
chain = prompt | structured_llm
3) Add retrieval from lending policy documents
In production you would load servicing policies into a vector store. Here is the pattern with FAISS, OpenAIEmbeddings, and RetrievalQA-style retrieval logic. The point is to ground every recommendation in lender-approved text.
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
docs = [
Document(
page_content="Payment disputes under $25 may be auto-approved if no prior dispute exists.",
metadata={"product": "personal_loan", "region": "US"}
),
Document(
page_content="Hardship requests must be escalated to human review when borrower mentions unemployment or medical emergency.",
metadata={"product": "personal_loan", "region": "US"}
),
]
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
def get_policy_context(claim_text: str) -> str:
retrieved_docs = retriever.invoke(claim_text)
return "\n".join([doc.page_content for doc in retrieved_docs])
4) Run classification plus deterministic routing
The LLM should recommend; your rules should decide. That separation matters in lending because regulatory exceptions cannot depend on model whim.
def process_claim(claim_text: str):
policy_context = get_policy_context(claim_text)
result = chain.invoke({
"claim_text": claim_text,
"policy_context": policy_context,
})
# Deterministic guardrails
if result.claim_type == "hardship_request":
final_action = "escalate_to_human"
elif result.risk_level == "high":
final_action = "escalate_to_human"
else:
final_action = result.recommended_action
return {
"claim_type": result.claim_type,
"risk_level": result.risk_level,
"llm_recommendation": result.recommended_action,
"final_action": final_action,
"rationale": result.rationale,
"missing_information": result.missing_information,
"policy_context": policy_context,
}
sample_claim = """
I was charged twice for my March payment. I want this fixed before my next due date.
"""
print(process_claim(sample_claim))
This is the core pattern: retrieve approved policy text, ask the model for a structured recommendation, then enforce lender-specific rules outside the model.
Production Considerations
- •
Log everything needed for audit
- •Store claim text, retrieved policy snippets, model version, prompt version, and final action.
- •In lending disputes, you need to reconstruct why a decision happened months later.
- •
Keep data residency explicit
- •If borrower data must stay in-region, pin your model endpoint and vector store deployment accordingly.
- •Do not ship PII to tools or SaaS services that violate jurisdictional requirements.
- •
Add hard guardrails before execution
- •Block any action that changes balances or legal status unless a human approves it.
- •Use allowlists for actions like “request_more_info” or “route_to_queue.”
- •
Monitor drift by claim type
- •Track escalation rates by product line, region, channel, and language.
- •A spike in “high risk” classifications often means your prompts or retrieval corpus drifted.
Common Pitfalls
- •
Letting the LLM make final decisions
- •Wrong pattern: “model says approve it.”
- •Fix: use the model for extraction and recommendation only; enforce approval logic with deterministic code.
- •
Retrieving generic policy instead of product-specific rules
- •A mortgage chargeback rule is not a personal loan fee rule.
- •Fix: filter retrieval by
product,region, andeffective_datemetadata.
- •
Skipping audit trails
- •If you do not persist retrieved context and outputs, you cannot defend decisions during compliance review.
- •Fix: write every run to an immutable log with timestamps, document IDs, and prompt versions.
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