Register a Bot

Generate a bot key pair, whitelist it on your vault, and configure spending limits.

Register a Bot

Before a bot can make payments through your vault, its public address must be registered (whitelisted) on-chain. This guide covers key generation, registration, and policy configuration.

Key Generation

You have two options for creating a bot key pair.

Option A: Generate in the Dashboard

The dashboard can generate a key pair entirely client-side in your browser. The private key is never sent to Axon servers.

  1. Go to Vaults > [Your Vault] > Bots > Register New Bot
  2. Click Generate New Key Pair
  3. Save the private key using one of two options:

Encrypted keystore (recommended): Enter a passphrase (min 8 characters), click Download Keystore. The dashboard encrypts the key client-side using the standard Ethereum V3 keystore format (scrypt + AES-128-CTR — same as MetaMask and Geth) and downloads a .json file. The keystore file is safe to store in cloud backups, password managers, or version control — it is useless without the passphrase.

Plain text copy: Reveal and copy the raw private key. Store it in a password manager or secrets vault.

  1. The dashboard also shows a ready-to-use .env snippet with both options:
# Option 1: Encrypted keystore (recommended)
AXON_BOT_KEYSTORE_PATH=./axon-bot-0xABCD1234.json
AXON_BOT_PASSPHRASE=<your-passphrase>
 
# Option 2: Plain private key (not recommended)
# AXON_BOT_PRIVATE_KEY=0x...
 
AXON_VAULT_ADDRESS=0x...
AXON_CHAIN_ID=8453
  1. Confirm you have saved the key (or downloaded the keystore) before registering.

The private key is shown exactly once. If you lose both the plain key and the keystore passphrase, you will need to register a new bot address.

Using an Encrypted Keystore

To use a keystore file with the SDK, decrypt it at startup:

import { AxonClient, decryptKeystore } from '@axonfi/sdk';
import fs from 'fs';
 
const keystore = fs.readFileSync(process.env.AXON_BOT_KEYSTORE_PATH!, 'utf8');
const privateKey = await decryptKeystore(keystore, process.env.AXON_BOT_PASSPHRASE!);
 
const client = new AxonClient({
  botPrivateKey: privateKey,
  vaultAddress: process.env.AXON_VAULT_ADDRESS as `0x${string}`,
  chainId: Number(process.env.AXON_CHAIN_ID),
});

For best security, store the keystore file and passphrase in separate systems (e.g. file on disk, passphrase in AWS Secrets Manager or 1Password CLI).

Is encryption required? No. Bot keys already have limited blast radius in Axon — they can only sign expiring intents (5-minute deadline) within your configured spending limits. The bot cannot withdraw funds, change vault config, or call the contract directly. If a key is compromised, the owner can remove the bot instantly.

The encrypted keystore is a recommended safeguard against accidental exposure (clipboard leaks, accidental git commits, Slack pastes) rather than a hard security requirement. Think of it as a second layer of protection on top of Axon's already-bounded bot key model.

Option B: Bring Your Own Key

If you already have a key pair (generated with ethers.Wallet.createRandom(), openssl, or any other method):

  1. Go to Vaults > [Your Vault] > Bots > Register New Bot
  2. Click Register Existing Address
  3. Paste the public address only
  4. Your private key never touches Axon systems

Register on the Vault

Registration adds the bot's address to the vault's on-chain whitelist. This can be done by either the vault owner or the operator (if one is configured).

Via Dashboard

After generating or entering the bot address, click Register. The dashboard submits the on-chain transaction. Once confirmed, the bot appears in your bot list with an "Active" status.

Via SDK

Bot registration is an on-chain transaction that must be signed by the vault owner or operator. Use the Axon dashboard for a guided flow, or call the vault contract directly with viem or wagmi:

import { AxonVaultAbi } from '@axonfi/sdk';
import { createWalletClient, http, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
 
const ownerAccount = privateKeyToAccount(process.env.OWNER_PRIVATE_KEY as `0x${string}`);
 
const walletClient = createWalletClient({
  account: ownerAccount,
  chain: base,
  transport: http(),
});
 
await walletClient.writeContract({
  address: '0xYourVaultAddress',
  abi: AxonVaultAbi,
  functionName: 'addBot',
  args: [
    '0xYourBotPublicAddress',
    {
      maxPerTxAmount: parseUnits('100', 6),    // $100 USDC hard cap
      maxRebalanceAmount: 0n,                   // no rebalance cap
      spendingLimits: [],                       // no time-windowed limits (add later)
      aiTriggerThreshold: parseUnits('50', 6), // AI scan above $50
      requireAiVerification: false,
    },
  ],
});

Configure Spending Limits

Every registered bot has a BotConfig stored on-chain. The relayer reads these values from the contract, not from its own database, so your configuration is publicly verifiable.

Config Fields

FieldTypeDescription
maxPerTxAmountuint256Hard cap per transaction, enforced on-chain. Set to 0 for no limit.
spendingLimitsSpendingLimit[]Array of up to 5 time-windowed limits, each with amount, maxCount, and windowSeconds. Enforced by the relayer.
aiTriggerThresholduint256Payments above this amount trigger the 3-agent AI verification scan.
requireAiVerificationboolIf true, every payment from this bot goes through AI verification regardless of amount.

Set Limits via Dashboard

Navigate to Bots > [Bot Name] > Configuration and adjust the fields. Each change is an on-chain transaction signed by the owner or operator.

If an operator is configured, they can only set limits up to the operator ceilings defined by the owner. They can lower limits freely but cannot raise them above the ceilings.

Set Limits via SDK

Bot configuration (spending limits, AI thresholds, per-tx caps) is managed through the Axon dashboard or via direct on-chain contract calls. The SDK does not provide wrapper methods for these owner/operator transactions.

To configure limits programmatically, call the vault contract directly with viem or wagmi:

import { AxonVaultAbi } from '@axonfi/sdk';
import { parseUnits } from 'viem';
 
// Update bot config on-chain (owner or operator)
await walletClient.writeContract({
  address: '0xYourVaultAddress',
  abi: AxonVaultAbi,
  functionName: 'updateBotConfig',
  args: [
    '0xYourBotPublicAddress',
    {
      maxPerTxAmount: parseUnits('100', 6),       // $100 USDC hard cap
      maxRebalanceAmount: parseUnits('50', 6),    // $50 rebalance cap
      spendingLimits: [                           // up to 5 windows
        { amount: parseUnits('500', 6), maxCount: 0n, windowSeconds: 3600n },   // $500/hour
        { amount: parseUnits('2000', 6), maxCount: 0n, windowSeconds: 86400n }, // $2,000/day
      ],
      aiTriggerThreshold: parseUnits('500', 6),   // AI scan above $500
      requireAiVerification: false,
    },
  ],
});

Verify Bot Is Active

After registration, confirm the bot is active:

import { getBotConfig, createAxonPublicClient, Chain } from '@axonfi/sdk';
 
const publicClient = createAxonPublicClient(Chain.BaseSepolia, 'https://sepolia.base.org');
const config = await getBotConfig(publicClient, '0xYourVaultAddress', '0xYourBotPublicAddress');
 
console.log('Active:', config.isActive); // true
console.log('Max per tx:', config.maxPerTxAmount);
console.log('Spending limits:', config.spendingLimits);

Or check in the dashboard under Bots — the bot should show a green "Active" badge.

Revoking a Bot

To deactivate a bot, the owner or operator can revoke its registration. Use the dashboard or call the vault contract directly:

import { AxonVaultAbi } from '@axonfi/sdk';
 
await walletClient.writeContract({
  address: '0xYourVaultAddress',
  abi: AxonVaultAbi,
  functionName: 'removeBot',
  args: ['0xYourBotPublicAddress'],
});

Revoked bots cannot sign valid payment intents. Any pending intents from a revoked bot will be rejected by the contract.

Next Steps