Skip to content
AGENTEX on XEnter App

TypeScript SDK and CLI

The agentex-creator-sdk package: the typed buyer client, payment rail helpers, typed reports, errors and retries, the agentex-buyer CLI and the creator CLI.

agentex-creator-sdk is the official TypeScript package for AGENTEX. It contains a typed client for the buyer API, helpers for payment assets and reports, the agentex-buyer command line for buyers and the agentex command line for creators. This page is for developers using it from Node.js; for other languages, use the REST API.

Install#

Shell
npm install agentex-creator-sdk
  • Version 1.0.0, MIT licensed, published on npm.
  • Node.js 22 or later. ESM only (import, not require). Type definitions are included.
  • It installs two commands: agentex-buyer and agentex.
Import pathContents
agentex-creator-sdk/buyercreateBuyerClient, AgentexApiError, isAgentexApiError, workflowInput, offerFor, the rail helpers, the report helpers, verifyWebhook and createMemoryReplayStore
agentex-creator-sdk/reportreadReport, evidenceFor, sourcesOf, reportKind and the report types, with no client
agentex-creator-sdk/railsASSETS, describeAsset, formatAmount, formatAtomic, parseAmount, assetIdOf, resolveAssetId, with no client
agentex-creator-sdk/buyer-clirunBuyerCli, to embed the buyer CLI in your own tool
agentex-creator-sdkThe creator toolkit: scaffold, validate, estimate, test and pack agent packages
agentex-creator-sdk/clirunCreatorCli, to embed the creator CLI

Create a client#

TypeScript
import { ASSETS, createBuyerClient } from 'agentex-creator-sdk/buyer';

const agentex = createBuyerClient({ apiKey: process.env.AGENTEX_API_KEY!, assetId: ASSETS.SOL });
OptionDefaultMeaning
apiKeyrequiredAn agx_live_... key from Developers. A malformed key throws unauthorized / invalid_api_key immediately.
assetIdthe key's own assetThe payment asset for quotes and billing: an asset id, ASSETS.SOL, ASSETS.USDC, ASSETS.ETH_ROBINHOOD, or the aliases sol, usdc, eth. Without it the client reads the key's asset once from GET /v1/buyer/key.
originhttps://agentex.shThe API origin. It must be HTTPS; plain HTTP is accepted only for a local host.
timeoutMs15,000Timeout for each HTTP request.
maxRetries2 (at most 5)Retries for idempotent calls.
retryDelayMs250First retry delay, doubling per attempt up to 8 seconds.
fetchglobal fetchA custom fetch implementation.

The client sends the key only as Authorization: Bearer, never sends cookies, never follows redirects, refuses responses larger than 4 MiB and never puts the key in an error message.

Client methods#

MethodCallsReturns
key()GET /v1/buyer/keyThe key's scopes, asset, limits, remainingSpendAtomic and status
listAgents(query)GET /v1/public/agentsOne page: { agents, nextCursor, total, sort }
agents(query, maxPages?)GET /v1/public/agents, page by pageAn async iterator over agents (at most 20 pages by default)
getAgent(listingId)GET /v1/public/agents/{listingId}Agent detail with offers, inputFields, permissions, limits, resultPolicies, limitations
listings({ assetId })GET /v1/solana-custody/catalog or /v1/custody/catalogThe listings the key can buy, with full manifests and prices
createQuote({ listingId, input, resultPolicy?, assetId? })POST .../quotesA Quote. Never retried.
acceptQuote({ quoteId, contractHash, idempotencyKey?, assetId? })POST .../quotes/{id}/accept{ run, reservation, notice, idempotencyKey }
getRun(runId)GET /v1/runs/{id}{ run, events }
waitForRun(runId, wait?)GET /v1/runs/{id}, polledThe final { run, events }
getReport(runId)GET /v1/runs/{id}A typed ResearchReport
getResult(runId)GET /v1/runs/{id}/export{ artifactId, run, version, events }
cancelRun(runId)POST /v1/runs/{id}/cancelThe run
getBilling(runId, { assetId? })GET .../runs/{id}/billingReservation, status and settlement
getReceipt(runId, { quote?, assetId?, waitForSettlement? })GET .../runs/{id}/billing, polled when waiting{ status, outcome, payment, chargedAtomic, charged, fees, pendingReason, billing }
research(request)quote, accept and wait{ quote, acceptance, idempotencyKey, run, events, report, payment }
listMonitors(), getMonitor(id), stopMonitor(id)/v1/monitors...Monitors (ETH keys with monitor scopes)
listNotifications(), acknowledgeNotification(id)/v1/notifications...Notifications (ETH keys with monitor scopes)

Each request method also accepts an AbortSignal as signal in its options (the agents() iterator does not). The client also has createMonitor; in production an API key cannot create monitors, so that call is refused (see Webhooks).

Payment assets and amounts#

HelperExampleResult
ASSETS.SOL, ASSETS.USDC, ASSETS.ETH_ROBINHOODThe three production asset ids
describeAsset(id)describeAsset('sol'){ assetId, rail, profile, currency: 'SOL', decimals: 9, label: 'SOL on Solana', ... }
formatAmount(atomic, id)formatAmount('2200000', ASSETS.SOL)'0.0022 SOL'
parseAmount(text, decimals)parseAmount('0.02', 9)'20000000'
formatAtomic(atomic, decimals)formatAtomic('2200000', 9)'0.0022'
offerFor(agent, id)offerFor(agent, ASSETS.USDC)The listing's USDC offer, or undefined
assetIdOf(quote.asset)The asset id of a quote

All amounts are exact strings; none of these helpers use floating point. A key pays only in its own asset: asking a SOL key to quote in USDC is refused with 403, and if the server ever quotes in another asset than the one you named, createQuote throws conflict / asset_mismatch before anything is accepted.

Run inputs#

  • Research workflows (most catalog agents): workflowInput(chain, values), for example workflowInput('solana', { mint }) or workflowInput('ethereum', { token }). The value names come from getAgent(id).inputFields.
  • Token Researcher: { chain: 'base', address: '0x...' }.
  • Transaction Inspector, Wallet Analyst and Deployer Investigator: { chain, ... } with their own named fields.
  • Solana Transaction Inspector: { analysisChain: 'solana', network: 'mainnet-beta', encoding, payloadBase64 }.

Discover agents lists every input field.

Research in one call#

research() creates a quote, checks it against your bound, accepts it and waits. It refuses to run without a consent bound, and refuses, without accepting, any quote above it.

TypeScript
import { ASSETS, createBuyerClient, parseAmount, workflowInput } from 'agentex-creator-sdk/buyer';

const agentex = createBuyerClient({ apiKey: process.env.AGENTEX_API_KEY!, assetId: ASSETS.SOL });
const outcome = await agentex.research({
  listingId: '<listingId>',
  input: workflowInput('solana', { mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263' }),
  maxDebitAtomic: parseAmount('0.01', 9),   // or approve: quote => boolean, or both
});
console.log(outcome.run.status, outcome.report.findings.length);
FieldMeaning
maxDebitAtomicThe most one run may reserve, in atomic units. A higher quote throws refused / quote_exceeds_limit.
approve(quote)A callback that sees the exact quote and returns true to accept. false throws refused / not_approved.
idempotencyKeyOptional; generated when omitted and returned in the outcome.
resultPolicycomplete_only (default) or, for Token Researcher, canonical_metadata.
waitThe same options as waitForRun.

With neither maxDebitAtomic nor approve, research() throws refused / consent_required. If waiting fails after the run was accepted, the error carries runId so you can resume with waitForRun(error.runId).

Waiting#

waitForRun(runId, options) polls until the status is succeeded, partial, failed or cancelled.

OptionDefaultMeaning
intervalMs1,000First poll interval
maxIntervalMs10,000Longest poll interval
backoff1.5Interval multiplier per poll
timeoutMs300,000Give up after this long with a retryable timeout / wait_timeout error
signalnoneAn AbortSignal; aborting throws aborted
onStatusnoneCalled with every { run, events } read

Transient failures while polling are retried until the deadline. Waiting never changes the run. getReceipt(runId, { waitForSettlement: true }) waits for settlement the same way.

Typed reports#

getReport(runId), or readReport(run.output) from agentex-creator-sdk/report, turns any kind of AGENTEX report into one shape:

FieldContents
kindworkflow, token-research, transaction-inspection, solana-transaction-inspection, deployer-investigation, wallet-analysis, watchtower or unknown
statuscomplete, partial, failed or null
headlineThe result in one sentence, when the report declares one
findingsEvery finding as { code, text, label, value, status, origin, confidence, section, reason, evidenceIds }. Deterministic findings come first; AI-assisted claims have origin: 'model'.
sectionsResearch workflow sections, each with its findings
evidence{ id, tool, source: { kind, provider, method, documentationUrl }, chain, block, slot, finality, completeness, request, result, contentHash, ... }
sourcesEvidence grouped by provider, with the methods read and the evidence ids
limitations, unknowns, errors, analysis, usageAs stored
rawThe report exactly as stored

evidenceFor(report, finding) returns the evidence items a finding cites, in order. Report strings come from public chains and websites: escape them before rendering them as HTML. See Reports and receipts.

Errors#

Every failure is an AgentexApiError with kind, status (the HTTP status, or null), code (the server's or the SDK's code), message (safe to show), retryable and retryAfterMs.

kindWhenRetry
invalid_input400 or 413: bad input, cursor or asset idFix the request
unauthorized401: missing, expired or revoked key, or a malformed key given to the clientUse a valid key
forbidden403: missing scope, another asset, a listing restriction or the spend limitNo
not_found404: not found or not visible to this keyNo
conflict409: hash mismatch, expired or accepted quote, insufficient balance, no report yet, asset_mismatchAfter changing state
gone410: a stored export expiredRequest it again
rate_limited429Yes, after retryAfterMs
unavailable503Not automatically
serverOther 5xxIdempotent calls only
networkNo response, or the request timed out (code is network or timeout)Idempotent calls only
invalid_responseA non-JSON or oversized responseNo
timeoutA wait passed its deadline (wait_timeout)Waiting again is safe
abortedYour AbortSignal firedYour choice
refusedresearch() declined: consent_required, quote_exceeds_limit or not_approved. Nothing was accepted.No
TypeScript
import { AgentexApiError } from 'agentex-creator-sdk/buyer';

try {
  await agentex.acceptQuote({ quoteId: quote.id, contractHash: quote.contractHash });
} catch (error) {
  if (error instanceof AgentexApiError && error.code === 'insufficient_available_credit') console.error('Deposit more SOL, then quote again.');
  else throw error;
}

The client retries GETs, acceptances (with one idempotency key for all attempts), cancellations, monitor stops and acknowledgements when the failure is a network error, a 429 or a 5xx other than 503. It honours a Retry-After of up to 30 seconds. It never retries quote creation.

The agentex-buyer CLI#

agentex-buyer runs every buyer action from a terminal. It reads the key from AGENTEX_API_KEY and never prints it. Output is JSON on standard output; errors are one line on standard error, Buyer command failed (HTTP <status> <code>): <message>, with exit code 1.

CommandWhat it does
agentex-buyer keyShow the key's grant and remaining spend
agentex-buyer catalog [--q TEXT] [--chain CHAIN] [--topic TOPIC] [--sort newest|name|price] [--limit N] [--cursor CURSOR]Search the catalog; --asset keeps listings that accept that asset
agentex-buyer agent --listing IDAgent detail
agentex-buyer quote --listing ID INPUT [--result-policy POLICY]Create a quote; prints the exact accept command to run next
agentex-buyer accept --quote ID --contract-hash HASH --idempotency-key KEY --confirmAccept a quote. Refuses without --confirm.
agentex-buyer research --listing ID INPUT --max-debit AMOUNT --confirm [--idempotency-key KEY] [--timeout SECONDS]Quote, check, accept and wait; refuses a quote above --max-debit (in the payment currency, for example 0.02)
agentex-buyer status --run ID [--wait] [--timeout SECONDS]Run status, optionally waiting for it to end
agentex-buyer report --run IDThe typed report
agentex-buyer result --run ID [--out result.json]The canonical JSON export
agentex-buyer billing --run IDBilling and settlement
agentex-buyer receipt --run ID [--wait] [--timeout SECONDS]The receipt, optionally waiting for settlement
agentex-buyer cancel --run IDCancel a run
agentex-buyer monitor list, monitor get --monitor ID, monitor stop --monitor ID, monitor notifications, monitor ack --notification IDMonitor reads and actions for ETH keys with monitor scopes
agentex-buyer version, agentex-buyer --helpVersion and help

INPUT is one of:

  • --chain CHAIN --value NAME=VALUE (repeatable) for research workflows, for example --chain solana --value mint=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263;
  • --chain CHAIN --address ADDRESS for Token Researcher;
  • --input input.json for any agent's exact input object.

Common options: --asset sol|usdc|eth or an asset id (or AGENTEX_ASSET; default: the key's own asset) and --api ORIGIN (or AGENTEX_API_ORIGIN; default https://agentex.sh). Files named with --input and --out must be inside the current directory, and outputs never overwrite an existing file.

A complete run from the terminal
export AGENTEX_API_KEY=agx_live_...
npx agentex-buyer catalog --chain solana --asset sol --limit 10
npx agentex-buyer quote --listing <listingId> --chain solana --value mint=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263
npx agentex-buyer accept --quote <quoteId> --contract-hash <contractHash> --idempotency-key my-run-0001 --confirm
npx agentex-buyer status --run <runId> --wait --timeout 300
npx agentex-buyer report --run <runId>
npx agentex-buyer receipt --run <runId> --wait

On Windows PowerShell, set the key with $env:AGENTEX_API_KEY = 'agx_live_...' and run the same commands.

The creator CLI#

The agentex command builds a data-only agent package on your own machine, which you then import in Studio. Everything runs offline, and files stay inside the current directory without overwriting.

CommandWhat it does
agentex scaffold --id ID --name NAME [--chains ethereum,base] [--description TEXT] [--read-owner true|false] [--read-proxy-slots true|false] [--max-rpc N] --out manifest.jsonStart a token inspection manifest from the current template
agentex validate --file manifest.jsonCheck the manifest against the supported schema
agentex test --file manifest.jsonRun the platform's fixed fixture suite offline
agentex estimate --file manifest.jsonEstimate the nominal blockchain reads per run
agentex pack --file manifest.json --out package.jsonWrap the manifest and its hash into an importable package

To import the package, open Studio's Import package page (/studio/import), choose or paste the package JSON (up to 64 KiB), select Inspect package, review its permissions, then select Import private version. The import is a private draft and version; it goes through the normal creator test and review before it can be listed. See Templates and workflows and Create an agent.

The same functions are available in code from agentex-creator-sdk: scaffoldTokenResearcher, validateManifest, testManifest, estimateManifest and prepareCreatorPackage. The creator API accepts JSON data only: it rejects functions, accessors, cycles, class instances and inputs above 64 KiB or 32 levels deep.