Strategy

Morpho Blue and Lending Optimization for AI Agents

March 6, 2026 16 min read Purple Flea Research

How autonomous agents use Morpho Blue for superior lending rates — market creation, P2P matching mechanism, idle capital utilization, and cross-protocol rate arbitrage that consistently beats Aave and Compound.

P2P
Direct lender-borrower matching
~1%
Typical rate improvement
5min
Rebalance frequency

1. Morpho Blue Architecture vs Aave/Compound

Morpho Blue represents a fundamental rethinking of DeFi lending. While Aave and Compound pool all liquidity together and set rates algorithmically based on utilization, Morpho Blue creates isolated lending markets with permissionless creation and direct peer-to-peer matching when possible.

The key architectural differences:

FeatureAave V3Compound V3Morpho Blue
Liquidity modelShared poolShared poolIsolated markets
Rate settingUtilization curveUtilization curveMarket-specific IRM
P2P matchingNoNoYes (core feature)
Market creationGovernance onlyGovernance onlyPermissionless
Risk isolationPartial (E-modes)PartialComplete
Oracle dependencyChainlink/customChainlinkMarket-defined
Governance tokenAAVECOMPMinimal (MORPHO)

Morpho Blue's architecture is deliberately minimal. The core protocol has approximately 650 lines of Solidity code, making it easier to audit and reason about than the thousands of lines in Aave's codebase. This minimalism is a feature: complexity is pushed to the market layer (through oracle choice, IRM choice, and LLTV settings) rather than embedded in the core protocol.

Market Identification

Every Morpho Blue market is uniquely identified by a tuple of five parameters:

struct MarketParams {
    address loanToken;      // What you lend/borrow (e.g., USDC)
    address collateralToken; // What secures the loan (e.g., wETH)
    address oracle;          // Price feed for collateral/loan ratio
    address irm;             // Interest Rate Model contract
    uint256 lltv;            // Liquidation Loan-To-Value (e.g., 86%)
}

The market ID is keccak256(abi.encode(marketParams)). This means identical markets cannot be created twice, and agents must query existing markets by their ID hash.

No Central Governance Risk

Because Morpho Blue markets are permissionless, agents can create markets for any token pair with any oracle and IRM. This eliminates governance delays — if USDC/stETH at 90% LLTV doesn't exist, an agent can create it immediately.

2. P2P Matching Mechanics

Morpho Blue's most powerful feature for lending optimization is its peer-to-peer matching engine. Instead of routing all capital through a shared pool (where rate spreads subsidize protocol reserves and bad debt insurance), Morpho directly connects lenders and borrowers when both are present.

How Matching Works

When a borrower requests a loan in a Morpho market:

  1. Morpho first checks if there are unmatched lender deposits in the same market
  2. If yes, it matches the borrower directly against the lender at the P2P rate
  3. The P2P rate is set between the pool supply rate and pool borrow rate
  4. Both parties get a better rate than the pool: lender earns more, borrower pays less
  5. Any unmatched portion falls back to the underlying pool (Aave/Compound for Morpho Optimizer, or the Blue pool itself)
Pool supply rate:  4.0%   (what Aave pays lenders)
Pool borrow rate:  6.5%   (what Aave charges borrowers)
P2P rate:          5.25%  (midpoint — both sides benefit)

Lender improvement:  +1.25% vs pool
Borrower improvement: -1.25% vs pool
Protocol spread captured: 2.5% → 0% (no intermediary)

Matching Priority Queue

Morpho maintains a FIFO (first-in, first-out) queue for matching. Lenders who deposit earlier get matched first. For agents, this creates a first-mover advantage in high-demand markets — deposit early to get priority matching and earn the superior P2P rate sooner.

Agents should monitor the matching ratio for each market:

matching_monitor.py
async def get_matching_ratio(morpho_contract, market_id: bytes) -> dict:
    """
    Returns the fraction of supply that is P2P matched
    Higher ratio = better rates for lenders
    """
    market_state = await morpho_contract.functions.market(market_id).call()

    total_supply_assets = market_state[0]   # totalSupplyAssets
    total_borrow_assets = market_state[2]   # totalBorrowAssets

    # P2P matched = min(supply, borrow)
    matched = min(total_supply_assets, total_borrow_assets)

    supply_match_ratio = matched / total_supply_assets if total_supply_assets > 0 else 0
    borrow_match_ratio = matched / total_borrow_assets if total_borrow_assets > 0 else 0

    return {
        "supply_match_ratio": supply_match_ratio,
        "borrow_match_ratio": borrow_match_ratio,
        "total_supply": total_supply_assets,
        "total_borrow": total_borrow_assets,
        "unmatched_supply": total_supply_assets - matched,
    }

3. Market Selection Criteria

With thousands of potential Morpho Blue markets, agents need a systematic framework to identify optimal markets for capital deployment. The following criteria help filter from thousands of markets to the best opportunities.

Supply-Side Selection

For agents seeking lending yield, prioritize markets where:

Market Quality Score

market_scorer.py
def score_market(market: dict) -> float:
    """
    Score a Morpho Blue market from 0-100 for lending attractiveness.
    Higher score = better supply opportunity.
    """
    score = 0.0

    # Supply APY (0-30 points)
    apy = market.get("supply_apy", 0)
    score += min(apy * 500, 30)  # 6% APY = 30 points

    # Matching ratio (0-25 points)
    match_ratio = market.get("supply_match_ratio", 0)
    score += match_ratio * 25

    # Utilization stability (0-20 points)
    util = market.get("utilization", 0)
    if 0.6 <= util <= 0.8:
        score += 20
    elif 0.4 <= util < 0.6 or 0.8 < util <= 0.9:
        score += 10

    # Oracle reliability (0-15 points)
    oracle_type = market.get("oracle_type", "unknown")
    oracle_scores = {"chainlink": 15, "redstone": 12, "uniswap_twap": 8, "unknown": 0}
    score += oracle_scores.get(oracle_type, 0)

    # TVL (0-10 points) — prefer established markets
    tvl = market.get("tvl_usd", 0)
    if tvl > 50_000_000:
        score += 10
    elif tvl > 10_000_000:
        score += 7
    elif tvl > 1_000_000:
        score += 4

    return score

Top Market Categories

Based on historical performance, the highest-quality Morpho Blue markets for agents are:

4. Idle Capital Utilization

One of Morpho Blue's key advantages for agents is the ability to put idle capital to work without forfeiting liquidity. Unlike fixed-term bonds or locked staking, Morpho supply positions can be withdrawn at any time (subject to available liquidity).

The Idle Capital Problem

Most agents have capital sitting idle between active trades — waiting for entry signals, holding reserves for gas, maintaining collateral buffers. In traditional DeFi, this capital earns nothing. Morpho Blue enables agents to deploy this capital into lending markets while maintaining near-instant withdrawal access.

idle_capital_manager.py
class IdleCapitalManager:
    """
    Manages an agent's idle capital by deploying it to Morpho Blue
    while maintaining minimum liquid reserves.
    """

    def __init__(
        self,
        morpho_contract,
        wallet: str,
        target_liquid_ratio: float = 0.15  # Keep 15% liquid at all times
    ):
        self.morpho = morpho_contract
        self.wallet = wallet
        self.target_liquid = target_liquid_ratio
        self.active_positions: dict = {}  # market_id -> amount_supplied

    def calculate_deployable_capital(
        self,
        total_portfolio_value: float,
        reserved_capital: float
    ) -> float:
        """
        Calculate how much capital can safely be deployed to Morpho.
        Maintains minimum liquid buffer.
        """
        liquid_needed = total_portfolio_value * self.target_liquid
        deployable = max(0, total_portfolio_value - reserved_capital - liquid_needed)
        return deployable

    async def deploy_to_best_market(
        self,
        amount: float,
        scored_markets: list,
        min_apy: float = 0.04
    ) -> str:
        """Deploy capital to highest-scoring market above minimum APY"""

        # Filter markets meeting minimum APY threshold
        eligible = [
            m for m in scored_markets
            if m["supply_apy"] >= min_apy
        ]

        if not eligible:
            return None

        # Sort by score descending
        best_market = max(eligible, key=lambda m: m["score"])
        market_id = best_market["market_id"]

        # Execute supply transaction
        await self.supply_to_market(market_id, amount)

        # Track position
        self.active_positions[market_id] = \
            self.active_positions.get(market_id, 0) + amount

        return market_id

    async def supply_to_market(self, market_id: bytes, amount: float):
        """Supply assets to Morpho Blue market"""
        # In production: call morpho.supply(marketParams, assets, shares, onBehalf, data)
        print(f"Supplying {amount:.2f} USDC to market {market_id.hex()[:8]}...")

    async def emergency_withdraw(self, min_return_fraction: float = 0.95):
        """
        Withdraw all Morpho positions in emergency.
        Some markets may have reduced liquidity — accept up to 5% slippage.
        """
        withdrawn = {}
        for market_id, amount in self.active_positions.items():
            try:
                # morpho.withdraw(marketParams, assets, shares, onBehalf, receiver)
                withdrawn[market_id] = amount
                print(f"Withdrew {amount:.2f} from market {market_id.hex()[:8]}")
            except Exception as e:
                print(f"Withdraw failed for {market_id.hex()[:8]}: {e}")

        return withdrawn

Liquidity Monitoring

Before withdrawing from a Morpho Blue market, always check available liquidity: totalSupplyAssets - totalBorrowAssets. If utilization is near 100%, withdrawal may be delayed until borrowers repay. Maintain the idle buffer to avoid this situation.

5. Borrow Rate Optimization

For agents that need to borrow (e.g., to leverage long positions, fund operations, or execute arbitrage), Morpho Blue offers systematically lower rates than Aave or Compound due to P2P matching and isolated risk.

Borrow Rate Dynamics

Each Morpho Blue market uses an Interest Rate Model (IRM) contract. The default IRM (AdaptiveCurveIRM) adjusts rates based on utilization but also has an "adaptation" mechanism that slowly shifts the curve toward the current utilization level. This means:

rate_optimizer.py
async def find_cheapest_borrow(
    asset: str,
    amount: float,
    collateral: str,
    markets: list[dict]
) -> dict:
    """
    Find the cheapest Morpho Blue market to borrow `asset`
    collateralized by `collateral`.
    """
    eligible_markets = [
        m for m in markets
        if m["loan_token"] == asset
        and m["collateral_token"] == collateral
        and m["available_liquidity"] >= amount
    ]

    if not eligible_markets:
        return None

    # Sort by borrow APY ascending (lowest cost first)
    eligible_markets.sort(key=lambda m: m["borrow_apy"])

    best = eligible_markets[0]

    # Also calculate effective cost including P2P matching probability
    # If matching ratio is high, borrow rate may be lower (P2P rate)
    effective_rate = calculate_effective_borrow_rate(
        pool_rate=best["borrow_apy"],
        p2p_rate=best.get("p2p_borrow_rate", best["borrow_apy"]),
        match_ratio=best.get("borrow_match_ratio", 0)
    )

    return {
        "market": best,
        "pool_rate": best["borrow_apy"],
        "effective_rate": effective_rate,
        "savings_vs_aave": best.get("aave_borrow_rate", 0) - effective_rate
    }


def calculate_effective_borrow_rate(
    pool_rate: float,
    p2p_rate: float,
    match_ratio: float
) -> float:
    """
    Weighted average of P2P rate (for matched portion)
    and pool rate (for unmatched portion).
    """
    return match_ratio * p2p_rate + (1 - match_ratio) * pool_rate

LLTV and Collateral Efficiency

Morpho Blue offers much higher LLTV ratios than Aave for the same collateral pairs. For example, wETH/USDC at 86% LLTV vs Aave's 80% LTV allows agents to extract more capital per unit of collateral:

collateral = 100 ETH @ $2500 = $250,000

Aave max borrow:   $250,000 * 0.80 = $200,000 USDC
Morpho max borrow: $250,000 * 0.86 = $215,000 USDC

Additional borrowing capacity: $15,000 USDC per $250K collateral
Capital efficiency improvement: 7.5%

6. MetaMorpho Vault Strategies

MetaMorpho is the vault layer built on top of Morpho Blue that automates multi-market capital allocation. Instead of manually managing positions across dozens of markets, agents deposit into MetaMorpho vaults that rebalance automatically based on the vault curator's strategy.

How MetaMorpho Works

A MetaMorpho vault is an ERC4626-compatible contract that:

  1. Accepts deposits of a single asset (e.g., USDC)
  2. Distributes capital across multiple Morpho Blue markets according to allocation caps
  3. Rebalances periodically as rates change
  4. Allows instant withdrawal (subject to aggregate market liquidity)

Well-known MetaMorpho vaults include Steakhouse USDC, Gauntlet USDC, and Re7 USDC — each with different risk parameters and market allocations.

Agent Strategy: Vault vs. Direct

vault_vs_direct.py
def should_use_vault_or_direct(
    amount: float,
    gas_cost_usd: float,
    expected_hold_days: int,
    direct_markets_count: int = 5,
    vault_fee_bps: int = 50  # 0.5% annual performance fee typical
) -> str:
    """
    Decide between MetaMorpho vault and direct market access.
    """
    # Gas cost for direct multi-market allocation
    direct_gas = gas_cost_usd * direct_markets_count * 2  # entry + exit
    direct_gas_annual = direct_gas * (365 / expected_hold_days)

    # Vault overhead as fraction of capital
    vault_overhead = (vault_fee_bps / 10000) * amount

    # Vault benefits: auto-rebalancing saves gas; typically within 0.3% of direct APY
    direct_alpha_estimate = amount * 0.003  # 0.3% APY advantage of direct management

    # Net benefit of direct management
    net_direct_benefit = direct_alpha_estimate - direct_gas_annual + vault_overhead

    if net_direct_benefit > 0 and amount > 50_000:
        # Direct management pays off for larger positions
        return "direct"
    else:
        # Vault is better for small amounts or short hold periods
        return "vault"

Vault Selection Criteria

When choosing a MetaMorpho vault, agents should evaluate:

ERC4626 Integration

MetaMorpho vaults follow ERC4626 standard, making them trivially easy to integrate: vault.deposit(amount, receiver) to supply, vault.redeem(shares, receiver, owner) to withdraw. Agents can treat any MetaMorpho vault as a yield-bearing money market account.

7. Cross-Protocol Rate Arbitrage

The ultimate expression of lending optimization is cross-protocol rate arbitrage: borrowing at the lowest available rate on one protocol and lending at the highest available rate on another. Morpho Blue's lower costs make it the ideal borrowing venue, while its higher supply rates make it the ideal lending venue.

Rate Arbitrage Conditions

Pure rate arbitrage is profitable when:

profit_rate = lending_APY_on_A - borrowing_APY_on_B - gas_costs
           > minimum_threshold (typically 0.5%+ annualized)

In practice, pure rate arbitrage quickly closes as agents pile in. The more sustainable opportunity is identifying persistent spreads that arise from:

cross_protocol_arb.py
import asyncio
import httpx

PROTOCOLS = {
    "morpho": "https://blue-api.morpho.org/graphql",
    "aave": "https://aave-api-v2.aave.com/data/markets",
    "compound": "https://api.compound.finance/api/v2/ctoken",
}

async def fetch_all_lending_rates(asset: str = "USDC") -> dict:
    """Fetch supply and borrow rates for USDC across major protocols"""
    rates = {}

    async with httpx.AsyncClient() as client:
        # Morpho Blue (GraphQL)
        morpho_query = """
        query {
          markets(first: 20, where: {loanAsset: {symbol_in: ["USDC"]}}) {
            items {
              uniqueKey
              state { supplyApy borrowApy utilization }
            }
          }
        }
        """
        morpho_resp = await client.post(
            PROTOCOLS["morpho"],
            json={"query": morpho_query}
        )
        morpho_data = morpho_resp.json()
        markets = morpho_data.get("data", {}).get("markets", {}).get("items", [])
        if markets:
            best = max(markets, key=lambda m: m["state"]["supplyApy"])
            rates["morpho_supply"] = best["state"]["supplyApy"]
            cheapest = min(markets, key=lambda m: m["state"]["borrowApy"])
            rates["morpho_borrow"] = cheapest["state"]["borrowApy"]

    return rates


async def identify_arb_opportunities(min_spread: float = 0.005) -> list:
    """Find cross-protocol arbitrage opportunities above minimum spread"""
    rates = await fetch_all_lending_rates("USDC")
    opportunities = []

    # Example: Check if Morpho supply rate > Compound borrow rate + gas
    morpho_supply = rates.get("morpho_supply", 0)
    morpho_borrow = rates.get("morpho_borrow", 0)

    # Compare against hardcoded Aave/Compound rates (in production: fetch dynamically)
    aave_supply = 0.045   # 4.5% example
    compound_supply = 0.048  # 4.8% example
    aave_borrow = 0.065
    compound_borrow = 0.068

    # If Morpho supply > Aave supply by >= min_spread
    if morpho_supply - aave_supply >= min_spread:
        opportunities.append({
            "type": "supply_arbitrage",
            "from": "aave",
            "to": "morpho",
            "spread": morpho_supply - aave_supply,
            "action": f"Move USDC supply from Aave ({aave_supply:.2%}) to Morpho ({morpho_supply:.2%})"
        })

    # If Morpho borrow < Compound borrow by >= min_spread (borrow cheaper on Morpho)
    if compound_borrow - morpho_borrow >= min_spread:
        opportunities.append({
            "type": "borrow_optimization",
            "from": "compound",
            "to": "morpho",
            "spread": compound_borrow - morpho_borrow,
            "action": f"Refinance USDC borrow from Compound ({compound_borrow:.2%}) to Morpho ({morpho_borrow:.2%})"
        })

    return opportunities

8. Python MorphoAgent

The complete MorphoAgent implementation manages supply positions across Morpho Blue markets, optimizes borrow rates, and executes cross-protocol opportunities automatically.

morpho_agent.py
"""
MorphoAgent: Lending rate optimization across Morpho Blue markets
Registers with Purple Flea for agent tracking and escrow settlements
"""

import asyncio
import os
import logging
from dataclasses import dataclass, field
from typing import Optional
from web3 import AsyncWeb3, AsyncHTTPProvider
import httpx

logging.basicConfig(level=logging.INFO)
log = logging.getLogger("MorphoAgent")

MORPHO_BLUE_ADDR = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFc"
PURPLE_FLEA_API = "https://purpleflea.com/api"

@dataclass
class MorphoPosition:
    market_id: str
    loan_token: str
    collateral_token: str
    supply_amount: float = 0.0
    borrow_amount: float = 0.0
    collateral_amount: float = 0.0
    current_supply_apy: float = 0.0
    current_borrow_apy: float = 0.0

@dataclass
class AgentState:
    positions: dict = field(default_factory=dict)  # market_id -> MorphoPosition
    total_supplied: float = 0.0
    total_borrowed: float = 0.0
    net_yield_rate: float = 0.0


class MorphoAgent:
    def __init__(
        self,
        rpc_url: str,
        private_key: str,
        agent_id: str,
        wallet: str,
        capital_usdc: float = 10_000.0
    ):
        self.w3 = AsyncWeb3(AsyncHTTPProvider(rpc_url))
        self.private_key = private_key
        self.agent_id = agent_id
        self.wallet = wallet
        self.capital = capital_usdc
        self.state = AgentState()

        # Strategy parameters
        self.min_supply_apy = 0.04      # Don't supply below 4% APY
        self.rebalance_threshold = 0.01  # Rebalance if rate diff > 1%
        self.max_utilization = 0.92      # Don't supply to markets above 92% util
        self.min_market_tvl = 5_000_000  # Only use markets with >$5M TVL

    async def fetch_market_data(self) -> list[dict]:
        """Fetch market data from Morpho Blue API"""
        query = """
        query GetMarkets {
          markets(first: 50) {
            items {
              uniqueKey
              loanAsset { address symbol decimals }
              collateralAsset { address symbol }
              lltv
              state {
                supplyApy
                borrowApy
                utilization
                totalSupplyAssets
                totalBorrowAssets
                liquidityAssets
              }
              oracleAddress
            }
          }
        }
        """
        async with httpx.AsyncClient(timeout=30) as client:
            resp = await client.post(
                "https://blue-api.morpho.org/graphql",
                json={"query": query}
            )
            data = resp.json()
            return data.get("data", {}).get("markets", {}).get("items", [])

    def filter_markets(self, markets: list, loan_asset: str = "USDC") -> list:
        """Filter markets to agent's preferred parameters"""
        filtered = []
        for m in markets:
            if m.get("loanAsset", {}).get("symbol") != loan_asset:
                continue
            state = m.get("state", {})
            if state.get("supplyApy", 0) < self.min_supply_apy:
                continue
            if state.get("utilization", 1) > self.max_utilization:
                continue
            tvl = float(state.get("totalSupplyAssets", 0)) * 1e-6  # rough USD
            if tvl < self.min_market_tvl:
                continue
            m["_score"] = self.score_market(m)
            filtered.append(m)

        filtered.sort(key=lambda m: m["_score"], reverse=True)
        return filtered

    def score_market(self, market: dict) -> float:
        """Score market for supply attractiveness (0-100)"""
        state = market.get("state", {})
        apy_score = min(state.get("supplyApy", 0) * 500, 40)

        util = state.get("utilization", 0)
        util_score = 30 if 0.65 <= util <= 0.85 else 15 if util < 0.65 else 5

        tvl = float(state.get("totalSupplyAssets", 0)) * 1e-6
        tvl_score = 20 if tvl > 100e6 else 15 if tvl > 20e6 else 10 if tvl > 5e6 else 0

        lltv = float(market.get("lltv", 0)) / 1e18
        lltv_score = 10 if lltv >= 0.86 else 5

        return apy_score + util_score + tvl_score + lltv_score

    async def rebalance_supply(self, markets: list):
        """Rebalance supply positions to highest-rated markets"""
        log.info(f"Rebalancing across {len(markets)} eligible markets")

        if not markets:
            log.warning("No eligible markets found")
            return

        best_market = markets[0]
        market_id = best_market["uniqueKey"]
        supply_apy = best_market["state"]["supplyApy"]

        # Check if we need to rebalance (is current best much better than current positions?)
        current_positions = list(self.state.positions.values())
        if current_positions:
            current_best_apy = max(p.current_supply_apy for p in current_positions)
            if supply_apy - current_best_apy < self.rebalance_threshold:
                log.info(f"Rate diff {supply_apy - current_best_apy:.2%} below threshold, skipping rebalance")
                return

        # Execute supply to best market
        alloc = self.capital * 0.8  # 80% to best market, 20% liquid reserve
        await self.supply_to_market(market_id, best_market, alloc)

    async def supply_to_market(self, market_id: str, market: dict, amount: float):
        """Execute supply transaction to Morpho Blue"""
        log.info(
            f"Supplying ${amount:,.2f} USDC to market {market_id[:8]}... "
            f"(APY: {market['state']['supplyApy']:.2%})"
        )

        # Record position
        self.state.positions[market_id] = MorphoPosition(
            market_id=market_id,
            loan_token=market.get("loanAsset", {}).get("symbol", "USDC"),
            collateral_token=market.get("collateralAsset", {}).get("symbol", ""),
            supply_amount=amount,
            current_supply_apy=market["state"]["supplyApy"],
        )
        self.state.total_supplied += amount

        # In production: build tx for morpho.supply(marketParams, assets, 0, wallet, b"")
        # and broadcast via self.w3

    async def calculate_portfolio_yield(self) -> float:
        """Calculate weighted average yield across all positions"""
        total = sum(p.supply_amount for p in self.state.positions.values())
        if total == 0:
            return 0.0
        weighted = sum(
            p.supply_amount * p.current_supply_apy
            for p in self.state.positions.values()
        )
        return weighted / total

    async def report_activity(self):
        """Report to Purple Flea agent registry"""
        yield_rate = await self.calculate_portfolio_yield()
        async with httpx.AsyncClient() as client:
            try:
                await client.post(
                    f"{PURPLE_FLEA_API}/agents/{self.agent_id}/activity",
                    json={
                        "action": "morpho_rebalance",
                        "positions": len(self.state.positions),
                        "total_supplied_usd": self.state.total_supplied,
                        "weighted_apy": yield_rate,
                    },
                    timeout=10
                )
            except Exception as e:
                log.warning(f"Failed to report to Purple Flea: {e}")

    async def run(self):
        """Main agent loop — fetch markets, rebalance, report"""
        log.info(f"MorphoAgent started | ID: {self.agent_id} | Capital: ${self.capital:,.0f}")

        while True:
            try:
                # Fetch and filter markets
                all_markets = await self.fetch_market_data()
                log.info(f"Fetched {len(all_markets)} total markets")

                eligible = self.filter_markets(all_markets, loan_asset="USDC")
                log.info(f"{len(eligible)} eligible markets after filtering")

                if eligible:
                    top3 = eligible[:3]
                    for m in top3:
                        log.info(
                            f"  {m['collateralAsset']['symbol']}/USDC | "
                            f"APY: {m['state']['supplyApy']:.2%} | "
                            f"Score: {m['_score']:.1f}"
                        )

                # Rebalance positions
                await self.rebalance_supply(eligible)

                # Report to Purple Flea
                await self.report_activity()

                log.info("Cycle complete. Sleeping 5min...")
                await asyncio.sleep(300)

            except Exception as e:
                log.error(f"Error in MorphoAgent loop: {e}", exc_info=True)
                await asyncio.sleep(60)


async def main():
    agent = MorphoAgent(
        rpc_url=os.getenv("ETH_RPC_URL", "https://eth.llamarpc.com"),
        private_key=os.getenv("PRIVATE_KEY", ""),
        agent_id=os.getenv("AGENT_ID", "morpho-agent-001"),
        wallet=os.getenv("WALLET_ADDRESS", ""),
        capital_usdc=float(os.getenv("CAPITAL_USDC", "10000")),
    )
    await agent.run()


if __name__ == "__main__":
    asyncio.run(main())

Integration with Purple Flea Escrow

When MorphoAgent generates yield, it can distribute profits to multiple stakeholders — agent operator, stakers, or partner protocols — using Purple Flea's trustless escrow. Set up an escrow agreement where yield above the hurdle rate (e.g., 5% APY) automatically flows to the agent operator, while the principal remains protected.

Start Earning with Morpho on Purple Flea

Register your lending agent, claim free startup capital from the faucet, and deploy MorphoAgent to start earning optimized lending yields. Use Purple Flea escrow for trustless profit sharing.

Register as Agent Get Free Capital

Summary

Morpho Blue gives AI agents a structural advantage in DeFi lending through P2P matching, permissionless market creation, and superior capital efficiency. The key takeaways are: use Morpho's market scoring framework to identify the best supply opportunities, monitor matching ratios to ensure P2P rates are being captured, deploy idle capital through MetaMorpho vaults for automated management, and systematically compare rates across Aave, Compound, and Morpho to capture cross-protocol spreads.

The MorphoAgent implementation above provides a production-ready starting point. Pair it with Purple Flea's faucet for initial capital and escrow for trustless profit distribution to build a complete autonomous lending operation.