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

@noxy-network/node-sdk

v2.2.0

Published

Decision Layer SDK for AI agents. Encrypted actionable decisions over gRPC.

Readme

@noxy-network/node-sdk

SDK for AI agent backends integrating with Noxy human-in-the-loop guardrails: send encrypted, actionable prompts (tool proposals, approvals, next-step hints) to registered user devices over gRPC so users can take decisions before work proceeds.

Before you integrate: Create your app at noxy.network. When the app is created, you receive an app id and an app token (auth token). This Node SDK authenticates with the relay using the app token (authToken in the client config). The app id is used by client SDKs (browser, iOS, Android, Telegram bot), not as the bearer token here.

Overview

Use this SDK to:

  • Route decisions to devices bound to a logical identity (identity_id on the relay) — whichever form your app uses when users register devices, e.g. Web3 wallet (0x…), email, phone (E.164-style), user_id, or another stable string — plus structured JSON you define (tool proposals, parameters, summaries).
  • Receive delivery outcomes from the relay (DELIVERED, QUEUED, NO_DEVICES, etc.) plus a decision_id when the relay accepts the route.
  • Wait for human-in-the-loop resolutionusers take decisions on-device and decision outcomes return via polling; prompts can expire if unanswered. The usual path is sendDecisionAndWaitForOutcome (route + poll in one step). Use getDecisionOutcome / waitForDecisionOutcome alone for finer control.
  • Query quota for your agent application on the relay.
  • Resolve identity devices so each device receives its own encrypted copy of the decision.

The wire API uses agent.proto (noxy.agent.AgentService): RouteDecision, GetDecisionOutcome, GetQuota, GetIdentityDevices.

Communication is gRPC over TLS with Bearer authentication. Payloads are encrypted end-to-end (Kyber + AES-256-GCM) per device before leaving your process; the relay sees ciphertext only.

Architecture

The encrypted path covers SDK → relay and relay → device: decision content is ciphertext on both hops; the relay forwards without decrypting.

                      Ciphertext only (E2E)                  Ciphertext only (E2E)
┌──────────────────┐     gRPC (TLS)      ┌─────────────────┐     gRPC (TLS), WSS  ┌──────────────────┐
│  AI agent /      │ ◄─────────────────► │  Noxy relay     │ ◄──────────────────► │  User device     │
│  orchestrator    │   RouteDecision     │  human-in-the-  │                      │  (users take     │
│  (this SDK)      │   GetDecisionOutcome│  loop relay     │                      │   decisions)     │
│                  │   GetQuota          │   forwards only │                      │   decrypts       │
│                  │   GetIdentityDevices│                 │                      │                  │
└──────────────────┘                     └─────────────────┘                      └──────────────────┘

Requirements

  • Node.js >= 22
  • ESM ("type": "module")

Installation

npm install @noxy-network/node-sdk
# or
pnpm add @noxy-network/node-sdk

Quick start

Route encrypted prompts and wait until users take decisions or the prompt expires (one call):

import { initNoxyAgentClient, NoxyHumanDecisionOutcome } from '@noxy-network/node-sdk';

const client = await initNoxyAgentClient({
  endpoint: 'https://relay.noxy.network',
  authToken: 'your-api-token',
  decisionTtlSeconds: 3600,
});

const identity =
  '0xaabb...'; // or e.g. 'user_42', '+15555550100', '[email protected]' — match how devices are linked in your Noxy app

const resolution = await client.sendDecisionAndWaitForOutcome(identity, {
  kind: 'propose_tool_call',
  tool: 'transfer_funds',
  args: { to: '0x000000000000000000000000000000000000dEaD', amountWei: '1' },
  title: 'Transfer 1 wei to the burn address',
  summary: 'The agent is requesting approval to send 1 wei to the burn address.',
});

if (resolution.outcome === NoxyHumanDecisionOutcome.APPROVED) {
  // run the proposed action
} else {
  // REJECTED, EXPIRED, or non-approved — do not run the action (optionally branch on outcome)
}

resolution.outcome is always a NoxyHumanDecisionOutcome (normalized from the relay: string enums from gRPC are mapped to 03). APPROVED → continue; anything else → stop or fallback. Use isTerminalHumanOutcome(outcome) for “finalized vs still pending”; for one-off getDecisionOutcome polls, also read pending.

Configuration

| Option | Type | Required | Description | |--------|------|----------|-------------| | endpoint | string | Yes | Relay gRPC endpoint (e.g. https://relay.noxy.network). https:// is stripped; TLS is used. | | authToken | string | Yes | Bearer token for relay auth (Authorization header). | | decisionTtlSeconds | number | Yes | TTL for routed decisions (seconds). |

SendDecisionAndWaitOptions

Optional third argument to sendDecisionAndWaitForOutcome

| Option | Type | Required | Description | |--------|------|----------|-------------| | initialPollIntervalMs | number | No | Delay after the first poll before the next attempt (ms). Default 400. | | maxPollIntervalMs | number | No | Maximum delay between polls (ms). Default 30000. | | maxWaitMs | number | No | Total time budget for polling (ms). Default 900000 (15 minutes). Exceeded → WaitForDecisionOutcomeTimeoutError. | | backoffMultiplier | number | No | Multiplier applied to the poll interval after each attempt. Default 1.6. | | signal | AbortSignal | No | When aborted, polling stops with an AbortError. |

API

initNoxyAgentClient(config): Promise<NoxyAgentClient>

Async init (loads Kyber WASM for post-quantum encapsulation).

NoxyAgentClient

sendDecision(identityId, actionableDecision): Promise<NoxyDeliveryOutcome[]>

Routes an encrypted decision to every device registered for the identity_id (wallet, email, phone, user_id, etc.—must match relay/device registration).

  • Returns per device: relay status (DELIVERED, QUEUED, NO_DEVICES, …), request_id, and decision_id when the relay can track human resolution (use with GetDecisionOutcome).

getDecisionOutcome({ decisionId, identityId })

Single poll for human-in-the-loop state (pending + outcome). identityId is the same logical identity string you passed to sendDecision.

sendDecisionAndWaitForOutcome(identityId, actionableDecision, options?)

Runs sendDecision, then waitForDecisionOutcome using the first delivery that has a non-empty decision_id. Polling uses the same identityId as routing. Optional options is SendDecisionAndWaitOptions (same as WaitForDecisionOutcomeOptions without decisionId or identityId — e.g. maxWaitMs, backoff, signal).

  • Returns NoxyGetDecisionOutcomeResponse (same as waitForDecisionOutcome). Throws SendDecisionAndWaitNoDecisionIdError if no decision_id was returned.

waitForDecisionOutcome(options)

Polls with exponential backoff (configurable initialPollIntervalMs, maxPollIntervalMs, backoffMultiplier) until:

  • outcome is APPROVED, REJECTED, or EXPIRED, or
  • pending becomes false, or
  • maxWaitMs is exceeded → throws WaitForDecisionOutcomeTimeoutError.

Options: decisionId, identityId, initialPollIntervalMs (default 400), maxPollIntervalMs (default 30000), maxWaitMs (default 900000), backoffMultiplier (default 1.6), optional AbortSignal.

getQuota(): Promise<NoxyGetQuotaResponse>

Quota usage for the application.

Lower-level helpers (also exported)

  • waitForDecisionOutcome(fetch, options) — pass your own GetDecisionOutcome caller if needed.
  • parseHumanDecisionOutcome, isTerminalHumanOutcome
  • WaitForDecisionOutcomeTimeoutError

Types

  • NoxyIdentityId: Logical identity string (wallet, email, phone, application user_id, … — same convention as relay identity_id).
  • NoxyDeliveryStatus: DELIVERED | QUEUED | NO_DEVICES | REJECTED | ERROR
  • NoxyHumanDecisionOutcome: PENDING | APPROVED | REJECTED | EXPIRED
  • NoxyQuotaStatus: QUOTA_ACTIVE | QUOTA_SUSPENDED | QUOTA_DELETED

Encryption (summary)

  1. Kyber768 encapsulation per device pq_public_key.
  2. HKDF-SHA256 → AES-256-GCM key; random 12-byte nonce.
  3. JSON payload encrypted; only kyber_ct, nonce, ciphertext cross the relay.

Development

pnpm install
pnpm run build
pnpm run typecheck
pnpm run test

License

MIT