Skip to main content
Copy-paste configurations for the most common autonomous agent use cases.

🤖 AI Trading Agent

An AI that executes trades based on market signals, sentiment, or predictions.

Permissions Needed

  • Swap tokens on DEXes
  • Per-trade and daily spending limits
  • Time-limited access

Configuration

import { 
  getUniversalActionPolicy, 
  ParamCondition 
} from "@biconomy/abstractjs";

const UNISWAP_ROUTER = "0x2626664c2603336E57B271c5C0b26F421741e481";  // Base
const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";

const tradingAgentSession = await sessionClient.grantPermissionTypedDataSign({
  redeemer: agentSigner.address,
  feeToken: { address: USDC, chainId: base.id },
  
  // 7-day access window
  sessionValidAfter: Math.floor(Date.now() / 1000),
  sessionValidUntil: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60,
  
  // Max gas spend
  maxPaymentAmount: parseUnits("50", 6),
  
  actions: [{
    chainId: base.id,
    actionTarget: UNISWAP_ROUTER,
    actionTargetSelector: toFunctionSelector("exactInputSingle((address,address,uint24,address,uint256,uint256,uint160))"),
    actionPolicies: [
      getUniversalActionPolicy({
        valueLimitPerUse: 0n,
        paramRules: {
          length: 2n,
          rules: [
            // Recipient must be user's account (prevent draining)
            {
              condition: ParamCondition.EQUAL,
              offsetIndex: 96,  // recipient field offset
              ref: pad(userAccountAddress),
              isLimited: false,
              usage: { limit: 0n, used: 0n }
            },
            // Max 500 USDC per trade, 5000 daily
            {
              condition: ParamCondition.LESS_THAN_OR_EQUAL,
              offsetIndex: 128,  // amountIn offset
              ref: pad(toHex(parseUnits("500", 6))),
              isLimited: true,
              usage: { limit: parseUnits("5000", 6), used: 0n }
            }
          ]
        }
      })
    ]
  }]
});

Agent Logic Example

async function executeTrade(signal: TradeSignal) {
  if (signal.confidence < 0.7) return;  // Only high-confidence trades
  
  const instruction = await agentAccount.buildComposable({
    type: "default",
    data: {
      chainId: base.id,
      to: UNISWAP_ROUTER,
      abi: UniswapAbi,
      functionName: "exactInputSingle",
      args: [{
        tokenIn: signal.fromToken,
        tokenOut: signal.toToken,
        fee: 3000,
        recipient: userAccountAddress,
        amountIn: signal.amount,
        amountOutMinimum: signal.minOutput,
        sqrtPriceLimitX96: 0n
      }]
    }
  });
  
  return await agentClient.usePermission({
    sessionDetails,
    mode: "USE",
    instructions: [instruction]
  });
}

📈 Yield Optimization Agent

Automatically moves funds to the highest-yielding opportunities.

Permissions Needed

  • Deposit/withdraw from multiple protocols
  • Cross-chain movement (optional)
  • Trusted protocol access

Configuration

import { getSudoPolicy } from "@biconomy/abstractjs";

const PROTOCOLS = {
  base: {
    morpho: "0xA2Cac0023a4797b4729Db94783405189a4203AFc",
    aave: "0x...",
  },
  optimism: {
    aave: "0x...",
    exactly: "0x...",
  }
};

const yieldAgentSession = await sessionClient.grantPermissionTypedDataSign({
  redeemer: agentSigner.address,
  feeToken: { address: USDC, chainId: base.id },
  
  // 30-day access
  sessionValidUntil: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60,
  
  // Generous gas for cross-chain
  maxPaymentAmount: parseUnits("100", 6),
  
  actions: [
    // Morpho on Base
    {
      chainId: base.id,
      actionTarget: PROTOCOLS.base.morpho,
      actionTargetSelector: toFunctionSelector("deposit(uint256,address)"),
      actionPolicies: [getSudoPolicy()]
    },
    {
      chainId: base.id,
      actionTarget: PROTOCOLS.base.morpho,
      actionTargetSelector: toFunctionSelector("withdraw(uint256,address,address)"),
      actionPolicies: [getSudoPolicy()]
    },
    // Aave on Optimism
    {
      chainId: optimism.id,
      actionTarget: PROTOCOLS.optimism.aave,
      actionTargetSelector: toFunctionSelector("supply(address,uint256,address,uint16)"),
      actionPolicies: [getSudoPolicy()]
    },
    {
      chainId: optimism.id,
      actionTarget: PROTOCOLS.optimism.aave,
      actionTargetSelector: toFunctionSelector("withdraw(address,uint256,address)"),
      actionPolicies: [getSudoPolicy()]
    }
  ]
});

Agent Logic Example

async function rebalanceForYield() {
  const yields = await fetchYields([
    { protocol: "morpho", chain: "base" },
    { protocol: "aave", chain: "optimism" }
  ]);
  
  const currentPosition = await getCurrentPosition(userAccountAddress);
  const bestYield = yields.sort((a, b) => b.apy - a.apy)[0];
  
  // Only rebalance if 10%+ improvement
  if (bestYield.apy > currentPosition.apy * 1.1) {
    // Withdraw from current
    await executeWithdraw(currentPosition);
    
    // Bridge if needed
    if (currentPosition.chain !== bestYield.chain) {
      await executeBridge(currentPosition.chain, bestYield.chain);
    }
    
    // Deposit to best
    await executeDeposit(bestYield);
  }
}

💳 Subscription Payment Agent

Automates recurring payments to a fixed recipient.

Permissions Needed

  • Transfer to specific address only
  • Fixed amount per payment
  • Monthly frequency

Configuration

const MERCHANT = "0x...";  // Subscription service address

const subscriptionSession = await sessionClient.grantPermissionTypedDataSign({
  redeemer: agentSigner.address,
  feeToken: { address: USDC, chainId: base.id },
  
  // 1 year subscription
  sessionValidUntil: Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60,
  
  maxPaymentAmount: parseUnits("10", 6),
  
  actions: [{
    chainId: base.id,
    actionTarget: USDC,
    actionTargetSelector: toFunctionSelector("transfer(address,uint256)"),
    usageLimit: 12n,  // 12 payments max
    actionPolicies: [
      getUniversalActionPolicy({
        valueLimitPerUse: 0n,
        paramRules: {
          length: 2n,
          rules: [
            // Only to merchant address
            {
              condition: ParamCondition.EQUAL,
              offsetIndex: 0,
              ref: pad(MERCHANT),
              isLimited: false,
              usage: { limit: 0n, used: 0n }
            },
            // Exactly 9.99 USDC
            {
              condition: ParamCondition.EQUAL,
              offsetIndex: 32,
              ref: pad(toHex(parseUnits("9.99", 6))),
              isLimited: false,
              usage: { limit: 0n, used: 0n }
            }
          ]
        }
      })
    ]
  }]
});

Agent Logic Example

// Run on 1st of each month
async function processSubscriptions() {
  const activeSubscriptions = await db.subscriptions.find({ active: true });
  
  for (const sub of activeSubscriptions) {
    await agentClient.usePermission({
      sessionDetails: sub.sessionDetails,
      mode: "USE",
      instructions: [{
        chainId: base.id,
        calls: [{
          to: USDC,
          data: encodeFunctionData({
            abi: erc20Abi,
            functionName: "transfer",
            args: [MERCHANT, parseUnits("9.99", 6)]
          })
        }]
      }]
    });
  }
}

🔄 Portfolio Rebalancing Agent

Maintains target allocations by trading when drift exceeds threshold.

Configuration

const rebalanceSession = await sessionClient.grantPermissionTypedDataSign({
  redeemer: agentSigner.address,
  feeToken: { address: USDC, chainId: base.id },
  
  // Quarterly rebalancing
  sessionValidUntil: Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60,
  
  // Limit to 4 rebalances
  usageLimit: 4n,
  
  maxPaymentAmount: parseUnits("30", 6),
  
  actions: [
    // Allow swaps between portfolio assets
    {
      chainId: base.id,
      actionTarget: UNISWAP_ROUTER,
      actionTargetSelector: toFunctionSelector("exactInputSingle(...)"),
      actionPolicies: [
        getUniversalActionPolicy({
          // Max 10% of portfolio per rebalance
          paramRules: { /* ... */ }
        })
      ]
    }
  ]
});

🎮 Gaming Agent

Automates in-game actions like claiming rewards, crafting, or battles.

Configuration

const GAME_CONTRACT = "0x...";

const gamingSession = await sessionClient.grantPermissionTypedDataSign({
  redeemer: agentSigner.address,
  feeToken: { address: USDC, chainId: base.id },
  
  sessionValidUntil: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60,
  
  // 1000 actions per week
  usageLimit: 1000n,
  
  maxPaymentAmount: parseUnits("5", 6),
  
  actions: [
    {
      chainId: base.id,
      actionTarget: GAME_CONTRACT,
      actionTargetSelector: toFunctionSelector("claimRewards()"),
      actionPolicies: [getSudoPolicy()]
    },
    {
      chainId: base.id,
      actionTarget: GAME_CONTRACT,
      actionTargetSelector: toFunctionSelector("performAction(uint256)"),
      actionPolicies: [getSudoPolicy()]
    }
  ]
});

Quick Reference

Agent TypePrimary PolicyKey Limits
TradingUniversal ActionPer-trade + daily caps
YieldSudoTime + gas limits
SubscriptionUniversal ActionRecipient + amount + usage
RebalancingUniversal ActionPortfolio % + usage
GamingSudoUsage limit