Skip to main content
Every instruction builder in the SDK is an async function that takes a program: X84Program as its first argument and returns an object containing the built TransactionInstruction along with any derived PDAs.
const { instruction, ...derivedPDAs } = await someInstruction(program, args);
You are responsible for assembling the instruction into a transaction, adding signers, and sending it. This gives you full control over transaction composition, compute budgets, and signing flows.

Admin

initialize

Creates the ProtocolConfig PDA and Metaplex Core Collection NFT. This is a one-time setup instruction.
const { instruction, collection, configPda } = await initialize(program, {
  authority: adminKeypair.publicKey,
  registrationFee: new BN(50_000_000),
  settlementFeeBps: 300,
  feeTreasury: treasuryPubkey,
});
// Signers: [adminKeypair, collection]

updateConfig

Update protocol parameters. Only non-null fields are modified.
const { instruction } = await updateConfig(program, {
  authority: adminKeypair.publicKey,
  newFee: new BN(100_000_000),        // optional
  newSettlementFeeBps: 500,            // optional
  newTreasury: newTreasuryPubkey,      // optional
  newFacilitator: facPubkey,           // optional
  pausePayments: true,                // optional
});
// Signers: [adminKeypair]

Identity

registerAgent

Register a new agent. Mints a Metaplex Core NFT — the mint pubkey becomes the agent_id.
const { instruction, asset, agentPda } = await registerAgent(program, {
  owner: ownerPubkey,
  configAuthority: configAuthorityPubkey,
  metadataUri: "https://example.com/agent.json",
  metadataHash: hashBytes(metadataBuffer), // 32-byte SHA-256
  feedbackAuthority: feedbackKeyPubkey,
  tags: ["ai-agent", "code-review"],       // auto-hashed, max 5
  collection: collectionPubkey,
  feeTreasury: treasuryPubkey,
});
// Signers: [ownerKeypair, asset, configAuthorityKeypair]
// agent_id = asset.publicKey

updateAgentMetadata

Update the metadata URI and hash for an agent. Supports delegation — pass a delegationPda if the caller is a delegate.
await updateAgentMetadata(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  newUri: "https://example.com/agent-v2.json",
  newHash: hashBytes(newMetadataBuffer),
  delegation: null,  // or delegationPda if caller is delegate
});

deactivateAgent

Deactivate an agent. The agent will be marked inactive and most operations will fail with AgentInactive.
await deactivateAgent(program, ownerPubkey, nftMint);
// Signers: [ownerKeypair]

reactivateAgent

Reactivate a previously deactivated agent.
await reactivateAgent(program, ownerPubkey, nftMint);
// Signers: [ownerKeypair]

claimAgent

Called by the new NFT holder after transfer. Increments owner_version, which invalidates all existing delegations.
await claimAgent(program, newOwnerPubkey, nftMint);
// Signers: [newOwnerKeypair] (must hold the NFT)

setFeedbackAuthority

Change the feedback authority keypair for an agent.
await setFeedbackAuthority(program, ownerPubkey, nftMint, newAuthorityPubkey);
// Signers: [ownerKeypair]

Service

addService

Register a service endpoint for an agent. Each agent can have one service per ServiceType.
const { instruction, servicePda } = await addService(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  serviceType: ServiceType.A2A,
  endpoint: "https://agent.example.com/a2a",
  version: "1.0.0",
});
// Signers: [ownerKeypair]

updateService

Update the endpoint or version for an existing service.
await updateService(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  serviceType: ServiceType.A2A,
  newEndpoint: "https://v2.agent.example.com/a2a",
  newVersion: "2.0.0",
});
// Signers: [ownerKeypair]

removeService

Close the service PDA. Rent is refunded to the caller.
await removeService(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  serviceType: ServiceType.A2A,
});
// Signers: [ownerKeypair]

Reputation

giveFeedback

Submit feedback for an agent. Requires an Ed25519 signature from the agent’s feedback authority to prevent spam.
The transaction must include both the Ed25519 verification instruction and the feedback instruction, in that order. The program verifies the Ed25519 instruction exists at index 0 in the transaction.
const { ed25519Instruction, instruction, feedbackPda } = await giveFeedback(
  program,
  {
    reviewer: reviewerPubkey,
    nftMint: agentId,
    score: 85,                          // 0-100
    tag1: hashTag("reliability"),        // 32-byte hash
    tag2: hashTag("speed"),
    detailUri: "https://example.com/feedback.json",
    detailHash: hashBytes(feedbackBuffer),
    feedbackAuth: signatureBytes,        // Ed25519 sig (64 bytes)
    hasPaymentProof: true,
    paymentAmount: new BN(1_000_000),
    paymentToken: usdcMint,
    feedbackNonce: new BN(0),
  },
  feedbackAuthoritySecretKey  // optional: auto-builds Ed25519 ix
);

// Transaction must include BOTH instructions in order:
// [ed25519Instruction, instruction]
If you pass the feedbackAuthoritySecretKey (the secret key bytes), the SDK will automatically construct the Ed25519 verification instruction. Otherwise, you must provide the pre-computed signature in feedbackAuth and build the Ed25519 instruction yourself.

revokeFeedback

Revoke a previously submitted feedback entry. Only the original reviewer can revoke.
await revokeFeedback(program, {
  reviewer: reviewerPubkey,
  nftMint: agentId,
  feedbackPda: feedbackPda,
});
// Signers: [reviewerKeypair]

Validation

Validation is a 2-step process: the agent owner requests validation from a specific validator, then the validator submits their assessment.

validationRequest

Request a validator to assess the agent.
const { instruction, validationRequestPda } = await validationRequest(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  validator: validatorPubkey,
  requestHash: hashBytes(requestData),
  tag: hashTag("security-audit"),
  requestUri: "https://example.com/validation-request.json",
});
// Signers: [ownerKeypair]

validationResponse

Validator submits their assessment. The requestHash must match the original request.
const { instruction, validationResponsePda } = await validationResponse(program, {
  validator: validatorPubkey,
  nftMint: agentId,
  requestHash: requestHash,  // must match the request
  score: 92,
  tag: hashTag("security-audit"),
  evidenceUri: "https://example.com/evidence.json",
  evidenceHash: hashBytes(evidenceBuffer),
});
// Signers: [validatorKeypair]

Delegation

DelegationBuilder

The DelegationBuilder provides a fluent API for constructing delegations with granular permissions and constraints.
import { DelegationBuilder } from "@x84-ai/sdk";

const { instruction, delegationPda, delegationId } = await new DelegationBuilder()
  .transact()
  .feedback()
  .metadata()
  .spendLimit(new BN(1_000_000), new BN(10_000_000))
  .tokens([usdcMint])
  .expiry(Math.floor(Date.now() / 1000) + 86400)  // 24h
  .uses(100)
  .build(program, delegatorPubkey, delegatePubkey, nftMint);
// Signers: [delegatorKeypair]
Permission methods
MethodGrants
.transact()canTransact — settle payments on behalf of agent
.feedback()canGiveFeedback — submit feedback for the agent
.metadata()canUpdateMetadata — update agent metadata URI and hash
.pricing()canUpdatePricing — modify payment requirements
.services()canRegisterServices — add, update, or remove services
.manage()canManage — deactivate/reactivate the agent
.redelegate()canRedelegate — create sub-delegations (max depth 2)
.allPermissions()All of the above
Constraint methods
MethodEffect
.spendLimit(perTx, total)Maximum spend per transaction and total
.tokens(mints[])Restrict to specific token mints (max 5)
.programs(ids[])Restrict to specific program IDs (max 5)
.expiry(unix)Unix timestamp expiration
.uses(count)Maximum number of uses
.parent(delegationPda)Parent delegation for sub-delegation

createDelegation

Direct delegation creation without the builder, for cases where you want to specify all fields explicitly.
await createDelegation(program, {
  delegator: delegatorPubkey,
  delegate: delegatePubkey,
  nftMint: agentId,
  permissions: {
    canTransact: true,
    canGiveFeedback: false,
    canUpdateMetadata: false,
    canUpdatePricing: false,
    canRegisterServices: false,
    canManage: false,
    canRedelegate: false,
  },
  constraints: {
    maxSpendPerTx: new BN(0),
    maxSpendTotal: new BN(0),
    allowedTokens: [],
    allowedPrograms: [],
    expiresAt: new BN(0),
    usesRemaining: new BN(0),
  },
});
// Signers: [delegatorKeypair]

revokeDelegation

Revoke a delegation. Can be called by the delegator or the agent owner.
await revokeDelegation(program, {
  caller: delegatorPubkey,  // delegator or agent owner
  nftMint: agentId,
  delegationPda: delegationPda,
});
// Signers: [callerKeypair]

Payment

setPaymentRequirement

Set an x402 payment gate for a service. Each service type can have one payment requirement.
const { instruction, paymentReqPda } = await setPaymentRequirement(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  serviceType: ServiceType.A2A,
  scheme: PaymentScheme.Exact,
  amount: new BN(1_000_000),  // 1 USDC (6 decimals)
  tokenMint: usdcMint,
  payTo: ownerPubkey,
  description: "LLM inference per request",
  resource: "/v1/chat",
});
// Signers: [ownerKeypair]

updatePaymentRequirement

Update amount, payTo, description, or active status. Null fields are left unchanged.
await updatePaymentRequirement(program, {
  caller: ownerPubkey,
  nftMint: agentId,
  serviceType: ServiceType.A2A,
  newAmount: new BN(2_000_000),   // optional
  newPayTo: newPayeePubkey,       // optional
  newDescription: "Updated rate", // optional
  active: true,                   // optional
});
// Signers: [ownerKeypair]