A borrower applies for a business loan. CIBIL score: 720. Income proof: Submitted. Bank statements: Clean.

Approved.

Six months later, the loan is non-performing. What happened?

The credit score said nothing about:

  • The borrower’s primary customer had filed for bankruptcy two weeks before the loan application
  • Three key suppliers had stopped extending credit to the borrower’s business
  • The borrower’s industry was entering a cyclical downturn visible in GST filing patterns across the sector
  • Professional network analysis showed the borrower’s business partners were exiting similar ventures

The credit score was accurate. It just measured the wrong things - or rather, it measured the right things at the wrong time, without context.

This is the fundamental limitation of score-based underwriting. And it’s what agentic AI is positioned to solve.

The Credit Score Problem

Credit scores are backward-looking, individual-centric, and context-free.

Backward-looking: A credit score tells you how someone behaved in the past. It says nothing about whether the conditions that enabled that behavior still exist.

Individual-centric: Credit scores treat borrowers as isolated economic units. But businesses exist in ecosystems - suppliers, customers, competitors, partners. A business with a perfect credit history can become high-risk overnight if its ecosystem deteriorates.

Context-free: A 720 score means the same thing whether the borrower is in a booming industry or a declining one, whether they’re in a tier-1 city or a rural area, whether they’re a first-generation entrepreneur or from a business family.

flowchart TB
    subgraph Traditional["Traditional Underwriting"]
        A[Credit Score] --> B{Threshold}
        B -->|Above| C[Approve]
        B -->|Below| D[Reject]
    end

    subgraph Reality["Economic Reality"]
        E[Borrower]
        F[Customers]
        G[Suppliers]
        H[Competitors]
        I[Industry Trends]
        J[Geographic Factors]
        K[Network Effects]

        E --- F
        E --- G
        E --- H
        F --- I
        G --- I
        E --- J
        E --- K
    end

    Traditional -.->|Ignores| Reality

What Agentic AI Makes Possible

Agentic AI isn’t about replacing credit scores with a fancier model. It’s about building systems that can:

  1. Orchestrate complex data gathering across multiple sources
  2. Reason about relationships between entities
  3. Detect signals that humans would miss in the noise
  4. Adapt investigation depth based on what the agent finds
  5. Explain its reasoning in terms underwriters can verify

Here’s an architecture that actually works:

flowchart TB
    subgraph Orchestrator["Underwriting Orchestrator Agent"]
        A[Application Intake]
        B[Investigation Planner]
        C[Evidence Synthesizer]
        D[Decision Recommender]
    end

    subgraph Specialists["Specialist Agents"]
        E[Entity Verification Agent]
        F[Financial Analysis Agent]
        G[Ecosystem Analysis Agent]
        H[Industry Context Agent]
        I[Behavioral Pattern Agent]
    end

    subgraph DataSources["Data Sources"]
        J[(Bureau Data)]
        K[(GST Network)]
        L[(MCA Registry)]
        M[(Banking Data)]
        N[(Professional Networks)]
        O[(Merchant Ecosystem)]
        P[(Industry Databases)]
    end

    A --> B
    B --> E & F & G & H & I
    E --> J & L & N
    F --> M & K
    G --> N & O & K
    H --> P & K
    I --> M & O

    E & F & G & H & I --> C
    C --> D

Let me walk through what each specialist agent does - and why this matters.

Agent 1: Entity Verification Agent

Before analyzing creditworthiness, verify that the entity is what it claims to be.

class EntityVerificationAgent:
    """
    Verify borrower entity across multiple authoritative sources
    """

    async def investigate(self, application: LoanApplication) -> EntityVerification:
        # Parallel verification across sources
        verifications = await asyncio.gather(
            self.verify_mca_registration(application.company_cin),
            self.verify_gst_registration(application.gstin),
            self.verify_udyam_registration(application.udyam_number),
            self.verify_professional_presence(application.directors),
            self.cross_reference_addresses(application),
        )

        # Detect inconsistencies
        inconsistencies = self.detect_cross_source_inconsistencies(verifications)

        # Build entity confidence score
        entity_confidence = self.calculate_entity_confidence(
            verifications,
            inconsistencies
        )

        # Flag shell company indicators
        shell_indicators = self.detect_shell_company_patterns(verifications)

        return EntityVerification(
            verified_identity=entity_confidence > 0.85,
            confidence_score=entity_confidence,
            inconsistencies=inconsistencies,
            shell_company_risk=shell_indicators,
            verification_details=verifications
        )

    def detect_shell_company_patterns(self, verifications) -> list:
        """
        Patterns that indicate potential shell company
        """
        indicators = []

        # Common director across many companies
        if verifications['mca'].director_company_count > 10:
            indicators.append({
                'type': 'excessive_directorships',
                'detail': f"Director holds {verifications['mca'].director_company_count} directorships",
                'risk_weight': 0.3
            })

        # Registered address is a virtual office
        if verifications['address'].is_virtual_office:
            indicators.append({
                'type': 'virtual_office_registration',
                'detail': 'Company registered at known virtual office address',
                'risk_weight': 0.2
            })

        # No GST filings despite claimed revenue
        if verifications['gst'].filing_count == 0 and application.claimed_revenue > 0:
            indicators.append({
                'type': 'no_gst_filings',
                'detail': 'Claims revenue but no GST filings found',
                'risk_weight': 0.5
            })

        # Professional presence doesn't match claimed business scale
        if verifications['professional'].linkedin_employee_count < application.claimed_employees * 0.3:
            indicators.append({
                'type': 'employee_presence_mismatch',
                'detail': f"Claims {application.claimed_employees} employees, {verifications['professional'].linkedin_employee_count} found online",
                'risk_weight': 0.25
            })

        return indicators

This isn’t about catching fraud (though it does). It’s about building confidence in the entity before analyzing its creditworthiness.

Agent 2: Financial Analysis Agent

Go beyond bank statement verification to understand cash flow dynamics.

class FinancialAnalysisAgent:
    """
    Deep financial analysis beyond traditional metrics
    """

    async def investigate(self, application: LoanApplication) -> FinancialAnalysis:
        # Get banking data (with consent)
        bank_data = await self.fetch_bank_statements(application.bank_consent_token)

        # Get GST filing data
        gst_data = await self.fetch_gst_returns(application.gstin)

        # Cross-reference for consistency
        consistency = self.check_bank_gst_consistency(bank_data, gst_data)

        # Analyze cash flow patterns
        cash_flow_analysis = self.analyze_cash_flow_patterns(bank_data)

        # Detect revenue concentration risk
        revenue_concentration = self.analyze_revenue_concentration(bank_data, gst_data)

        # Identify payment behavior patterns
        payment_patterns = self.analyze_payment_patterns(bank_data)

        # Project cash flow under stress scenarios
        stress_projections = self.project_stress_scenarios(cash_flow_analysis)

        return FinancialAnalysis(
            consistency_score=consistency.score,
            consistency_issues=consistency.issues,
            cash_flow_volatility=cash_flow_analysis.volatility,
            revenue_concentration_risk=revenue_concentration,
            payment_discipline_score=payment_patterns.discipline_score,
            stress_test_results=stress_projections
        )

    def analyze_revenue_concentration(self, bank_data, gst_data) -> ConcentrationRisk:
        """
        How dependent is this business on specific customers?
        """
        # Extract unique payers from bank credits
        credit_sources = self.extract_credit_sources(bank_data.transactions)

        # Calculate concentration metrics
        top_1_concentration = credit_sources[0].amount / sum(c.amount for c in credit_sources)
        top_5_concentration = sum(c.amount for c in credit_sources[:5]) / sum(c.amount for c in credit_sources)

        # Identify the top customers
        top_customers = []
        for source in credit_sources[:5]:
            # Try to identify the entity
            identified = await self.identify_entity(source.name, source.account_patterns)
            top_customers.append({
                'identifier': source.name,
                'identified_entity': identified,
                'concentration': source.amount / sum(c.amount for c in credit_sources),
                'payment_regularity': self.calculate_payment_regularity(source.transactions)
            })

        return ConcentrationRisk(
            top_1_concentration=top_1_concentration,
            top_5_concentration=top_5_concentration,
            top_customers=top_customers,
            risk_level='high' if top_1_concentration > 0.4 else 'medium' if top_1_concentration > 0.2 else 'low'
        )

The key insight: a business with 60% revenue from one customer is fundamentally different from a business with diversified revenue - even if their credit scores are identical.

Agent 3: Ecosystem Analysis Agent

This is where it gets interesting. A borrower doesn’t exist in isolation.

class EcosystemAnalysisAgent:
    """
    Analyze the borrower's position in their business ecosystem
    """

    async def investigate(self, application: LoanApplication) -> EcosystemAnalysis:
        # Build the borrower's ecosystem graph
        ecosystem = await self.build_ecosystem_graph(application)

        # Analyze customer health
        customer_health = await self.analyze_customer_health(ecosystem.customers)

        # Analyze supplier relationships
        supplier_stability = await self.analyze_supplier_stability(ecosystem.suppliers)

        # Identify ecosystem-level risks
        ecosystem_risks = self.identify_ecosystem_risks(ecosystem)

        # Calculate network position strength
        network_position = self.calculate_network_position(ecosystem)

        return EcosystemAnalysis(
            ecosystem_graph=ecosystem,
            customer_health_score=customer_health.aggregate_score,
            customer_health_details=customer_health.details,
            supplier_stability_score=supplier_stability.aggregate_score,
            supplier_concentration=supplier_stability.concentration,
            ecosystem_risks=ecosystem_risks,
            network_centrality=network_position.centrality,
            network_resilience=network_position.resilience
        )

    async def build_ecosystem_graph(self, application: LoanApplication) -> EcosystemGraph:
        """
        Build a graph of the borrower's business relationships
        """
        graph = EcosystemGraph(center=application.entity_id)

        # Add customers (from bank statement analysis)
        customers = await self.identify_customers_from_transactions(application)
        for customer in customers:
            graph.add_node(customer.entity_id, type='customer')
            graph.add_edge(customer.entity_id, application.entity_id,
                          relationship='customer_of',
                          weight=customer.transaction_volume)

        # Add suppliers (from GST input credits)
        suppliers = await self.identify_suppliers_from_gst(application.gstin)
        for supplier in suppliers:
            graph.add_node(supplier.entity_id, type='supplier')
            graph.add_edge(application.entity_id, supplier.entity_id,
                          relationship='customer_of',
                          weight=supplier.purchase_volume)

        # Add professional network connections
        professional_connections = await self.analyze_professional_network(application.directors)
        for connection in professional_connections:
            if connection.is_business_relevant:
                graph.add_node(connection.entity_id, type='professional_connection')
                graph.add_edge(application.entity_id, connection.entity_id,
                              relationship=connection.relationship_type)

        # Extend graph one level - customers' customers, suppliers' suppliers
        await self.extend_graph_one_level(graph)

        return graph

    async def analyze_customer_health(self, customers: list) -> CustomerHealthAnalysis:
        """
        How healthy are the borrower's customers?
        """
        health_scores = []

        for customer in customers:
            # Check if customer is identifiable
            if customer.identified_gstin:
                # Get customer's GST filing regularity
                gst_health = await self.check_gst_filing_health(customer.identified_gstin)

                # Check for any negative signals
                negative_signals = await self.check_negative_signals(customer.entity_id)

                health_scores.append({
                    'customer': customer,
                    'gst_filing_regularity': gst_health.filing_regularity,
                    'gst_trend': gst_health.revenue_trend,  # Growing, stable, declining
                    'negative_signals': negative_signals,
                    'health_score': self.calculate_customer_health_score(gst_health, negative_signals)
                })

        # Weighted average by transaction volume
        aggregate_score = sum(
            h['health_score'] * h['customer'].transaction_volume
            for h in health_scores
        ) / sum(h['customer'].transaction_volume for h in health_scores)

        return CustomerHealthAnalysis(
            aggregate_score=aggregate_score,
            details=health_scores,
            at_risk_concentration=sum(
                h['customer'].transaction_volume
                for h in health_scores
                if h['health_score'] < 0.5
            ) / sum(h['customer'].transaction_volume for h in health_scores)
        )

Why this matters: If 40% of a borrower’s revenue comes from customers whose GST filings show declining revenue, that’s a leading indicator of trouble - even if the borrower’s own financials still look healthy.

Agent 4: Industry Context Agent

Same business, different industry context = different risk.

class IndustryContextAgent:
    """
    Understand the industry dynamics affecting this borrower
    """

    async def investigate(self, application: LoanApplication) -> IndustryContext:
        # Identify industry from GST HSN codes
        industry = self.identify_industry(application.primary_hsn_codes)

        # Get industry-level GST trends (aggregated, anonymized)
        industry_trends = await self.fetch_industry_trends(industry.sector_code)

        # Analyze competitive dynamics
        competitive_analysis = await self.analyze_competitive_position(
            application, industry
        )

        # Check for industry-specific risk factors
        industry_risks = self.identify_industry_risks(industry)

        # Compare borrower to industry benchmarks
        benchmark_comparison = self.compare_to_benchmarks(
            application.financials, industry.benchmarks
        )

        return IndustryContext(
            industry=industry,
            industry_growth_trend=industry_trends.growth_rate,
            industry_health_score=industry_trends.health_score,
            borrower_vs_industry=benchmark_comparison,
            competitive_position=competitive_analysis,
            industry_specific_risks=industry_risks
        )

    async def fetch_industry_trends(self, sector_code: str) -> IndustryTrends:
        """
        Aggregate GST data shows industry health
        """
        # This uses aggregated, anonymized industry data
        # Not individual company data

        trends = await self.gst_analytics.get_sector_trends(
            sector_code=sector_code,
            geography=application.state,
            period='trailing_12_months'
        )

        return IndustryTrends(
            growth_rate=trends.yoy_growth,
            growth_trend=trends.growth_trajectory,  # accelerating, stable, decelerating
            health_indicators={
                'filing_regularity': trends.avg_filing_regularity,
                'credit_input_ratio': trends.avg_credit_input_ratio,
                'interstate_activity': trends.interstate_activity_trend,
            },
            seasonal_patterns=trends.seasonal_patterns,
            health_score=self.calculate_industry_health(trends)
        )

Agent 5: Behavioral Pattern Agent

How does the borrower actually behave?

class BehavioralPatternAgent:
    """
    Analyze behavioral patterns that indicate creditworthiness
    """

    async def investigate(self, application: LoanApplication) -> BehavioralAnalysis:
        # Analyze transaction timing patterns
        timing_patterns = self.analyze_transaction_timing(application.bank_transactions)

        # Analyze payment behavior with suppliers
        supplier_payment_behavior = self.analyze_supplier_payments(
            application.bank_transactions
        )

        # Analyze digital footprint consistency
        digital_consistency = await self.analyze_digital_consistency(application)

        # Detect potential round-tripping
        round_trip_indicators = self.detect_round_tripping(application.bank_transactions)

        # Analyze growth patterns
        growth_patterns = self.analyze_growth_patterns(
            application.bank_transactions,
            application.gst_returns
        )

        return BehavioralAnalysis(
            payment_discipline_score=supplier_payment_behavior.discipline_score,
            early_payment_frequency=supplier_payment_behavior.early_payment_ratio,
            transaction_regularity=timing_patterns.regularity_score,
            digital_consistency_score=digital_consistency.score,
            round_trip_risk=round_trip_indicators,
            growth_quality=growth_patterns.quality_score
        )

    def analyze_supplier_payments(self, transactions) -> SupplierPaymentBehavior:
        """
        How does the borrower treat their suppliers?
        """
        # Identify recurring supplier payments
        supplier_payments = self.identify_supplier_payments(transactions)

        # For each supplier, analyze payment timing
        payment_analysis = []
        for supplier, payments in supplier_payments.items():
            # Infer payment terms from patterns
            inferred_terms = self.infer_payment_terms(payments)

            # Calculate how often payments are early, on-time, late
            timing_distribution = self.calculate_timing_distribution(
                payments, inferred_terms
            )

            payment_analysis.append({
                'supplier': supplier,
                'early_ratio': timing_distribution['early'],
                'ontime_ratio': timing_distribution['on_time'],
                'late_ratio': timing_distribution['late'],
                'average_delay_days': timing_distribution['avg_delay']
            })

        # Aggregate across suppliers
        aggregate_discipline = sum(
            p['ontime_ratio'] + p['early_ratio'] * 1.2  # Bonus for early
            for p in payment_analysis
        ) / len(payment_analysis)

        return SupplierPaymentBehavior(
            discipline_score=aggregate_discipline,
            early_payment_ratio=sum(p['early_ratio'] for p in payment_analysis) / len(payment_analysis),
            chronic_late_payers=[p for p in payment_analysis if p['late_ratio'] > 0.3],
            details=payment_analysis
        )

The insight: Someone who consistently pays suppliers early has different risk characteristics than someone who stretches payables - even if their credit score is identical.

The Synthesis: Putting It Together

The orchestrator agent synthesizes findings from all specialists:

class UnderwritingOrchestratorAgent:
    """
    Orchestrate the investigation and synthesize findings
    """

    async def evaluate_application(self, application: LoanApplication) -> UnderwritingDecision:
        # Phase 1: Entity Verification (must pass to continue)
        entity_verification = await self.entity_agent.investigate(application)

        if not entity_verification.verified_identity:
            return UnderwritingDecision(
                decision='reject',
                reason='entity_verification_failed',
                details=entity_verification
            )

        if entity_verification.shell_company_risk.score > 0.7:
            return UnderwritingDecision(
                decision='manual_review',
                reason='shell_company_indicators',
                details=entity_verification
            )

        # Phase 2: Parallel deep investigation
        financial, ecosystem, industry, behavioral = await asyncio.gather(
            self.financial_agent.investigate(application),
            self.ecosystem_agent.investigate(application),
            self.industry_agent.investigate(application),
            self.behavioral_agent.investigate(application)
        )

        # Phase 3: Synthesize findings
        synthesis = self.synthesize_findings(
            entity_verification,
            financial,
            ecosystem,
            industry,
            behavioral
        )

        # Phase 4: Generate recommendation with explanation
        decision = self.generate_decision(synthesis)

        return decision

    def synthesize_findings(self, entity, financial, ecosystem, industry, behavioral) -> Synthesis:
        """
        Create a unified view of the borrower
        """
        # Identify reinforcing signals
        reinforcing = []
        if financial.payment_discipline_score > 0.8 and behavioral.payment_discipline_score > 0.8:
            reinforcing.append({
                'signal': 'consistent_payment_discipline',
                'sources': ['financial_analysis', 'behavioral_analysis'],
                'confidence': 'high'
            })

        # Identify conflicting signals
        conflicting = []
        if financial.cash_flow_volatility < 0.2 and ecosystem.at_risk_concentration > 0.3:
            conflicting.append({
                'signal': 'stable_cashflow_vs_risky_customers',
                'detail': 'Cash flow looks stable but significant customer base shows stress signals',
                'resolution': 'leading_indicator_risk'
            })

        # Identify hidden risks
        hidden_risks = []
        if ecosystem.customer_health_score < 0.6:
            hidden_risks.append({
                'risk': 'customer_ecosystem_deterioration',
                'detail': f"Key customers showing stress signals",
                'potential_impact': 'revenue_decline_within_6_months',
                'confidence': ecosystem.customer_health_details
            })

        if industry.industry_growth_trend == 'decelerating' and financial.growth_quality.score > 0.7:
            hidden_risks.append({
                'risk': 'growth_against_industry_tide',
                'detail': 'Borrower growing while industry contracts - verify sustainability',
                'potential_impact': 'unsustainable_growth'
            })

        # Calculate composite scores
        composite = self.calculate_composite_scores(
            entity, financial, ecosystem, industry, behavioral
        )

        return Synthesis(
            composite_scores=composite,
            reinforcing_signals=reinforcing,
            conflicting_signals=conflicting,
            hidden_risks=hidden_risks,
            confidence_level=self.calculate_confidence(reinforcing, conflicting)
        )

    def generate_decision(self, synthesis: Synthesis) -> UnderwritingDecision:
        """
        Generate decision with full explanation
        """
        # Decision logic
        if synthesis.composite_scores['overall'] > 0.75 and len(synthesis.hidden_risks) == 0:
            decision = 'approve'
            pricing_tier = 'standard'
        elif synthesis.composite_scores['overall'] > 0.6:
            if len(synthesis.hidden_risks) > 0:
                decision = 'approve_with_conditions'
                pricing_tier = 'elevated'
                conditions = self.generate_conditions(synthesis.hidden_risks)
            else:
                decision = 'approve'
                pricing_tier = 'standard_plus'
        elif synthesis.composite_scores['overall'] > 0.45:
            decision = 'manual_review'
            pricing_tier = None
        else:
            decision = 'reject'
            pricing_tier = None

        # Generate human-readable explanation
        explanation = self.generate_explanation(synthesis, decision)

        return UnderwritingDecision(
            decision=decision,
            pricing_tier=pricing_tier,
            composite_score=synthesis.composite_scores['overall'],
            explanation=explanation,
            key_factors=self.extract_key_factors(synthesis),
            risks_identified=synthesis.hidden_risks,
            confidence=synthesis.confidence_level,
            full_synthesis=synthesis
        )

The Explanation Layer

This is critical for regulatory compliance and human oversight:

def generate_explanation(self, synthesis: Synthesis, decision: str) -> Explanation:
    """
    Generate explanation suitable for underwriter review and regulatory audit
    """
    explanation = Explanation()

    # Summary
    explanation.summary = self.generate_summary(synthesis, decision)

    # Key positive factors
    explanation.positive_factors = [
        {
            'factor': 'Entity Verification',
            'finding': f"Entity verified with {synthesis.entity.confidence_score:.0%} confidence",
            'data_sources': ['MCA', 'GST Registry', 'Professional Networks']
        },
        # ... more factors
    ]

    # Key concerns
    explanation.concerns = [
        {
            'concern': concern['risk'],
            'detail': concern['detail'],
            'data_source': concern.get('source', 'Multiple sources'),
            'mitigant': self.suggest_mitigant(concern)
        }
        for concern in synthesis.hidden_risks
    ]

    # Comparison to similar approved loans
    explanation.peer_comparison = self.compare_to_peers(synthesis)

    # Recommended conditions (if any)
    explanation.recommended_conditions = self.generate_conditions(synthesis)

    return explanation

This system only works with proper consent infrastructure:

flowchart TB
    subgraph Consent["Consent Management"]
        A[Borrower Consent UI] --> B[Consent Registry]
        B --> C{Consent Type}
        C -->|Banking Data| D[Account Aggregator]
        C -->|GST Data| E[GST Sahay]
        C -->|Credit Bureau| F[Bureau Pull]
        C -->|Professional| G[LinkedIn OAuth]
    end

    subgraph DataAccess["Data Access Layer"]
        D --> H[Encrypted Data Store]
        E --> H
        F --> H
        G --> H
        H --> I[Agent Access API]
    end

    subgraph Governance["Data Governance"]
        I --> J[Access Logging]
        J --> K[Audit Trail]
        I --> L[Purpose Limitation]
        L --> M[Data Minimization]
    end

Key principles:

  • Explicit consent for each data source
  • Purpose limitation - data used only for underwriting decision
  • Data minimization - agents request only what’s needed
  • Full audit trail - every data access logged
  • Consent revocation - borrower can withdraw consent

What This Changes

Traditional Underwriting Agentic Underwriting
Point-in-time credit score Dynamic ecosystem health
Individual-centric Network-aware
Backward-looking Forward-looking signals
Binary decision Risk-priced decisions
Black box Explainable reasoning
Same process for all Investigation depth adapts
Catches fraud reactively Detects fraud patterns proactively

Implementation Considerations

1. Start With High-Value Segments

Don’t try to apply this everywhere. Start with:

  • MSME loans (high default rates, thin credit files)
  • Business loans above a certain threshold
  • Applications that would otherwise be rejected

2. Human-in-the-Loop

Agents recommend. Humans decide. The agent’s job is to surface insights that humans would miss, not to replace human judgment.

3. Continuous Learning

Track which signals were predictive:

class UnderwritingFeedbackLoop:
    """
    Learn from loan performance
    """

    def record_outcome(self, loan_id: str, outcome: LoanOutcome):
        # Get original decision factors
        original_decision = self.decision_store.get(loan_id)

        # Compare predicted risks to actual outcome
        predicted_risks = original_decision.risks_identified
        actual_issues = outcome.issues_encountered

        # Update signal weights
        for risk in predicted_risks:
            if risk['risk'] in actual_issues:
                self.increase_signal_weight(risk['signal_type'])
            else:
                self.decrease_signal_weight(risk['signal_type'])

        # Identify missed signals
        missed_signals = self.identify_missed_signals(
            original_decision.synthesis,
            actual_issues
        )

        # Feed back to agent training
        self.training_feedback.record(
            loan_id=loan_id,
            predicted=predicted_risks,
            actual=actual_issues,
            missed=missed_signals
        )

How This Connects to What We Build

At Rotavision, we’ve built the infrastructure to make this possible:

Guardian provides the reliability monitoring layer - ensuring your agentic underwriting system behaves consistently and catching drift before it affects decisions.

Vishwas provides fairness monitoring - ensuring your ecosystem analysis doesn’t inadvertently discriminate based on geography, community, or other protected characteristics.

Orchestrate provides the agentic infrastructure - reliable agent orchestration with human-in-the-loop controls and full audit trails.

We’ve also integrated with Rotascale’s Context Engine for the semantic data joining that makes ecosystem analysis possible - connecting “ABC Traders” in bank statements to “ABC Trading Co. Pvt. Ltd.” in GST records.

The Opportunity

Indian lending is at an inflection point. OCEN, Account Aggregator, and GST Sahay have created the consent and data infrastructure. The question is who will build the intelligence layer on top.

Credit scores served their purpose. But in a world where you can - with proper consent - see a borrower’s position in their entire economic ecosystem, limiting yourself to a three-digit number is leaving insight on the table.

The lenders who figure this out will have structural advantages in risk selection. The ones who don’t will be adversely selected - getting the borrowers that the smarter lenders reject.

If you’re building lending products and thinking about how agentic AI changes underwriting, let’s talk. This is exactly what we’re working on.