> ## Documentation Index
> Fetch the complete documentation index at: https://docs.biconomy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Building Your Agent

> Complete guide to implementing an autonomous agent

This guide walks through building a production-ready agent from scratch.

## Architecture Overview

```
+------------------------------------------------------------------+
|                         YOUR APPLICATION                         |
+------------------------------------------------------------------+
| Frontend (User Prepares And Enable Permission)                   |             
| - SCA deployment if not already                                  |
| - Smart session validator installation if not already            |
| - Funds the SCA if required                                      |
| - Enable session permissions                                     |
+------------------------------------------------------------------+
| Backend (Agent Executes)                                         |
| - Store agent private key securely                               |
| - Store sessionDetails per user                                  |
| - Executes on behalf of user with enabled permissions            |
+------------------------------------------------------------------+
| BICONOMY MEE NETWORK                                             |
| - Executes transactions, enforces policies onchain               |
+------------------------------------------------------------------+
```

## Step 1: Setup

### Install Dependencies

```bash theme={null}
npm install @biconomy/abstractjs viem
```

### Initialize SDK

```typescript theme={null}
import { 
  createMeeClient, 
  getMEEVersion, 
  MEEVersion, 
  SessionDetail, 
  toMultichainNexusAccount 
} from "@biconomy/abstractjs";
import { Abi, Address, http, parseUnits, toFunctionSelector, encodeFunctionData } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { arbitrum, base, optimism } from "viem/chains";
```

## Step 2: Generate Agent Key

Your agent needs its own keypair. Store this securely in your backend.

```typescript theme={null}
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";

// Generate once, store securely (e.g., AWS Secrets Manager, Vault)
const agentPrivateKey = generatePrivateKey();
const agentSigner = privateKeyToAccount(agentPrivateKey);

console.log("Agent address:", agentSigner.address);
// This address is what users will enable permissions to
```

<Warning>
  **Never expose the agent private key.** Treat it like a production database password.
</Warning>

## Step 3: User Onboarding (Frontend)

When a user wants to activate your agent, they enable permissions.

### Create User's Account & Mee Client

```typescript theme={null}
// User's signer (from their wallet - Privy, MetaMask, etc.)
const userSigner = privateKeyToAccount(generatePrivateKey());

console.log("User address:", userSigner.address);

// Create the user's multichain account
const userAccount = await toMultichainNexusAccount({
    signer: userSigner,
    chainConfigurations: [
        { chain: base, transport: http(), version: getMEEVersion(MEEVersion.V2_1_0) },
        { chain: optimism, transport: http(), version: getMEEVersion(MEEVersion.V2_1_0) },
        { chain: arbitrum, transport: http(), version: getMEEVersion(MEEVersion.V2_1_0) }
    ]
});

// Create MEE client with session actions
const meeClient = await createMeeClient({ account: userAccount });
```

### Prepare And Enable Permissions

While user wants to enable permissions, they do the following operations

* Deploying the Smart Contract Account (SCA) if it doesn't exist yet.
* Installing the Smart Session Validator module if not already present.
* Funding the SCA if additional funds are required.
* Granting (enabling) session permissions for the agent to act on the user's behalf.

All in one supertransaction.

```typescript theme={null}
const MORPHO_VAULT: Address = "0x...";
const USDC: Address = "0x...";

// Define what your agent can do
const [depositAction] = userAccount.buildSessionAction({
    type: "custom",
    data: {
        chainIds: [base.id],
        contractAddress: MORPHO_VAULT,
        functionSignature: toFunctionSelector("deposit(uint256,address)"),
        // By default sudo policy will be applied
    }
});

const [withdrawAction] = userAccount.buildSessionAction({
    type: "custom",
    data: {
        chainIds: [base.id],
        contractAddress: MORPHO_VAULT,
        functionSignature: toFunctionSelector("withdraw(uint256,address,address)"),
        // By default sudo policy will be applied
    }
});

const [transferAction] = userAccount.buildSessionAction({
    type: "transfer",
    data: {
        chainIds: [base.id],
        contractAddress: USDC,
        recipientAddress: "0x...", 
        amountLimitPerAction: parseUnits("5", 6),
        maxAmountLimit: parseUnits("100", 6),
        usageLimit: 100n,
        validAfter: Math.floor(Date.now() / 1000),
        validUntil: Math.floor(Date.now() / 1000) + 60 * 60 * 24
    }
});

const prepareAndEnableSessionQuote = await meeClient.getSessionQuote({
    mode: "PREPARE",
    enableSession: {
        redeemer: agentSigner.address,
        // Allowed actions
        actions: [depositAction, withdrawAction, transferAction],
        // Max gas spend
        maxPaymentAmount: parseUnits("20", 6),  // 20 USDC for gas
    },
    simulation: { simulate: true },
    feeToken: { address: USDC, chainId: base.id },
    trigger: {
        tokenAddress: USDC,
        chainId: base.id,
        amount: parseUnits("10", 6), // $10 USDC funding
    },
});

// Store the sessions details for later use.
let sessionDetails: SessionDetail[] = [];

if (prepareAndEnableSessionQuote) {
    const { hash } = await meeClient.executeSessionQuote(prepareAndEnableSessionQuote);
    await meeClient.waitForSupertransactionReceipt({ hash });

    if (prepareAndEnableSessionQuote.sessionDetails) sessionDetails = prepareAndEnableSessionQuote.sessionDetails;
}

// IMPORTANT: Send sessionDetails to your backend
await sendToBackend(sessionDetails, userAccount.addressOn(base.id));
```

## Step 4: Store Session Data (Backend)

Your backend needs to store session details for each user:

```typescript theme={null}
// Example database schema
interface UserSession {
  userId: string;
  accountAddress: string;  // User's smart account address
  sessionDetails: SessionDetail[];  // Can be JSON stringified while storing
  createdAt: Date;
  expiresAt: Date;
}

// Store session
async function storeSession(userId: string, accountAddress: string, sessionDetails: SessionDetail[]) {
  await db.userSessions.insert({
    userId,
    accountAddress,
    sessionDetails: JSON.stringify(sessionDetails),
    createdAt: new Date(),
    expiresAt: new Date(sessionDetails.sessionValidUntil * 1000)
  });
}
```

## Step 5: Agent Execution (Backend)

Your agent can now act on behalf of users:

```typescript theme={null}
async function executeAgentAction(userId: string, action: AgentAction) {
  // 1. Load user's session
  const session = await db.userSessions.findOne({ userId });
  const sessionDetails: SessionDetail[] = JSON.parse(session.sessionDetails);
  
  // 2. Create agent's MEE client
  const agentAccount = await toMultichainNexusAccount({
    signer: agentSigner,
    chainConfigurations: [
      { 
        chain: base, 
        transport: http(), 
        version: getMEEVersion(MEEVersion.V2_1_0),
        accountAddress: session.accountAddress  // User's account address
      }
    ],
  });
  
  const agentMeeClient = await createMeeClient({ account: agentAccount });

  // 3. Build the instruction
  const depositData = encodeFunctionData({
      abi: MORPHO_ABI,
      functionName: "deposit",
      args: [parseUnits("5", 6), session.accountAddress],
  });
  
  const instructions = await agentAccount.build({
      type: "default",
      data: [{
          calls: [{
              to: MORPHO_VAULT,
              data: depositData
          }],
          chainId: base.id,
      }]
  });
  
  // 4. Get session quote
  const quote = await agentMeeClient.getSessionQuote({
      mode: "USE",
      sessionDetails,
      simulation: { simulate: true },
      feeToken: { address: USDC, chainId: base.id },
      instructions
  });

  // 5. Execute with permission
  const { hash } = await agentMeeClient.executeSessionQuote(quote);
  
  // 6. Wait for confirmation
  const { receipts } = await agentMeeClient.waitForSupertransactionReceipt({ hash });

  
  return receipts;
}
```

## Step 6: Agent Logic

Implement your agent's decision-making:

### Yield Optimization Agent

```typescript theme={null}
async function runYieldOptimizer() {
  // Get all users with active sessions
  const users = await db.userSessions.find({
    expiresAt: { $gt: new Date() }
  });
  
  for (const user of users) {
    // Check current positions
    const positions = await getPositions(user.accountAddress);
    
    // Find best yield opportunity
    const bestOpportunity = await findBestYield();
    
    // Rebalance if significantly better
    if (bestOpportunity.apy > positions.currentApy * 1.1) {
      // Withdraw from current
      await executeAgentAction(user.userId, {
        type: "withdraw",
        protocol: positions.currentProtocol,
        amount: positions.amount
      });
      
      // Deposit to better opportunity
      await executeAgentAction(user.userId, {
        type: "deposit",
        protocol: bestOpportunity.protocol,
        amount: positions.amount
      });
    }
  }
}

// Run every hour
setInterval(runYieldOptimizer, 60 * 60 * 1000);
```

### Trading Agent

```typescript theme={null}
async function runTradingAgent() {
  const users = await getActiveUsers();
  
  for (const user of users) {
    const signal = await analyzeMarket(user.preferences);
    
    if (signal.shouldTrade) {
      await executeAgentAction(user.userId, {
        type: "swap",
        tokenIn: signal.fromToken,
        tokenOut: signal.toToken,
        amount: signal.amount
      });
    }
  }
}
```

## Sponsored Agent Execution

If you want to pay gas for your users:

```typescript theme={null}
await agentMeeClient.getSessionQuote({
  mode: "USE",
  sessionDetails,
  simulation: { simulate: true },
  sponsorship: true,  // You pay gas
  instructions
});
```

<Note>
  When using `sponsorship: true`, don't set `feeToken` when enabling permissions.
</Note>

## Monitoring & Observability

```typescript theme={null}
// Log all agent actions
async function executeWithLogging(userId: string, action: AgentAction) {
  const startTime = Date.now();
  
  try {
    const receipts = await executeAgentAction(userId, action);
    
    await logAgentAction({
      userId,
      action,
      status: "success",
      transactionHashes: receipts.map((receipt) => receipt.transactionHash),
      duration: Date.now() - startTime
    });
    
    return result;
  } catch (error) {
    await logAgentAction({
      userId,
      action,
      status: "failed",
      error: error.message,
      duration: Date.now() - startTime
    });
    
    throw error;
  }
}
```

## Security Checklist

<Check>Agent private key stored in secure secret management</Check>
<Check>Session details stored encrypted in database</Check>
<Check>Rate limiting on agent actions</Check>
<Check>Monitoring for unusual activity</Check>
<Check>Automatic session cleanup on expiry</Check>
<Check>User notification system for important events</Check>
