How to Build a Multi-Agent Loan Underwriting Committee in Python¶
Good credit decisions surface both the case for and against an application before a senior decides. This recipe uses the Debate pattern: an approve-advocate and a decline-advocate argue the loan with specific evidence, and a senior-underwriter judge weighs the exchange into a decision with conditions — an auditable alternative to a single opaque score.
Patterns used: Debate
Architecture¶
flowchart TD
A[Loan Application] --> D{Debate}
D --> AP[Approve Advocate]
D --> DC[Decline Advocate]
AP <-->|rounds| DC
AP --> J[Senior Underwriter\nJudge]
DC --> J
J --> R[Decision + Conditions]
Implementation¶
import asyncio
from pyagent_patterns.base import Agent
from pyagent_patterns.resolution import Debate
from pyagent_providers import AnthropicLLM, GeminiLLM
committee = Debate(
debaters=[
Agent(
"approve_advocate",
GeminiLLM("gemini-2.5-pro"),
system_prompt=(
"Argue to APPROVE this loan. Cite debt-to-income, credit history, collateral, and "
"stable income. Pre-empt the decline case with mitigants and proposed conditions."
),
),
Agent(
"decline_advocate",
GeminiLLM("gemini-2.5-pro"),
system_prompt=(
"Argue to DECLINE this loan. Focus on repayment risk, thin file, concentration, and "
"downside scenarios. Rebut the approve case with specific counter-evidence."
),
),
],
judge=Agent(
"senior_underwriter",
AnthropicLLM("claude-sonnet-4-20250514"),
system_prompt=(
"You are the senior underwriter. Weigh both arguments and decide: APPROVE, "
"APPROVE WITH CONDITIONS, or DECLINE. State the key reasons and any conditions "
"(rate, term, collateral, covenants). Be explicit about the deciding factor."
),
),
rounds=2,
)
result = asyncio.run(committee.run(
"Application: $250k 7-year business loan. DTI 38%, credit score 690, 2 years trading, "
"revenue $480k (growing), $90k equipment as collateral, one prior late payment."
))
print(result.output)
print(f"Rounds: {result.metadata['rounds']}")
Expected output¶
DECISION — APPROVE WITH CONDITIONS
Deciding factor: collateral + revenue growth offset the thin file and one late payment.
Conditions: rate +1.5% risk premium, personal guarantee, quarterly financials covenant,
cap utilization until 12 clean months.
Approve case: serviceable DTI, growing revenue, secured.
Decline case: short trading history, single collateral asset.
Rounds: 2
The transcript of both advocates and the judge's reasoning is your audit trail for regulators.
Customization¶
Add a third advocate¶
committee.debaters.append(
Agent("policy_advocate", GeminiLLM("gemini-2.5-pro"),
system_prompt="Argue from lending-policy and regulatory limits (LTV, DTI caps)."),
)
Tune the debate depth¶
Structured decision¶
committee.judge.system_prompt += " Output as JSON: {decision, rate, conditions[], deciding_factor}."
When to Use¶
| Situation | Use Debate? |
|---|---|
| A decision benefits from explicit for/against argument | ✅ Yes |
| You need an auditable rationale, not just a score | ✅ Yes |
| Independent graders should vote a label | ❌ Use Voting |
| A document moves through fixed processing steps | ❌ Use Loan Origination Workflow |
Cost Profile¶
| Driver | Typical model | Avg cost | Volume (1k apps/mo) |
|---|---|---|---|
| 2 debaters × 2 rounds | gemini-pro | $0.012 | $360/mo |
| Judge | claude-sonnet | $0.006 | $180/mo |
| Per application | mix | ~$0.018 | ~$540/mo |
See Also¶
- Debate pattern
- Loan Origination Workflow — the document pipeline that precedes underwriting
- Browse all recipes