How to Build a underwriting Agent Using AutoGen in Python for retail banking
A retail banking underwriting agent automates the first pass of credit decisions: it pulls applicant data, checks policy rules, scores risk, and produces a decision package for a human underwriter or downstream workflow. It matters because retail banks need faster approvals without losing control over compliance, auditability, and consistent application of lending policy.
Architecture
- •
Applicant intake layer
- •Receives structured application data from LOS, CRM, or API gateway.
- •Normalizes fields like income, employment status, debt obligations, and consent flags.
- •
Policy and compliance agent
- •Encodes lending policy constraints.
- •Checks hard rules such as minimum age, residency, KYC status, and prohibited attributes.
- •
Risk analysis agent
- •Evaluates affordability, debt-to-income ratio, and basic credit risk signals.
- •Produces a reasoned recommendation with evidence from the input payload.
- •
Audit logger
- •Stores every prompt, tool call, model output, and final decision.
- •Required for model governance, dispute handling, and internal audit review.
- •
Human review handoff
- •Escalates borderline or policy-sensitive cases to an underwriter.
- •Prevents the agent from making final decisions on unsupported cases.
- •
AutoGen orchestration layer
- •Coordinates the agents using
AssistantAgent,UserProxyAgent, andGroupChat. - •Handles turn-taking and termination logic.
- •Coordinates the agents using
Implementation
- •Install AutoGen and define your data contract
For retail banking, keep the input schema strict. Don’t let free-form text drive underwriting logic unless you’ve already validated it against your policy engine.
from dataclasses import dataclass
from typing import Optional
@dataclass
class Applicant:
applicant_id: str
country: str
age: int
monthly_income: float
monthly_debt_payments: float
employment_status: str
has_kyc_passed: bool
consent_to_process: bool
requested_amount: float
purpose: str
- •Create AutoGen agents with explicit roles
Use separate agents for policy review and risk analysis. That keeps responsibilities clear and makes audit trails easier to interpret later.
import autogen
llm_config = {
"model": "gpt-4o-mini",
"api_key": "YOUR_OPENAI_API_KEY",
}
policy_agent = autogen.AssistantAgent(
name="policy_agent",
llm_config=llm_config,
system_message=(
"You are a retail banking underwriting policy checker. "
"Only approve applications that satisfy policy constraints. "
"If required data is missing or consent is false, reject escalation."
),
)
risk_agent = autogen.AssistantAgent(
name="risk_agent",
llm_config=llm_config,
system_message=(
"You are a retail banking risk analyst. "
"Assess affordability using DTI and income stability. "
"Return a concise recommendation with reasons."
),
)
user_proxy = autogen.UserProxyAgent(
name="underwriting_orchestrator",
human_input_mode="NEVER",
)
- •Wire the conversation with a group chat
This is the core pattern. The orchestrator sends the applicant payload to both agents, collects their outputs, and terminates when a final recommendation is produced.
from autogen import GroupChat, GroupChatManager
applicant = Applicant(
applicant_id="A12345",
country="KE",
age=34,
monthly_income=180000.0,
monthly_debt_payments=42000.0,
employment_status="permanent",
has_kyc_passed=True,
consent_to_process=True,
requested_amount=250000.0,
purpose="personal loan",
)
message = f"""
Evaluate this retail banking loan application.
Applicant:
{applicant}
Return:
1) Policy eligibility verdict
2) Risk assessment verdict
3) Final recommendation: APPROVE / REFER / DECLINE
4) Reasons suitable for audit logging
"""
groupchat = GroupChat(
agents=[user_proxy, policy_agent, risk_agent],
messages=[],
max_round=4,
)
manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)
result = user_proxy.initiate_chat(
manager,
message=message,
)
print(result.summary if hasattr(result, "summary") else "No summary available")
- •Add deterministic pre-checks before the LLM call
This is where most banking teams get better outcomes than by asking the model to do everything. Hard rules should be enforced in Python before any agent reasoning starts.
def precheck(applicant: Applicant) -> list[str]:
violations = []
if not applicant.consent_to_process:
violations.append("Missing consent to process personal data")
if not applicant.has_kyc_passed:
violations.append("KYC not completed")
if applicant.age < 18:
violations.append("Applicant below minimum age")
dti = applicant.monthly_debt_payments / max(applicant.monthly_income, 1)
if dti > 0.5:
violations.append(f"DTI too high: {dti:.2f}")
return violations
violations = precheck(applicant)
if violations:
print({"decision": "DECLINE", "reasons": violations})
else:
print("Proceed to AutoGen workflow")
Production Considerations
- •
Keep model decisions non-final for regulated credit
- •Use the agent for recommendation only.
- •Final approval should remain with a rules engine or human underwriter when required by policy.
- •
Log everything for auditability
- •Persist input payloads, prompts, outputs, timestamps, model version, and rule outcomes.
- •Store logs in an immutable audit store tied to
applicant_id.
- •
Enforce data residency
- •Route customer data to region-approved infrastructure only.
- •Redact PII before sending anything unnecessary to the LLM.
- •
Add guardrails around adverse action reasons
- •Ensure reasons are based on approved factors like income stability or DTI.
- •Never let the model generate prohibited explanations tied to protected attributes.
Common Pitfalls
- •
Letting the LLM replace policy logic
- •Mistake: asking the agent to decide eligibility from scratch.
- •Fix: run deterministic eligibility checks first; use AutoGen for reasoning and summarization only.
- •
Sending raw sensitive data into prompts
- •Mistake: passing full statements, IDs, or unredacted KYC documents.
- •Fix: minimize prompt payloads and redact anything not needed for underwriting analysis.
- •
Skipping traceability across agent turns
- •Mistake: storing only the final answer.
- •Fix: capture each message in the
GroupChatflow so compliance teams can reconstruct how the recommendation was produced.
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