How to Build a underwriting Agent Using CrewAI in Python for investment banking
An underwriting agent in investment banking helps analysts and bankers turn raw deal inputs into a first-pass credit and risk assessment. It can read borrower financials, extract covenants, flag inconsistencies, draft a credit memo, and route exceptions for human approval, which matters because underwriting speed and consistency directly affect deal execution, risk exposure, and compliance.
Architecture
- •
Input ingestion layer
- •Pulls term sheets, financial statements, KYC files, and sponsor notes from approved sources.
- •Normalizes PDFs, spreadsheets, and text into structured fields.
- •
Analysis agent
- •Reviews leverage, liquidity, coverage ratios, covenant headroom, and qualitative risk factors.
- •Produces an underwriting summary with explicit assumptions.
- •
Compliance/controls agent
- •Checks for policy breaches, missing disclosures, restricted industries, sanctions flags, and required approvals.
- •Enforces human-in-the-loop escalation for exceptions.
- •
Memo generation agent
- •Drafts the credit memo in the bank’s standard format.
- •Includes recommendation, rationale, risks, mitigants, and open items.
- •
Audit logging layer
- •Persists prompts, outputs, source document references, timestamps, and reviewer actions.
- •Supports model governance and regulatory review.
- •
Human approval workflow
- •Routes high-risk cases to a banker or credit officer.
- •Captures sign-off before any downstream system consumes the result.
Implementation
- •Install CrewAI and define the agents
Use crewai with explicit roles. For investment banking workflows, keep each agent narrow so you can audit behavior and isolate failures.
from crewai import Agent
underwriting_analyst = Agent(
role="Underwriting Analyst",
goal="Assess borrower risk using provided financial data and prepare a structured underwriting summary.",
backstory=(
"You are a senior investment banking analyst focused on leveraged finance "
"and corporate lending. You evaluate financial strength, covenant headroom, "
"and key risks using only supplied documents."
),
verbose=True,
allow_delegation=False,
)
compliance_reviewer = Agent(
role="Compliance Reviewer",
goal="Identify policy breaches, missing approvals, sanctions issues, and documentation gaps.",
backstory=(
"You review deals against internal banking policy. You do not estimate or infer "
"missing facts; you only flag issues that require human review."
),
verbose=True,
allow_delegation=False,
)
memo_writer = Agent(
role="Credit Memo Writer",
goal="Draft a concise credit memo suitable for banker review.",
backstory=(
"You write formal investment banking memos with clear recommendations, "
"risks, mitigants, assumptions, and next steps."
),
verbose=True,
allow_delegation=False,
)
- •Define tasks with strict outputs
Use Task descriptions that force structured results. In banking workflows, ambiguity becomes a control issue.
from crewai import Task
underwrite_task = Task(
description=(
"Review the borrower packet: financial statements, term sheet summary, "
"and sponsor notes. Produce: leverage ratios, liquidity view, debt service "
"coverage commentary, key risks, mitigants, and assumptions."
),
expected_output="A structured underwriting summary with numeric ratio analysis and risk flags.",
agent=underwriting_analyst,
)
compliance_task = Task(
description=(
"Check the underwriting summary for policy issues: missing KYC references,"
" restricted sector exposure, sanctions concerns, unusual terms,"
" or unsupported assumptions. Flag anything needing escalation."
),
expected_output="A compliance findings report with explicit escalation items.",
agent=compliance_reviewer,
)
memo_task = Task(
description=(
"Using the underwriting summary and compliance findings,"
" draft a credit memo section with recommendation,"
" key risks, mitigants, conditions precedent,"
" and items requiring human approval."
),
expected_output="A banker-ready credit memo draft.",
agent=memo_writer,
)
- •Assemble the crew and run it
This is the core pattern. Use Crew, Process.sequential, and keep the output deterministic enough for review by constraining scope through task design.
from crewai import Crew
from crewai import Process
crew = Crew(
agents=[underwriting_analyst, compliance_reviewer, memo_writer],
tasks=[underwrite_task, compliance_task, memo_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff()
print(result)
If you need to pass actual deal data into the workflow from your app layer:
deal_context = """
Borrower: Northbridge Logistics Ltd
Revenue: $420M
EBITDA: $68M
Net Debt: $210M
Term Loan A: $150M
Industry: Transportation / Logistics
Notes: Sponsor-backed acquisition financing
"""
underwrite_task.description += f"\n\nDeal context:\n{deal_context}"
compliance_task.description += "\n\nEscalate if any data is missing or inconsistent."
memo_task.description += "\n\nDo not invent facts not present in prior outputs."
- •Add auditability around every run
For investment banking use cases you need traceability more than cleverness. Persist inputs/outputs with timestamps so reviewers can reconstruct how a recommendation was formed.
import json
from datetime import datetime
audit_record = {
"timestamp": datetime.utcnow().isoformat(),
"workflow": "underwriting_agent",
"output": str(result),
}
with open("audit_log.jsonl", "a", encoding="utf-8") as f:
f.write(json.dumps(audit_record) + "\n")
Production Considerations
- •
Deployment
- •Run the agent behind an internal API inside your bank’s approved network boundary.
- •Keep model access restricted to approved regions if data residency applies.
- •Separate environments for development,, UAT,, and production; never test on live borrower data.
- •
Monitoring
- •Track task latency,, tool calls,, exception rates,, and human override frequency.
- •Log every source document reference used in the final memo.
- •Alert when outputs contain unsupported claims or when compliance escalations spike.
- •
Guardrails
- •Block generation of final recommendations unless mandatory fields are present.
- •Require human approval for high-leverage deals,, distressed credits,, regulated industries,, or sanctions-adjacent counterparties.
- •Add prompt constraints that forbid invented financial metrics or unstated assumptions.
- •
Governance
- •Version prompts,, agents,, and task definitions like code artifacts.
- •Keep an approval trail for model changes so audit can map output drift to configuration changes.
- •Retain records according to your bank’s retention policy.
Common Pitfalls
- •
Letting one agent do everything
- •This creates opaque behavior and weak controls.
- •Split analysis,, compliance,, and memo drafting into separate agents with narrow responsibilities.
- •
Skipping structured inputs
- •Free-form text leads to hallucinated ratios or inconsistent interpretations of deal terms.
- •Normalize borrower data before it reaches CrewAI and force explicit assumptions in every task output.
- •
Ignoring review requirements
- •An underwriting draft is not an approved credit decision.
- •Build mandatory human sign-off into the workflow for exceptions,, large exposures,, policy breaches,, or incomplete diligence.
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