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

axis-protocol-sdk

v0.2.3

Published

Reference SDK for the AXIS protocol. Agent identity, signing, and registry operations. Zero runtime dependencies; runs in Node 20+, Cloudflare Workers, and modern browsers.

Readme

axis-protocol-sdk

Reference SDK for the AXIS protocol. Agent identity, signing, and registry operations in one small library. Zero runtime dependencies, ESM, runs in Node 20+, Cloudflare Workers, Deno, Bun, and modern browsers.

Status: v0.2.2 (the constant SDK_VERSION is derived from package.json so the two cannot drift). The protocol itself is v0.1.1 (Apache 2.0) at MachinesOfDesire/axis-protocol. Breaking changes are possible before v1. See CHANGELOG.md for release notes.


What this does

The AXIS reference registry is a small HTTP API. Anything that wants to use AXIS needs to know how to generate Ed25519 keypairs in the right format, sign AITs the registry will accept, verify tokens, register agents, and issue or revoke delegations. This SDK is the canonical client for all of that.

Without it, every consumer would re-implement the primitives (and do it slightly differently). With it, you write client.createAgent(...) and await session.sign() and the protocol stays consistent.

Properties

  • Zero runtime dependencies. Uses only crypto.subtle, fetch, TextEncoder, and base64 helpers. All built-in in every target runtime.
  • Universal. Same source runs in Node 20+, Cloudflare Workers, Deno, Bun, and modern browsers.
  • ESM-only. No CommonJS shim, no transpilation.
  • Small. Under 1000 lines of hand-written source.

Install

npm install axis-protocol-sdk

Or, before publication, point at a local checkout:

npm install /path/to/axis-protocol-sdk

Quick tour

Verify an AIT (public, no auth)

import { AxisClient } from "axis-protocol-sdk";

const client = new AxisClient({ registryUrl: "https://registry.axisprime.ai" });

const result = await client.verifyAIT(tokenFromIncomingRequest);
if (!result.valid) {
  throw new Error(`Invalid token: ${result.error}`);
}
console.log(result.agent_id, result.operator_id, result.status, result.expires_at);

Register an agent and sign tokens

import { AxisClient } from "axis-protocol-sdk";

const registrar = new AxisClient({
  registryUrl: "https://registry.axisprime.ai",
  apiKey: process.env.AXIS_REGISTRAR_KEY,
});

// Generate a keypair, register, and get a session with a sign() helper.
const session = await registrar.createAgent({
  operator: { email: "[email protected]" },
  metadata: { name: "Mira", description: "Managing editor for Offworld News" },
});

console.log("agent_id:", session.agent_id);
console.log("did:", session.did);

// Sign a short-lived AIT with an application claim.
const ait = await session.sign({ ttl: 300, claims: { act: "publish" } });

Verify locally without hitting the registry

import { verifyAITLocally } from "axis-protocol-sdk";

const { valid, payload } = await verifyAITLocally(token, knownPublicKeyB64, {
  audience: "your-platform-id",     // require token.aud to match (recommended)
  expectedKid: "axis:op:agent",     // require header.kid to match (recommended)
  // requireExp: true,              // default — reject tokens without exp
  // clockSkew: 30,                 // default — seconds of tolerance on exp/iat/nbf
});
if (valid) console.log("Issued by:", payload.iss);

Use this when you already have the agent's public key from a trusted local source. For anything public-facing, prefer client.verifyAIT(), which consults the registry (the canonical source of truth in AXIS v0.1).

The third options argument was added in v0.2.2; existing 0.2.1 callers (verifyAITLocally(token, key)) keep working unchanged. See CHANGELOG.md for the full migration note.

Client API, by role

The same AxisClient handles every role of caller. If the API key is missing or insufficient for a given endpoint, the server returns 401 / 403 and the SDK throws an AxisError with a stable code.

Public (no apiKey needed)

| Method | Endpoint | |---|---| | getAccessPolicy() | GET /.well-known/axis-access | | resolveAgent(id) | GET /agents/:id | | resolveDid(did) | GET /resolve/:did | | getOperator(id) | GET /operators/:id | | verifyAIT(token) | GET /verify?token= | | verifyDid(did) | GET /verify/:did | | verifySignature(opts) | POST /verify/signature | | checkRevocation(id) | GET /revocation/:id | | getDelegation(id) | GET /delegations/:id | | verifyDelegationChain(id) | GET /delegations/:id/chain |

Registrar (apiKey required)

| Method | Endpoint | |---|---| | registerAgent({operator, publicKey, metadata, service, proof}) | POST /register | | deactivateAgent(id, {reason}) | DELETE /agents/:id | | listAgents({operator_id}) | GET /agents?operator_id= | | createDelegation({issued_by, issued_to, root_operator, scope, expires, constraints?, parent_credential_id?, signature?}) | POST /delegations | | revokeDelegation(id, {reason}) | DELETE /delegations/:id | | verifyDomain({email, domain, method}) | POST /operators/verify-domain | | checkDomain({domain, token}) | POST /operators/verify-domain/check | | createAgent({operator, metadata, service}) | POST /register (convenience: keypair + register + sign helper) |

Admin / super-admin (role enforced server-side)

| Method | Endpoint | Role | |---|---|---| | adminListOperators({limit, offset}) | GET /admin/operators | admin+ | | adminGetAgent(id) | GET /admin/agents/:id | admin+ | | adminListAgents({limit, offset, status}) | GET /admin/agents | admin+ | | adminAudit({limit, offset}) | GET /admin/audit | admin+ | | adminStats() | GET /admin/stats | admin+ | | forceDeactivateAgent(id, {reason}) | POST /admin/force-deactivate-agent/:id | super_admin | | forceRevokeDelegation(id, {reason}) | POST /admin/force-revoke-delegation/:id | super_admin |

Break-glass endpoints require a non-empty reason string. The registry writes an audit row before the mutation and aborts if the audit write fails.

Error handling

Every call that touches the registry throws AxisError on failure, except verifyAIT() which returns {valid: false, error} for invalid tokens (so the common case does not need a try/catch around a known-bad token).

import { AxisError, ERR } from "axis-protocol-sdk";

try {
  await client.deactivateAgent("axis:other-operator:bot");
} catch (err) {
  if (err instanceof AxisError && err.code === ERR.NOT_YOUR_RESOURCE) {
    console.log("That agent belongs to a different registrar");
  } else {
    throw err;
  }
}

Stable error codes on err.code:

  • REGISTRY_UNREACHABLE, REGISTRY_HTTP — transport
  • API_KEY_REQUIRED, UNAUTHORIZED, FORBIDDEN, INSUFFICIENT_ROLE, NOT_YOUR_RESOURCE — auth / authorization
  • INVALID_INPUT, NOT_FOUND, CONFLICT — request state
  • AIT_INVALID, AIT_EXPIRED — token state
  • AGENT_NOT_FOUND, AGENT_REVOKED — agent state

Crypto helpers

Exported from the top level, usable standalone:

import {
  generateKeypair,       // {publicKey, privateKey, publicKeyB64, privateKeyJwk}
  signAIT,               // builds a compact JWT-encoded AIT
  decodeAIT,             // parses without verifying
  verifyAITLocally,      // verifies against a known public key
  importPrivateKey,      // JWK -> CryptoKey
  importPublicKey,       // base64url raw -> CryptoKey
  canonicalize,          // object -> canonical JSON (sorted top-level keys)
  signCanonical,         // sign a canonical-encoded object (used for register proof)
} from "axis-protocol-sdk";

Examples

See examples/:

Development

npm test        # runs all unit tests

No build step. The source IS the published artifact.

License

Apache 2.0. See LICENSE. See NOTICE for attribution and trademarks.

Governance

axis-protocol-sdk is owned and maintained by Kipple Labs, Inc. Stewardship of the AXIS Protocol project (spec, SDK, conformance) may transition to an independent nonprofit foundation at a future date when adoption justifies it; ownership of copyright and trademarks remains with Kipple Labs, Inc. regardless. See CONTRIBUTING.md for the contributor license terms.


Copyright 2026 Kipple Labs, Inc. "AXIS," "AXIS Protocol," "AXIS Prime," "N7," and "Kipple Labs" are trademarks of Kipple Labs, Inc.