🤖 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
Copy
Ask AI
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
Copy
Ask AI
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
Copy
Ask AI
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
Copy
Ask AI
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
Copy
Ask AI
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
Copy
Ask AI
// 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
Copy
Ask AI
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
Copy
Ask AI
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 Type | Primary Policy | Key Limits |
|---|---|---|
| Trading | Universal Action | Per-trade + daily caps |
| Yield | Sudo | Time + gas limits |
| Subscription | Universal Action | Recipient + amount + usage |
| Rebalancing | Universal Action | Portfolio % + usage |
| Gaming | Sudo | Usage limit |