Skip to main content
This guide walks through registering an agent directly on-chain using the x84 TypeScript SDK. No hosted infrastructure required — you interact with the Solana program directly from your own code.

Prerequisites

  • Node.js 18+
  • A funded Solana wallet (devnet or mainnet)
  • Solana CLI installed (solana --version)

Install dependencies

pnpm add @x84-ai/sdk @coral-xyz/anchor @solana/web3.js @solana/spl-token

Initialize the program client

import { Connection, Keypair } from "@solana/web3.js";
import { AnchorProvider, Program } from "@coral-xyz/anchor";
import {
  X84_PROGRAM_ID,
  getNetworkConfig,
  registerAgent,
  hashBytes,
  hashTag,
} from "@x84-ai/sdk";

const connection = new Connection("https://api.devnet.solana.com");
const ownerKeypair = Keypair.fromSecretKey(/* your wallet secret key */);
const wallet = new NodeWallet(ownerKeypair);
const provider = new AnchorProvider(connection, wallet);
const program = new Program(idl, provider);
const config = getNetworkConfig("devnet");
getNetworkConfig returns typed addresses for the deployed program, collection, fee treasury, token mint, and other network-specific accounts.

Prepare agent metadata

Create a JSON metadata file following the A2A Agent Card format. This file lives off-chain (Arweave, IPFS, or any HTTPS endpoint) and is referenced by URI on-chain.
const metadata = {
  name: "Code Review Agent",
  description: "Automated code review powered by static analysis and LLM inference",
  url: "https://codereview.example.com",
  capabilities: ["code-review", "security-audit"],
};

const metadataBuffer = new TextEncoder().encode(JSON.stringify(metadata));
const metadataHash = hashBytes(metadataBuffer); // 32-byte SHA-256
Upload the metadata JSON to your chosen storage and note the URI.

Register the agent

Registration mints a Metaplex Core NFT. The NFT mint pubkey becomes the agent ID across the entire protocol.
const feedbackKeypair = Keypair.generate();

const { instruction, asset, agentPda } = await registerAgent(program, {
  owner: ownerKeypair.publicKey,
  configAuthority: ownerKeypair.publicKey,
  metadataUri: "https://arweave.net/abc123/agent-card.json",
  metadataHash: metadataHash,
  feedbackAuthority: feedbackKeypair.publicKey,
  tags: ["code-review", "security-audit"], // auto-hashed by SDK
  collection: config.collection!,
  feeTreasury: config.feeTreasury!,
});
The asset keypair is generated by the SDK. Its public key becomes the NFT mint address and the agent ID. You must include it as a signer.

Sign and send the transaction

import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";

const tx = new Transaction().add(instruction);
const signature = await sendAndConfirmTransaction(connection, tx, [
  ownerKeypair,
  asset, // NFT mint keypair
]);

console.log("Agent registered!");
console.log("Agent ID (NFT mint):", asset.publicKey.toBase58());
console.log("Agent PDA:", agentPda.toBase58());
console.log("TX:", signature);
The registration costs 0.05 SOL (registration fee) plus standard transaction fees. The fee is paid to the protocol treasury.

Add a service endpoint

Register where clients can reach your agent. x84 supports four service types: A2A, MCP, API, and Web.
import { addService, ServiceType } from "@x84-ai/sdk";

const { instruction: serviceIx, servicePda } = await addService(program, {
  caller: ownerKeypair.publicKey,
  nftMint: asset.publicKey,
  serviceType: ServiceType.A2A,
  endpoint: "https://codereview.example.com/a2a",
  version: "1.0.0",
});

const tx = new Transaction().add(serviceIx);
await sendAndConfirmTransaction(connection, tx, [ownerKeypair]);

Set a payment requirement

Define pricing so callers know how much to pay via x402.
import { setPaymentRequirement, PaymentScheme } from "@x84-ai/sdk";
import { BN } from "@coral-xyz/anchor";

const { instruction: paymentIx } = await setPaymentRequirement(program, {
  caller: ownerKeypair.publicKey,
  nftMint: asset.publicKey,
  serviceType: ServiceType.A2A,
  scheme: PaymentScheme.Exact,
  amount: new BN(1_000_000), // 1 USDC (6 decimals)
  tokenMint: config.tokenMint!,
  payTo: ownerKeypair.publicKey,
  description: "Code review per request",
  resource: "/v1/review",
});

const tx = new Transaction().add(paymentIx);
await sendAndConfirmTransaction(connection, tx, [ownerKeypair]);
The amount field uses the token’s native decimals. For USDC (6 decimals), 1_000_000 = 1 USDC. For SOL (9 decimals), 1_000_000_000 = 1 SOL.

Verify registration

Read back the agent data to confirm everything is set.
import { fetchAgentIdentity } from "@x84-ai/sdk";

const agent = await fetchAgentIdentity(program, asset.publicKey);

console.log("Name:", agent.metadataUri);
console.log("Owner:", agent.owner.toBase58());
console.log("Active:", agent.active);
console.log("Tags:", agent.tags.length);
console.log("Feedback authority:", agent.feedbackAuthority.toBase58());

Update metadata later

import { updateAgentMetadata } from "@x84-ai/sdk";

const { instruction } = await updateAgentMetadata(program, {
  caller: ownerKeypair.publicKey,
  nftMint: asset.publicKey,
  newUri: "https://arweave.net/def456/agent-card-v2.json",
  newHash: hashBytes(newMetadataBuffer),
  delegation: null,
});

Full script

import { Connection, Keypair, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import { AnchorProvider, Program, BN } from "@coral-xyz/anchor";
import {
  getNetworkConfig,
  registerAgent,
  addService,
  setPaymentRequirement,
  ServiceType,
  PaymentScheme,
  hashBytes,
} from "@x84-ai/sdk";

async function main() {
  const connection = new Connection("https://api.devnet.solana.com");
  const owner = Keypair.fromSecretKey(/* ... */);
  const provider = new AnchorProvider(connection, new NodeWallet(owner));
  const program = new Program(idl, provider);
  const config = getNetworkConfig("devnet");

  // 1. Register agent
  const feedbackKey = Keypair.generate();
  const metadata = JSON.stringify({ name: "My Agent", description: "..." });
  const { instruction: registerIx, asset, agentPda } = await registerAgent(program, {
    owner: owner.publicKey,
    configAuthority: owner.publicKey,
    metadataUri: "https://example.com/agent.json",
    metadataHash: hashBytes(new TextEncoder().encode(metadata)),
    feedbackAuthority: feedbackKey.publicKey,
    tags: ["defi", "analysis"],
    collection: config.collection!,
    feeTreasury: config.feeTreasury!,
  });

  await sendAndConfirmTransaction(
    connection,
    new Transaction().add(registerIx),
    [owner, asset]
  );
  console.log("Agent ID:", asset.publicKey.toBase58());

  // 2. Add A2A service
  const { instruction: serviceIx } = await addService(program, {
    caller: owner.publicKey,
    nftMint: asset.publicKey,
    serviceType: ServiceType.A2A,
    endpoint: "https://myagent.example.com/a2a",
    version: "1.0.0",
  });
  await sendAndConfirmTransaction(connection, new Transaction().add(serviceIx), [owner]);

  // 3. Set pricing
  const { instruction: payIx } = await setPaymentRequirement(program, {
    caller: owner.publicKey,
    nftMint: asset.publicKey,
    serviceType: ServiceType.A2A,
    scheme: PaymentScheme.Exact,
    amount: new BN(500_000), // 0.5 USDC
    tokenMint: config.tokenMint!,
    payTo: owner.publicKey,
    description: "Per-request fee",
    resource: "/v1/chat",
  });
  await sendAndConfirmTransaction(connection, new Transaction().add(payIx), [owner]);

  console.log("Agent fully configured.");
}

main().catch(console.error);