How to Build a claims processing Agent Using LangChain in Python for investment banking
A claims processing agent in investment banking takes inbound claim documents, extracts the relevant facts, checks them against policy and transaction data, routes exceptions, and produces an auditable decision trail. It matters because claims handling sits at the intersection of client service, operational risk, compliance, and money movement; if you get it wrong, you create regulatory exposure and reconciliation problems fast.
Architecture
- •
Document ingestion layer
- •Pulls PDFs, emails, scanned forms, and structured attachments from approved internal systems.
- •Normalizes content into text chunks with metadata like client ID, jurisdiction, product type, and timestamp.
- •
Extraction chain
- •Uses an LLM to extract claim fields such as claimant name, event date, loss amount, account references, and supporting evidence.
- •Returns structured output instead of free text so downstream systems can validate it.
- •
Policy and rules layer
- •Checks extracted fields against banking policy rules, product eligibility, KYC status, and transaction history.
- •Separates deterministic validation from model reasoning.
- •
Decision router
- •Sends low-risk claims to straight-through processing.
- •Escalates ambiguous or high-value claims to human operations or compliance review.
- •
Audit and traceability store
- •Persists prompts, model outputs, tool calls, retrieved documents, and final decisions.
- •Supports internal audit, model risk management, and regulatory review.
- •
Security and residency controls
- •Enforces access control on client data.
- •Keeps processing inside approved regions and logs all cross-system reads.
Implementation
1) Define the claim schema and build the extraction chain
Use PydanticOutputParser so the model returns validated fields. In banking workflows, this is better than parsing raw text because you need consistent outputs for downstream controls.
from typing import Literal
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
class ClaimRecord(BaseModel):
claimant_name: str = Field(description="Name of the claimant")
claim_type: Literal["fee_dispute", "trade_error", "settlement_issue", "other"]
event_date: str = Field(description="ISO date string")
amount: float = Field(description="Claim amount")
account_reference: str
jurisdiction: str
summary: str
parser = PydanticOutputParser(pydantic_object=ClaimRecord)
prompt = ChatPromptTemplate.from_messages([
("system", "Extract claim details from banking claim documents. "
"Return only structured data. Do not infer missing facts."),
("human", "{document}\n\n{format_instructions}")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
extract_chain = prompt | llm | parser
doc_text = """
Client alleges a settlement issue on 2024-11-03 for USD 125000.
Account reference IB-77821. Jurisdiction: UK.
Claimant: Meridian Capital Ltd.
"""
result = extract_chain.invoke({
"document": doc_text,
"format_instructions": parser.get_format_instructions()
})
print(result.model_dump())
2) Add retrieval for policy checks
Claims agents in investment banking should not rely on the model’s memory. Use VectorStoreRetriever or a similar retriever over approved policy docs so the agent grounds decisions in current rules.
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
policy_docs = [
Document(page_content="Settlement issues above USD 100000 require manual review.", metadata={"policy_id": "POL-01"}),
Document(page_content="UK claims must retain audit logs for seven years.", metadata={"policy_id": "POL-02"}),
]
vectorstore = FAISS.from_documents(policy_docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
policy_context = retriever.invoke("USD 125000 settlement issue UK")
for doc in policy_context:
print(doc.page_content)
3) Route decisions with explicit thresholds
Use deterministic logic around the LLM output. The model extracts; your code decides. That keeps high-value claims from being auto-approved without controls.
def route_claim(claim: ClaimRecord) -> str:
if claim.amount >= 100000:
return "manual_review"
if claim.claim_type == "trade_error":
return "operations_review"
if claim.jurisdiction.lower() in {"uk", "eu"}:
return "compliance_check"
return "straight_through"
decision = route_claim(result)
print(decision)
4) Wrap the workflow in a LangChain runnable pipeline
This pattern gives you composability and observability. You can add tracing later with LangSmith without rewriting the core flow.
from langchain_core.runnables import RunnableLambda
def enrich_with_policy(claim: ClaimRecord):
query = f"{claim.claim_type} {claim.amount} {claim.jurisdiction}"
docs = retriever.invoke(query)
return {
"claim": claim.model_dump(),
"policy_hits": [d.page_content for d in docs],
"decision": route_claim(claim),
}
pipeline = extract_chain | RunnableLambda(enrich_with_policy)
output = pipeline.invoke({
"document": doc_text,
"format_instructions": parser.get_format_instructions()
})
print(output)
Production Considerations
- •
Auditability
- •Store every extracted field with source document references and timestamps.
- •Keep prompt versions and model versions tied to each decision for internal audit and model governance.
- •
Data residency
- •Keep ingestion, embeddings, vector storage, and inference inside approved regions.
- •Do not send client identifiers or sensitive trade data to unmanaged endpoints.
- •
Compliance guardrails
- •Block auto-resolution when claims touch sanctions screening, suspicious activity indicators, or legal hold cases.
- •Require human approval for exceptions above threshold or outside policy coverage.
- •
Monitoring
- •Track extraction accuracy by field type, escalation rate, false positives on manual review thresholds, and latency per region.
- •Alert on prompt drift when policy documents change or model outputs start missing required fields.
Common Pitfalls
- •
Letting the LLM make final decisions
- •Bad pattern: “approve/deny” directly from the model.
- •Fix: use the model for extraction and classification support only; keep approvals in deterministic code plus human review gates.
- •
Skipping structured output validation
- •Bad pattern: parsing free-form text from the assistant response.
- •Fix: use
PydanticOutputParseror another structured parser so invalid amounts, dates, or missing fields fail fast.
- •
Ignoring policy versioning
- •Bad pattern: retrieving whatever policy text is currently indexed without version control.
- •Fix: tag policies by effective date and jurisdiction so you can reproduce why a claim was routed a certain way during audit.
- •
Overlooking sensitive-data boundaries
- •Bad pattern: embedding full claim packets with account numbers into a general-purpose vector store.
- •Fix: redact where possible, tokenize identifiers when needed, and keep storage aligned with bank data handling rules.
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