abstxn-dev-agent-kit-sdk
v1.0.4
Published
Development SDK
Readme
@abstraxn/agent-kit
Backend SDK for creating and managing Web3 AI agents with auto-provisioned Abstraxn server wallets.
Installation
npm install @abstraxn/agent-kitPrerequisites
- Node.js >= 18
- API Key from the Abstraxn Dashboard
Basic Integration
1. Initialize the SDK
import { AgentKitClient } from '@abstraxn/agent-kit';
const agentKit = new AgentKitClient({
apiKey: process.env.ABSTRAXN_API_KEY!,
wallet: 'server', // default — auto-provision Abstraxn server wallet
});2. Create an Agent (with auto-provisioned wallet)
This is the primary flow. The SDK will:
- Generate a P-256 access key pair
- Create a server wallet via Abstraxn
- Retrieve the wallet's EVM address
- Register the agent in the backend
const { agent, wallet } = await agentKit.createAgent({
name: 'Trading Assistant',
description: 'AI agent that executes trades within spend policy',
userIdentity: '[email protected]',
userName: 'John Doe', // optional
userEmail: '[email protected]', // optional
metadata: { role: 'trader' }, // optional
});
// ─── Agent Details ───
console.log('Agent ID:', agent.id);
console.log('Agent API Key:', agent.apiKey);
console.log('Is Active:', agent.isActive);
// ─── Wallet Details ───
console.log('EVM Address:', wallet.evmAddress);
console.log('Organization ID:', wallet.organizationId);
// ⚠️ IMPORTANT: Store these securely in your backend database.
// The accessKey is the ONLY way to sign transactions for this wallet.
// It CANNOT be retrieved again.
console.log('Access Key:', wallet.accessKey);
await saveToDatabase({
agentId: agent.id,
accessKey: wallet.accessKey!, // secret — encrypt at rest (server wallet only)
evmAddress: wallet.evmAddress,
organizationId: wallet.organizationId,
});2b. Create an Agent (external / bring-your-own wallet)
Use your own EVM or Solana address — no server wallet or accessKey is created:
const agentKit = new AgentKitClient({
apiKey: process.env.ABSTRAXN_API_KEY!,
wallet: 'external',
});
const { agent, wallet } = await agentKit.createAgent({
name: 'Trading Assistant',
description: 'Uses the user MetaMask wallet',
userIdentity: '[email protected]',
evmAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // required (or solanaAddress)
});
console.log(wallet.type); // 'external'
console.log(wallet.evmAddress); // saved on the agent record
// wallet.accessKey is undefined — sign txs with your own wallet stackYou can also override per call without changing client config:
const { agent, wallet } = await agentKit.createAgent({
wallet: 'external',
evmAddress: '0x...',
name: '...',
description: '...',
userIdentity: '...',
});createAgentDirect() is equivalent to external mode (POST /agents with addresses only).
3. List Agents
const { items, total } = await agentKit.listAgents({
offset: 0,
limit: 20,
});
console.log(`Total agents: ${total}`);
items.forEach((agent) => {
console.log(`${agent.name} — ${agent.evmAddress} — active: ${agent.isActive}`);
});4. Get Agent by ID
const agent = await agentKit.getAgent('agent-uuid-here');
console.log(agent.name, agent.evmAddress);5. Update Agent
const updated = await agentKit.updateAgent('agent-uuid-here', {
name: 'Updated Agent Name',
description: 'Updated description',
isActive: false,
});6. Set Spend Policy
// Enable a daily budget of $5
const agent = await agentKit.updateSpendPolicy('agent-uuid-here', {
enabled: true,
budgetUsd: '5.00',
period: 'daily',
hardBlock: true, // false = advisory only
});
// Disable spend policy
await agentKit.updateSpendPolicy('agent-uuid-here', {
enabled: false,
});7. Delete Agent
await agentKit.deleteAgent('agent-uuid-here');8. Register ERC-8004 On-Chain Identity
Server wallet
After creating an agent and funding its server wallet with native gas on the target chain:
const identity = await agentKit.registerAgentIdentity({
agentId: agent.id,
userIdentity: '[email protected]',
accessKey: wallet.accessKey,
organizationId: wallet.organizationId,
evmAddress: wallet.evmAddress,
chainId: 11155111, // Sepolia — backend must have IdentityRegistry configured for this chain
});
console.log(identity.registration.agentIdentity);
// eip155:11155111:0x8004A818BFB912233c491871b3d84c89A494BD9e:42
const stored = await agentKit.getAgentIdentity(agent.id, 11155111);External wallet (bring-your-own signer)
Registry is a 3-step flow: prepare (backend) → sign (your wallet) → confirm (backend).
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sepolia } from 'viem/chains';
// 1. Create agent with your address (no server wallet)
const { agent } = await agentKit.createAgent({
wallet: 'external',
evmAddress: process.env.DEV_EVM_ADDRESS!,
name: 'My Agent',
description: '...',
userIdentity: '[email protected]',
});
// 2. Register — you provide the signer
const identity = await agentKit.registerAgentIdentityExternal({
agentId: agent.id,
evmAddress: process.env.DEV_EVM_ADDRESS!,
chainId: 11155111,
signTransaction: async ({ prepare, fromAddress }) => {
const account = privateKeyToAccount(process.env.DEV_PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: sepolia,
transport: http(prepare.rpcUrl),
});
const hash = await walletClient.sendTransaction({
account: fromAddress,
chain: sepolia,
to: prepare.registerCall.to as `0x${string}`,
data: prepare.registerCall.data,
value: BigInt(prepare.registerCall.value || '0'),
});
return hash;
},
});Manual steps (same APIs, full control):
const prepare = await agentKit.prepareAgentIdentity(agent.id, { chainId: 11155111 });
// sign prepare.registerCall with MetaMask / viem / ethers…
const confirmed = await agentKit.confirmAgentIdentity(agent.id, {
chainId: 11155111,
txHash: '0x…',
});Requirements for external registry:
- Agent
evmAddressmust match the account that signs (and holds gas on thatchainId). - Backend must have IdentityRegistry configured for the
chainId. registerAgentIdentity()(server) needsaccessKey+organizationId; external flow does not.
Registration file (public): GET {AGENT_KIT_PUBLIC_URL}/agents/{agentId}/registration
Signing Transactions with the Wallet
After creating an agent, use the stored accessKey to sign transactions via the ServerSignerClient:
const signer = agentKit.getServerSigner();
// Authenticate using the stored access key
const session = await signer.authenticate({
userIdentity: '[email protected]',
accessKey: storedAccessKey, // retrieved from your database
});
// Create a viem public client for EVM operations
const publicClient = signer.createPublicClient({
rpcUrl: 'https://rpc-amoy.polygon.technology',
chainId: 80002,
organizationId: storedOrganizationId,
fromAddress: storedEvmAddress as `0x${string}`,
});
// Send a transaction
const prepared = await publicClient.prepareTransaction({
to: '0x1111111111111111111111111111111111111111' as `0x${string}`,
value: 1_000_000_000_000_000n, // 0.001 ETH
});
const txHash = await publicClient.signAndSendPreparedTransaction(
prepared.unsignedTransaction,
);
const receipt = await publicClient.waitForTransactionReceipt(txHash);
console.log('Transaction confirmed:', receipt.transactionHash);
// Sign a message
const signature = await publicClient.signMessage({
message: 'Hello from my agent',
});Full Integration Example
A complete backend service that creates an agent and later uses it to send a transaction:
import { AgentKitClient } from '@abstraxn/agent-kit';
const agentKit = new AgentKitClient({
apiKey: process.env.ABSTRAXN_API_KEY!,
});
// ── Step 1: Create agent + wallet (run once, store results) ──
async function onboardAgent(userEmail: string) {
const { agent, wallet } = await agentKit.createAgent({
name: `Agent for ${userEmail}`,
description: 'Autonomous trading agent',
userIdentity: userEmail,
userEmail,
});
// Store in your database
return {
agentId: agent.id,
apiKey: agent.apiKey,
accessKey: wallet.accessKey, // ⚠️ encrypt at rest
evmAddress: wallet.evmAddress,
organizationId: wallet.organizationId,
};
}
// ── Step 2: Use the agent to sign & send transactions ──
async function executeAgentTrade(agentRecord: {
accessKey: string;
evmAddress: string;
organizationId: string;
userIdentity: string;
}) {
const signer = agentKit.getServerSigner();
await signer.authenticate({
userIdentity: agentRecord.userIdentity,
accessKey: agentRecord.accessKey,
});
const client = signer.createPublicClient({
rpcUrl: process.env.RPC_URL!,
chainId: Number(process.env.CHAIN_ID!),
organizationId: agentRecord.organizationId,
fromAddress: agentRecord.evmAddress as `0x${string}`,
});
const prepared = await client.prepareTransaction({
to: '0xRecipientAddress...' as `0x${string}`,
value: 500_000_000_000_000n,
});
const txHash = await client.signAndSendPreparedTransaction(
prepared.unsignedTransaction,
);
const receipt = await client.waitForTransactionReceipt(txHash);
return receipt;
}
// ── Step 3: Manage agents ──
async function manageAgents() {
// List all agents
const { items } = await agentKit.listAgents();
// Set spend limits
for (const agent of items) {
await agentKit.updateSpendPolicy(agent.id, {
enabled: true,
budgetUsd: '10.00',
period: 'daily',
hardBlock: true,
});
}
// Deactivate an agent
await agentKit.updateAgent(items[0].id, { isActive: false });
}Configuration
| Option | Required | Default | Description |
| ------------ | -------- | -------------------------------- | ---------------------------------------- |
| apiKey | Yes | — | API key from the Abstraxn dashboard |
| baseUrl | No | https://agent-kit.abstraxn.com | Agent Kit service base URL |
| retryCount | No | 1 | Number of retries for transient failures |
| fetch | No | Global fetch | Custom fetch implementation |
Error Handling
All errors extend AgentKitError with code and statusCode properties:
import {
AgentKitError,
ValidationError, // 400 — invalid input
BadRequestError, // 400 — server rejected request
UnauthorizedError, // 401 — invalid or missing API key
ForbiddenError, // 403 — insufficient permissions
NotFoundError, // 404 — agent not found
ConflictError, // 409 — duplicate resource
NetworkError, // network connectivity issue
} from '@abstraxn/agent-kit';
try {
await agentKit.createAgent({ ... });
} catch (error) {
if (error instanceof UnauthorizedError) {
console.error('Invalid API key — check your dashboard');
} else if (error instanceof NotFoundError) {
console.error('Agent not found');
} else if (error instanceof AgentKitError) {
console.error(`[${error.code}] ${error.message}`);
}
}Security Notes
- Store
accessKeyin a secure secrets manager or encrypted database column. - Never expose
accessKeyin frontend code or logs. - The
mcpToken(frombindAgent) is a one-time value — store it securely on first receipt. - Rotate API keys via the Abstraxn dashboard if compromised.
License
MIT
