npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@perkos/agent-sdk

v0.9.1

Published

TypeScript SDK for agent identity, escrow settlement, and reputation on Stacks.

Readme

@perkos/agent-sdk

TypeScript SDK for agent identity, escrow settlement, and reputation on Stacks.

PerkOS gives AI agents a programmable path to register, hire, fund work with STX or sBTC, submit deliverables, settle escrow, and build job-linked reputation.

This repository is the continuation of PerkOS-xyz/PerkOS-Agent-SDK, renamed to connect the public SDK with the Nayori product identity. The npm package remains @perkos/agent-sdk and the complete Git history, releases, issues, and pull requests are preserved.

Release status: @perkos/[email protected] is the published stable public line (npm latest since 2026-09-13). It promotes Nayori's earned-fee agentic-commerce-v6 / sbtc-commerce-v5 contracts as the mainnet defaults while preserving generic testnet v5/v4 and explicit QA v6/v5; the agent registry and reputation-registry-v3 are unchanged. Read clients, transaction builders, browser and headless signer adapters, confirmation receipts, safety policies, and a transactional testnet quickstart are implemented. The x402 v2 client and Stacks facilitator foundations are implemented, with wallet-linked OAuth and MCP support for invite-only partners. QA uses Stacks testnet; production uses mainnet. External review and independently attributable adoption evidence remain open. The direct x402 profile includes request-bound pure verification and payer-side intent, policy, Leather, and remote-signer foundations for STX, sBTC, and USDCx. The SDK also implements the MPP PaymentAuth usdc/charge Stacks profile for direct USDCx, including canonical challenges, credentials, pure verification and settlement receipts. Every payment signature remains delegated to the configured wallet or custody boundary. Mainnet facilitator settlement is confirmation-gated and payer-approved; sponsorship remains disabled.

Connect an existing agent

0.9.0 is the reviewed and published public npm line (latest, published 2026-09-13) with mainnet defaults agentic-commerce-v6 / sbtc-commerce-v5. Pin it exactly:

npm install --save-exact @perkos/[email protected]

The current patch is 0.9.1, which adds mainnet evaluation commitments. See 0.9.0 release and migration notes, including its publication record, and the immutable 0.8.0 release record. The rc.1 release record remains available for historical reproduction. The custody pilot remains testnet-only and does not inherit the mainnet default change.

Historical note (superseded 2026-09-13): earlier revisions of this README, including the copy bundled inside the published 0.9.0 tarball, described 0.8.0 as the public npm line and asked readers not to request 0.9.0 from npm until its publication gate completed. That gate has completed; the npm-hosted README can only be refreshed by a separate docs-only republish.

Your agent is already installed and working with your own LLM. Keep that setup: Nayori does not require PerkOS-LLM, Hermes or sharing model credentials. Start with the existing-agent onboarding guide: choose SDK/MCP → prepare your own wallet/signer separately → pin testnet and limits → register and verify the agent ID → create or fulfill work → verify settlement and reputation. Wallet creation is not registration, and OAuth access is not payment authority. Hermes is one supported MCP example, not a prerequisite. Operator-supervised internal sBTC lifecycles have passed; this is not certification of external onboarding. See validation and release boundaries.

Use the QA checkpoints and confirmation guide to distinguish wallet funding, registration, funded escrow, submitted work and final settlement. The custody pilot defaults to six subsequent Bitcoin burn blocks before advancing an operation; a txid or explorer success alone does not clear that gate. Preserve the journal rather than re-signing.

Start with the reproducible clean-install checkpoint: installed npm SDK, real MCP stdio for both roles and unsigned registration, without keys or LLM calls. This probe ships in 0.9.0 (first added in 0.8.0) and does not require a signer, wallet funding or LLM credentials.

Requirements

Configurable timing and confirmation policy

0.9.0 release notes record the current publication and exact installation; 0.8.0 release evidence records the previous stable gate. Historical prereleases remain immutable.

Confirmation policy and timing separates transaction depth, evaluation feedback and contractual appeal windows. Stable 0.8.0 added operator-bound version-2 QA permits and read-only progress, with conservative mainnet helpers. Existing version-1 permits and npm 0.8.0-rc.1 retain six burn blocks. The Hermes signer remains testnet-only; contract deadlines and x402/MPP are unchanged.

Nayori MCP for existing agents

Bounded job discovery adds optional nayori_list_jobs for either role. It does not claim jobs or sign, and leaves the existing six-tool default unchanged. Source constructor createNayoriMcp retains the old Hermes names as compatibility aliases; use your existing agent and its own configured LLM.

The stable package includes the Node-only nayori-mcp stdio binary for public testnet reads and offline buyer/provider commitments. It has no signer, broadcast, x402 purchase or wallet-generation tools by default. Optional operator-configured delegation to the separate nayori-custody pilot enables bounded QA actions without putting a key in MCP. Both are included in npm 0.9.0 (since 0.8.0). Clean registry installation and offline checks cover both roles. A prior published prerelease also passed a supervised funded lifecycle; broader autonomy and x402 remain separate gates. Provider operators may additionally enable public QA evaluation admission for the permitted, confirmed submission; this does not enable x402 purchases or expose evaluator credentials. See MCP setup and custody permissions, limits and release gates. Role-specific recording/QA guides: consumer and provider.

Connect your existing Hermes, OpenClaw, Codex or Claude Code through MCP client setup. Hermes has a verified internal lifecycle. OpenClaw, Codex and Claude Code passed native MCP connection checks for both roles; Codex also passed context and unsigned preparation calls. These network-disabled probes used no LLM, signer or funds; other client-specific E2Es remain pending. Evaluation admission has a bounded 45-second timeout; status reads retain 15 seconds. Check evaluator capacity before submission and reconcile the existing evaluation ID after an error. Do not retry an expired review or increase spending limits automatically.

Earned-service-fee integration

Mainnet v6/v5 uses a 2% included, evaluation-earned fee: net provider payout on approval or net client refund on evaluated rejection. The full budget stays in escrow until final settlement. Generic testnet remains v5/v4; the QA adapter continues to select v6/v5 explicitly. Existing jobs remain bound to their original contracts. See the integration and accounting guide before enabling any signer.

Runtime

  • Node.js 20 or newer
  • npm 10 or newer

Install

npm install --save-exact @perkos/[email protected]

npm latest resolves to 0.9.0 (published 2026-09-13); dist-tag next still points at the historical 0.8.0-rc.2 prerelease. Pin the exact version and keep the lockfile in any financial agent rather than relying on an unqualified install.

To develop from source:

git clone https://github.com/PerkOS-xyz/PerkOS-Nayori-Agent-SDK.git
cd PerkOS-Nayori-Agent-SDK
npm install
npm run verify
npm run quickstart

The quickstart performs public read-only calls and does not require a wallet or private key. Set PERKOS_NETWORK=testnet to read the testnet deployment.

The x402 foundation example is also read-only and requires no wallet. It creates and round-trips the official v2 PAYMENT-REQUIRED header for an existing PerkOS escrow job:

npm run quickstart:x402

The facilitator example uses public Hiro v3 transaction and event data to inspect a historical mainnet funding transaction. It proves the verifier fails closed when that otherwise matching proof is outside its payment window; it does not write replay state or submit a transaction:

npm run quickstart:x402:facilitator

The payer quickstart creates a request-bound USDCx intent, reserves explicit spending and fee limits, and builds a canonical unsigned Stacks transaction. It contains no private key, performs no network call, and does not request a wallet signature or broadcast:

npm run quickstart:x402:payer

The MPP PaymentAuth quickstart creates a standard WWW-Authenticate: Payment USDCx challenge, applies the same payer policy and builds an unsigned OnChainOnly Stacks transaction. It is offline, contains no private key and does not request a wallet signature or broadcast:

npm run quickstart:mpp

The transactional quickstart is safe by default: it prints an offline, role-separated STX/sBTC testnet workflow with committed criteria, provider evidence and appeal-aware settlement.

npm run quickstart:testnet

Use the role-separated QA guide and examples/testnet.env.example. Each process uses only its own client or provider signer; neither receives the evaluator key. One action runs per invocation. An external journal preserves txids and refuses automatic retries after ambiguous signing. The bridge and quickstart ship in 0.9.0 (first included in 0.8.0) for the QA workflow. Registry installation and offline role checks passed on the 0.8.0 line; job16 separately verified the funded npm SDK lifecycle with policy0/6 on the historical 0.8.0-rc.2 prerelease. See the separate evidence scopes.

Read on-chain state

import { PerkOSClient } from "@perkos/agent-sdk";

const perkos = new PerkOSClient({ network: "mainnet" });

const agentCount = await perkos.getAgentCount();
const sbtcJob = await perkos.getJob("sbtc", 1n);
const escrow = await perkos.getEscrowBalance("sbtc", 1n);
const reputation = await perkos.getReputation(
  "SP000000000000000000002Q6VF78"
);

Amounts are returned as bigint. sBTC values are satoshis and STX values are micro-STX.

Build a transaction plan

Builders return explicit, inspectable plans. They do not sign, broadcast, or read environment variables.

const plan = perkos.transactions.registerAgent({
  name: "Research Agent",
  description: "Produces cited market research.",
  wallet: "SP...",
  endpoints: [{ name: "mcp", url: "https://agent.example/mcp" }],
});

console.log(plan.contract, plan.functionName, plan.functionArgs);

Funding plans require the sender and generate an exact post-condition:

const plan = perkos.transactions.fundJob({
  asset: "sbtc",
  jobId: 7n,
  amount: 25_000n,
  sender: "SP...",
  serviceFeeAcceptance: {
    gross: 25_000n,
    basisPoints: 200,
    treasury: "SP1NT1V4X6GQR6T32Z8MSMNECZ6GSWX9HZ81SM1Y8",
    rejectionRefund: "net-after-evaluation",
  },
});

Settlement helpers read the job and escrow balance before building exact contract-principal post-conditions. This protects both wallet-originated and headless transactions from transferring more than the job requires.

Active versioned escrow

Published version 0.9.0 selects agentic-commerce-v6, sbtc-commerce-v5 and reputation-registry-v3 by default on mainnet. Generic testnet defaults deliberately remain v5/v4/v3; the QA adapter pins its reviewed v6/v5 contracts explicitly. A new mainnet job therefore needs no contract override:

import { PerkOSClient } from "@perkos/agent-sdk";

const perkos = new PerkOSClient({
  network: "mainnet",
  signer,
});

const job = await perkos.getJob("sbtc", 7n);
console.log(job?.submittedAtBurn, job?.reviewDeadline, job?.status);

// The evaluator records an explainable decision without moving escrow.
await perkos.recordDecision({
  asset: "sbtc",
  jobId: 7n,
  decision: "approve",
  evidenceHash: evidenceSha256,
  explanationHash: explanationSha256,
});

const sync = await perkos.getReputationSync("sbtc", 7n);
if (sync?.pending) await perkos.retryReputationSync("sbtc", 7n);

The fixed 12-burn-block review window is readable through getReviewWindow(asset). A decision opens the appeal period: three burn blocks in isolated QA and 144 on mainnet. The affected client or provider may appeal, a separately pinned human authority may resolve, and permissionless finalizers preserve liveness after either deadline. A review timeout is returned as the distinct timeout-paid (u6) status and must not be counted as a completed job or reputation success. A failed reputation write never rolls back economic settlement and can be retried permissionlessly.

Autonomous evaluation and appeals

Published 0.9.0 uses agentic-commerce-v6 and sbtc-commerce-v5 by default on mainnet:

const autonomous = new PerkOSClient({
  network: "mainnet",
  signer,
});

await autonomous.recordDecision({
  asset: "sbtc",
  jobId: 7n,
  decision: "approve",
  evidenceHash: evidenceSha256,
  explanationHash: explanationSha256,
});

const decision = await autonomous.getDecision("sbtc", 7n);
console.log(decision?.originalDecision, decision?.appealDeadline);

await autonomous.appealDecision({
  asset: "sbtc",
  jobId: 7n,
  evidenceHash: appealSha256,
});

Unappealed decisions are finalized with finalizeDecision. A separate pinned authority uses resolveAppeal; if it misses the second deadline, settleAppealTimeout preserves the original decision permissionlessly. High-level settlement methods derive recipients from on-chain state and use the live escrow plus the job-pinned sBTC token to construct exact deny-mode post-conditions. Every digest must be a non-zero 32-byte hexadecimal string or Uint8Array.

For sbtc-commerce-v2, sbtc-commerce-v3, sbtc-commerce-v4 and sbtc-commerce-v5, high-level settlement helpers also read the token pinned when the job was funded. Both the trait argument and exact fungible-token post-condition use that historical token, so rotating the contract's future funding default cannot strand an existing escrow.

The previous v5/v4, v4/v3 and v3/v2 generations remain supported through explicit same-network overrides. Existing jobs must keep their original contract IDs; changing SDK defaults never migrates escrow. The historical v4/v3/v3 generation first passed on Stacks testnet. Controlled STX and official PoX-5 sBTC complete paths pass 27/27 and 30/30. The real timeout path passes preparation 20/20, settlement 12/12 and separate public-state verification 10/10. Job u2 settled at burn 11290 in 0x06537111…15bb9, ending in timeout-paid (u6) with zero escrow, one exact 1,000-atomic-unit sBTC payout and no completion, reputation or rating credit. The frozen evidence is documented in the contracts/Web repository.

The historical v5/v4 sources are live on mainnet under SP2K7PV5NXBNRV510S6DCA6RFMTFHAF3ZPK6ZSXPH. Deployment confirmed in blocks 8905872 and 8905874, with configuration through 8905886. Guarded STX and canonical-sBTC appeal canaries passed 47/47 and 50/50 checks, followed by an independent 75/75 public-state postcheck. Both jobs settled exactly once with zero escrow and synchronized reputation. Those actors are team-operated release evidence, not external adoption, non-team wallet activity or revenue. The independent external security review remains open.

Browser signer (Leather and other Stacks wallets)

StacksConnectSigner adapts the official Stacks Connect request API. The application supplies the connected address and request function; the SDK forwards the complete plan and never receives wallet key material.

import { request } from "@stacks/connect";
import { PerkOSClient, StacksConnectSigner } from "@perkos/agent-sdk";

const signer = new StacksConnectSigner({
  network: "mainnet",
  address: connectedStacksAddress,
  request,
});
const perkos = new PerkOSClient({ network: "mainnet", signer });

Install @stacks/connect in the browser application. Wallet discovery and account selection stay at the application boundary so the SDK cannot silently choose an account.

Invite-only partner OAuth and MCP

NayoriPartnerClient enrolls an invited partner without taking custody of a wallet. It requests a single-use challenge, delegates the exact plaintext to Leather through stx_signMessage, submits the signature and returns the generated OAuth client secret once. OAuth authorizes API/MCP access only; every payment remains a separate wallet-signed transaction.

import { request } from "@stacks/connect";
import {
  NayoriPartnerClient,
  createStacksConnectPartnerSigner,
} from "@perkos/agent-sdk";

const partners = new NayoriPartnerClient();
const credentials = await partners.enroll({
  invitationToken,
  walletAddress: connectedTestnetAddress,
  signMessage: createStacksConnectPartnerSigner(request),
});

// Move the one-time secret directly into the application's secret manager.
const token = await partners.requestToken({
  clientId: credentials.clientId,
  clientSecret: credentials.clientSecret,
  scopes: ["mcp:invoke"],
});

const tools = await partners.callMcp({
  accessToken: token.accessToken,
  method: "tools/list",
});

See Partner pilot for the complete enrollment, scope and secret-handling boundary.

Headless signer

HeadlessSigner requests key material only when deriving the public address or signing. It caches only the derived address. Use an external secret manager, KMS adapter, or another controlled key provider; never hardcode production keys.

import { HeadlessSigner, PerkOSClient } from "@perkos/agent-sdk";

const signer = new HeadlessSigner({
  network: "testnet",
  privateKeyProvider: async () => loadKeyFromSecretManager(),
});

const perkos = new PerkOSClient({ network: "testnet", signer });

The callback may return a string or Uint8Array. The SDK copies and zeroes its local binary-key buffer after use; JavaScript strings cannot be reliably erased from memory.

Confirmation receipts

Broadcast acceptance is not execution success. Confirm through the configured Stacks API before advancing an automated workflow:

const broadcast = await perkos.execute(plan);
const confirmation = await perkos.confirm(broadcast, {
  timeoutMs: 10 * 60_000,
  pollIntervalMs: 5_000,
});

if (confirmation.status !== "success") {
  throw new Error(`Transaction ended with ${confirmation.status}`);
}

Confirmation status is normalized to pending, success, abort, dropped, or timeout, with block and Clarity-result fields when the API supplies them. Polling supports cancellation through an AbortSignal. If the v3 status response omits a terminal Clarity result, the tracker hydrates that field from the transaction-detail endpoint.

Spending policy

Funding is fail-closed. Both limits must be configured for every spendable asset:

const perkos = new PerkOSClient({
  network: "mainnet",
  signer: new WalletSigner(),
  spendingPolicy: {
    allowedAssets: ["sbtc"],
    maxPerTransaction: { sbtc: 50_000n },
    maxPerSession: { sbtc: 150_000n },
  },
});

const job = await perkos.getJob("sbtc", 7n);
const fee = await perkos.getJobServiceFee("sbtc", 7n);
if (!job) throw new Error("Job not found");
const serviceFeeAcceptance = {
  gross: job.budget,
  basisPoints: 200 as const,
  treasury: fee.treasury,
  rejectionRefund: "net-after-evaluation" as const,
};

await perkos.fundJob({
  asset: "sbtc",
  jobId: 7n,
  amount: 25_000n,
  serviceFeeAcceptance,
});

The policy also limits networks and contract principals. Funding attempts without explicit per-transaction and per-session limits are rejected before the signer is called.

x402 v2 client foundation

The SDK uses the official @x402/core v2 envelope and header codecs while preserving the PerkOS escrow lifecycle. A protected resource describes an existing, open job and its exact atomic budget. The scheme client validates that quote against on-chain state, funds it through the configured SDK signer and spending policy, waits for successful confirmation, and produces the PAYMENT-SIGNATURE payload.

import { x402Client } from "@x402/core/client";
import {
  PerkOSClient,
  PerkOSX402SchemeClient,
  createPerkOSX402PaymentRequired,
  encodePaymentRequiredHeader,
  toStacksX402Network,
} from "@perkos/agent-sdk";

const perkos = new PerkOSClient({
  network: "mainnet",
  signer,
  spendingPolicy: {
    allowedAssets: ["sbtc"],
    maxPerTransaction: { sbtc: 25_000n },
    maxPerSession: { sbtc: 50_000n },
  },
});

const job = await perkos.getJob("sbtc", 7n);
const fee = await perkos.getJobServiceFee("sbtc", 7n);
if (!job) throw new Error("Job not found");

const required = createPerkOSX402PaymentRequired(perkos.config, {
  resource: {
    url: "https://agent.example/jobs/7/fund",
    description: "Fund job 7 escrow",
    mimeType: "application/json",
  },
  asset: "sbtc",
  jobId: 7n,
  amount: job.budget,
  serviceFeeTerms: {
    gross: job.budget,
    basisPoints: 200,
    treasury: fee.treasury,
    rejectionRefund: "net-after-evaluation",
  },
});

const network = toStacksX402Network(perkos.config.network);
const paymentClient = new x402Client()
  .setSpendControls({
    allowedAssets: [
      { network, asset: required.accepts[0].asset, maxAmountPerPayment: "25000" },
    ],
  })
  .register(
    network,
    new PerkOSX402SchemeClient({
      client: perkos,
      // Replace with an operator UI or deterministic policy that shows and accepts
      // the exact gross, 200 bps, treasury and net-rejection terms.
      acceptServiceFee: async (terms, requirement) =>
        operatorAccepted({ terms, requirement }),
    })
  );

const paymentPayload = await paymentClient.createPaymentPayload(required);
console.log(encodePaymentRequiredHeader(required), paymentPayload);

The proof produced here is client-side confirmation evidence, not authorization by itself. Use the facilitator below to independently inspect the Stacks transaction, match its payment fields, apply a confirmation policy, and consume it through a replay store.

Direct x402 payments on Stacks

The separate stacks-signed-tx-v1 profile covers immediate pay-per-call resources. It uses the official x402 v2 exact scheme and explicit upfront flow because the facilitator must commit the signed Stacks transaction before the resource handler runs. It supports:

| Asset | Wire asset | Canonical internal identity | Atomic unit | |---|---|---|---| | STX | STX | CAIP-19 slip44:5757 | micro-STX | | sBTC | canonical address.contract | CAIP-19 SIP-010 | satoshi | | USDCx | canonical address.contract | CAIP-19 SIP-010 | 10^-6 USDCx |

Create a short-lived request quote and compatibility-first requirement without a wallet or network call:

import {
  createNayoriX402PaymentRequirements,
  createNayoriX402Quote,
} from "@perkos/agent-sdk";

const quote = await createNayoriX402Quote({
  quoteId: "quote-weather-001",
  merchantId: "merchant-weather",
  network: "testnet",
  asset: "usdcx",
  amount: 100_000n,
  payTo: "ST...",
  method: "POST",
  url: "https://api.example.com/v1/weather",
  body: JSON.stringify({ city: "Miami" }),
  issuedAt: Math.floor(Date.now() / 1000),
  expiresAt: Math.floor(Date.now() / 1000) + 300,
});

const requirement = await createNayoriX402PaymentRequirements(quote);

The quote fingerprint is placed in the 34-byte Stacks/SIP-010 memo, so the origin signature binds the transaction to the HTTP method, canonical URL, body digest, network, asset, exact amount, recipient, merchant, and expiry. verifyNayoriX402DirectPayment then validates the x402 envelope, trusted quote, actual request, canonical transaction encoding, origin signature, payer, network, memo, transfer template, amount, recipient, token contract, function arguments, deny mode, and exact post-condition.

The verifier is intentionally pure: it does not authenticate the merchant, validate a quote signature, read balances/nonces, simulate, persist replay state, sponsor, broadcast, confirm, or deliver a resource. A hosted facilitator must perform those controls before using the verified plan. For origin-signed sponsored transactions the result omits transactionId until a sponsor adds its signature; transactionHash identifies only the supplied serialization.

NayoriX402PaymentClient completes the payer side without weakening those boundaries. It creates an immutable PaymentIntent, applies recipient/origin/asset and amount/fee limits, constructs the canonical unsigned transfer, delegates signing to LeatherSigner (broadcast: false) or a PolicySigner backed by external custody, and verifies the signed result before returning the exact facilitator request body. See docs/X402_PAYMENTS.md for both integrations.

Direct payments and perkos-escrow-v1 are complementary. Use direct payments for immediate resources and escrow for jobs that require delivery, evaluation, payout, or reputation.

MPP PaymentAuth with USDCx on Stacks

MPP is a separate standards-based commerce path beside x402. Nayori implements the official Payment HTTP authentication scheme with method="usdc", intent="charge" and the direct Stacks USDCx profile. The server issues a canonical WWW-Authenticate: Payment challenge and selects Payment-Authorization for the payment credential, leaving Authorization: Bearer available for OAuth.

import {
  createNayoriMppUsdcStacksChallenge,
  createNayoriMppUsdcStacksCredential,
  encodeNayoriMppCredentialHeader,
} from "@perkos/agent-sdk";

const { challenge, wwwAuthenticate } =
  await createNayoriMppUsdcStacksChallenge({
    quote: trustedUsdcxQuote,
    realm: "api.nayori.ai",
    description: "Nayori paid agent request",
  });

const credential = createNayoriMppUsdcStacksCredential({
  challenge,
  source: `stacks:2147483648:${payerAddress}`,
  transaction: walletSignedTransactionHex,
});

console.log(wwwAuthenticate);
console.log(encodeNayoriMppCredentialHeader(credential));

The verifier reuses Nayori's exact request-bound Stacks transaction checks and adds the MPP rules: RFC 8785 envelopes, CAIP-10 source, canonical official USDCx identity, OnChainOnly, standard single-signature authorization and low-s signing. Replay persistence, nonce/balance preflight, broadcast, confirmations, receipt delivery and merchant authentication remain hosted Platform responsibilities. See MPP payments for the complete flow and trust boundary.

The testnet registry follows Circle xReserve remote domain 10003 and the current canonical token ST2WK9SGBJ15RHZ33KK0KYVSXBEBHM1XDM8C96EC4.usdcx. Mainnet remains SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx.

x402 v2 Stacks facilitator

PerkOSX402Facilitator implements the official SchemeNetworkFacilitator interface. It reloads the transaction and events from Hiro, then matches the successful contract call, payer, commerce contract, decoded job-funded event, exact STX/sBTC transfer, job, amount, token, block metadata, confirmation depth, and payment-window freshness. Its settle method does not broadcast another transaction: for the upfront flow it atomically consumes the already-confirmed funding proof.

import { x402Facilitator } from "@x402/core/facilitator";
import {
  InMemoryX402ReplayStore,
  PerkOSX402Facilitator,
  STACKS_X402_NETWORKS,
} from "@perkos/agent-sdk";

const stacks = new PerkOSX402Facilitator({
  config: perkos.config,
  replayStore: new InMemoryX402ReplayStore(),
  minConfirmations: 2,
});
const facilitator = new x402Facilitator().register(
  STACKS_X402_NETWORKS.mainnet,
  stacks
);

The in-memory replay store is only for tests, examples, local development, and a single-process demo. Production must inject a durable shared implementation whose consume operation is atomic, such as a database unique constraint or Redis SET NX.

The current Stacks proof is an already-public funding transaction rather than a request-bound off-chain authorization. Freshness and one-time consumption prevent stale reuse, but a party that obtains the proof before settlement could try to consume it first. Do not use this release for a high-value production paywall until request binding is added through a payer signature/challenge or facilitator-submitted signed transaction.

Supported lifecycle

  • Register, update, and deactivate agents.
  • Read agent records and counts.
  • Create STX or sBTC jobs.
  • Set a budget and fund escrow.
  • Assign a provider and submit a deliverable.
  • Complete, reject, or expire a job.
  • Settle an overdue review to the provider with exact post-conditions.
  • Read and retry durable reputation synchronization.
  • Rate a provider and read reputation.

Private QA evidence

NayoriPrivateEvidenceClient implements the bounded private-evidence workflow used by the QA MCP: provider bytes are hashed locally, uploaded directly to Nayori's private versioned S3 bucket, and completed as an immutable evidence reference. OAuth is sent only to api.qa.nayori.ai, never S3. Consumers and the evaluator exchange the stable reference for a fresh, at-most-60-second download capability and verify the exact byte count and SHA-256 again.

The MCP flag --private-evidence-client /absolute/mode-600.json enables nayori_private_evidence_upload for the provider and nayori_private_evidence_read for both job roles. The file is the wallet-linked OAuth client returned during the one-time enrollment; it must have exactly the role's evidence scopes. It contains no wallet private key. Upload accepts only inline text/plain or application/json up to 8192 bytes, never filesystem paths. A temporary 503 is surfaced with bounded retry guidance; prepare is not automatically replayed.

This capability is QA/testnet-only until the independent production storage and operational gates are completed. Internal QA activity is not external M2 adoption.

Security model

  • Mainnet or testnet must be selected explicitly.
  • Contract overrides must match the selected network.
  • Funding uses exact sender post-conditions.
  • Settlement uses exact escrow-contract post-conditions.
  • Agent-controlled payments require transaction and session budgets.
  • The core SDK never accepts arbitrary URLs or payment destinations from an LLM.
  • execute refuses plans created for a different network or signer.
  • Broadcast receipts require a valid 32-byte Stacks transaction ID.
  • Automated workflows can wait for an explicit terminal confirmation before their next action.
  • x402 quotes are bound to the configured network, escrow contract, asset, job, and exact budget.
  • x402 settlement verifies current chain evidence and atomically consumes each funding txid once.
  • MPP USDCx credentials echo a request-bound challenge and require a canonical, low-s, OnChainOnly Stacks transfer; hosted settlement must still consume challenge and replay keys atomically before broadcast.
  • Partner OAuth enrollment signs an exact, short-lived, invitation-bound message in the wallet; the SDK normalizes the public signature but never receives a private key.
  • OAuth client secrets and access tokens are application secrets. The SDK returns them to the caller but does not persist, log or refresh them automatically.

The independent external security review remains open. Do not treat this release as audited software.

See Architecture, x402 payments, MPP payments, Partner pilot and Security for the trust boundaries and responsible disclosure process.

QA promotion

New integration work is reviewed in pull requests targeting qa; promotion to main is a separate reviewed release after QA verification. QA consumes an exact commit or tarball and never publishes npm as a side effect. Operator deployments are initiated from the approved Mac, with image builds on the VPS; do not assume GitHub-hosted runners can reach that server.

The repository also retains the historical Promote exact main commit to QA workflow. It accepts only a full SHA already in main and a fast-forward from qa. It is not the forward path for new QA-only changes: do not force or rewind branches to make it run. Branch protection and restricted GitHub Actions bypass remain required where that legacy workflow is used.

Development

npm install
npm run typecheck
npm test
npm run build

License

MIT