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

@agently-org/sdk

v1.2.0

Published

A fully-typed TypeScript SDK for SaaS applications to securely encrypt and send authentication tokens to Agently

Readme

Agently SDK

A fully-typed TypeScript SDK for encrypting authentication tokens and securely sending them to Agently. Uses JWS (JSON Web Signature) and JWE (JSON Web Encryption) for maximum security.

Features

Fully Typed - Complete TypeScript support with comprehensive type definitions

🔐 Secure - Industry-standard JWS/JWE for signing and encryption

🎯 Simple API - Just 3 lines of code to authenticate users

🚀 One-Step Authentication - Built-in encryption and HTTP sending

🛡️ Token Validation - Built-in token validation and expiration checking

📦 Zero Config - Sensible defaults with full customization options

Installation

npm install @agently-org/sdk

Quick Start

import { AgentlyAuth } from "@agently-org/sdk";

const auth = new AgentlyAuth({
  signingPrivateKey: process.env.SIGNING_PRIVATE_KEY!,
  signingPublicKey: process.env.SIGNING_PUBLIC_KEY!,
  agentlyPublicKey: process.env.AGENTLY_PUBLIC_KEY!,
  agentId: process.env.AGENTLY_AGENT_ID!,
});

const tokens = [
  {
    name: "Authorization",
    value: "your-token-value",
    exp: Math.floor(Date.now() / 1000) + 3600,
    location: "header",
    format: "Bearer {token}",
  },
];

// Authenticate user with one call (link code auto-generated)
await auth.authenticateUser({
  context: {
    identifier: "user123",
    email: "[email protected]",
    username: "johndoe",
  },
  tokens,
});

That's it! The SDK encrypts the tokens and sends them securely to Agently. 🎉

How It Works

The SDK performs two security operations before sending to Agently:

  1. JWS (Signing): Signs the payload with your SaaS private key
  2. JWE (Encryption): Encrypts the signed payload with Agently's public key
[Tokens] → Sign with Your Private Key → [JWS] → Encrypt with Agently Public Key → [JWE] → Send to Agently

Only Agently can decrypt it (with their private key), and they can verify it came from you (with your public key).

Setup

Set Environment Variables

All keys are provided by Agently - you don't need to generate any keys yourself.

# .env file - All values provided by Agently
SIGNING_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"  # Provided by Agently
SIGNING_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"    # Provided by Agently
AGENTLY_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"    # Provided by Agently
AGENTLY_AGENT_ID="your-agent-id"                                                    # Provided by Agently

3. Use It!

See the Quick Start above.

API Reference

AgentlyAuth

The main class for encrypting and authenticating users with Agently.

Constructor

new AgentlyAuth(config: AuthConfig)

AuthConfig:

| Property | Type | Required | Default | Description | | ---------------------------- | -------- | -------- | ---------------- | ------------------------------------------------- | | signingPrivateKey | string | ✓ | - | SaaS private key (PKCS#8) - Provided by Agently | | signingPublicKey | string | ✓ | - | SaaS public key (SPKI) - Provided by Agently | | agentlyPublicKey | string | ✓ | - | Agently's public key (SPKI) - Provided by Agently | | agentId | string | ✓ | - | Agent ID - Provided by Agently | | expirationTime | string | ✗ | '5m' | JWT expiration time | | signingAlgorithm | string | ✗ | 'RS256' | Signing algorithm | | encryptionAlgorithm | string | ✗ | 'RSA-OAEP-256' | Encryption algorithm | | contentEncryptionAlgorithm | string | ✗ | 'A256GCM' | Content encryption |

Methods

authenticateUser(input: Omit<AuthInput, 'linkCode'>): Promise<AuthResult>

Authenticates a user by automatically generating a link code, encrypting and sending their tokens to Agently. This is the recommended method.

const result = await auth.authenticateUser({
  context: {
    identifier: "user123",
    email: "[email protected]",
    username: "johndoe",
  },
  tokens,
  // linkCode is automatically generated
});

if (result.success) {
  console.log("User authenticated!", result.status);
  console.log("Session ID:", result.sessionId);
} else {
  console.error("Authentication failed:", result.error);
}

authenticateUserWithCode(input: AuthInput): Promise<AuthResult>

Authenticates a user with a provided link code. Use this method when you have a specific link code to use.

const result = await auth.authenticateUserWithCode({
  context: {
    identifier: "user123",
    email: "[email protected]",
    username: "johndoe",
  },
  tokens,
  linkCode: "link-code-123", // Must provide linkCode
});

if (result.success) {
  console.log("User authenticated!", result.status);
} else {
  console.error("Authentication failed:", result.error);
}

encryptPayload(input: AuthInput): Promise<EncryptionResult>

Encrypts a payload and returns detailed result with metadata. Use this if you want to send the JWE yourself.

const result = await auth.encryptPayload({
  context: {
    identifier: "user123",
    email: "[email protected]",
    username: "johndoe",
  },
  tokens,
  linkCode: "link-code-123",
});

if (result.success) {
  console.log("JTI:", result.metadata?.jti);
  console.log("JWE:", result.jwe);

  // Send JWE yourself if needed
  await fetch("https://api.agently.best/client/auth/your-agent-id", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jwe: result.jwe }),
  });
}

Types

Context

The Context interface provides a flexible way to identify users and include additional metadata:

interface Context {
  identifier: string; // unique and mandatory - primary user reference
  [x: string]: any; // additional metadata about the user
}

Properties:

  • identifier (required): Unique identifier for the user (userId, email, username, etc.)
  • [x: string] (optional): Additional metadata about the user (role, department, etc.)

Examples:

// Simple user identification
const context: Context = {
  identifier: "user_12345",
};

// With additional metadata
const context: Context = {
  identifier: "user_12345",
  email: "[email protected]",
  username: "johndoe",
  role: "admin",
  department: "engineering",
};

// Using email as identifier
const context: Context = {
  identifier: "[email protected]",
  username: "johndoe",
  role: "user",
};

AgentlyToken

interface AgentlyToken {
  name: string; // Token name - for headers: 'Authorization', 'X-xsrf-token', etc. For cookies: cookie name
  value: string; // Token value
  exp: number; // Expiration (Unix timestamp in seconds)
  location: "header" | "cookie"; // Where to store
  format: TokenFormatTemplate; // Format template that must contain {token} placeholder
}

Example:

const token: AgentlyToken = {
  name: "Authorization", // HTTP header name
  value: "eyJhbGc...",
  exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour
  location: "header",
  format: "Bearer {token}", // Must contain {token} placeholder
};

Format Template Requirements:

The format property must contain the {token} placeholder string. This ensures proper token substitution when the token is used. Common examples:

  • "Bearer {token}" - For Authorization headers
  • "jwt {token}" - For JWT tokens
  • "{token}" - For raw token values
  • "Token {token}" - For custom token formats

Utility Functions

Token Validation

Validate tokens before sending:

import { validateTokens, filterExpiredTokens } from "@agently-org/sdk";

// Validate all tokens
const validation = validateTokens(tokens);
if (!validation.valid) {
  console.error("Invalid tokens:", validation.errors);
}

// Filter expired tokens
const { valid, expired } = filterExpiredTokens(tokens);
console.log(`${valid.length} valid, ${expired.length} expired`);

// Check tokens expiring soon
import { hasTokensExpiringSoon } from "@agently-org/sdk";
const expiringSoon = hasTokensExpiringSoon(tokens, 300); // 5 minutes
if (expiringSoon.expiringSoon) {
  console.warn("Some tokens expire soon!");
}

Complete Example

import { AgentlyAuth, AgentlyToken, validateTokens } from "@agently-org/sdk";

async function authenticateWithAgently() {
  // 1. Initialize auth client
  const auth = new AgentlyAuth({
    signingPrivateKey: process.env.SIGNING_PRIVATE_KEY!,
    signingPublicKey: process.env.SIGNING_PUBLIC_KEY!,
    agentlyPublicKey: process.env.AGENTLY_PUBLIC_KEY!,
    agentId: process.env.AGENTLY_AGENT_ID!, // Provided by Agently
  });

  // 2. Prepare tokens
  const tokens: AgentlyToken[] = [
    {
      name: "Authorization",
      value: "eyJhbGc...",
      exp: Math.floor(Date.now() / 1000) + 3600,
      location: "header",
      format: "Bearer {token}",
    },
    {
      name: "X-xsrf-token",
      value: "xsrf_token_value",
      exp: Math.floor(Date.now() / 1000) + 3600,
      location: "header",
      format: "{token}",
    },
    {
      name: "session_id",
      value: "sess_abc123",
      exp: Math.floor(Date.now() / 1000) + 86400,
      location: "cookie",
      format: "jwt {token}",
    },
  ];

  // 3. Validate tokens (optional but recommended)
  const validation = validateTokens(tokens);
  if (!validation.valid) {
    throw new Error("Invalid tokens: " + validation.errors.join(", "));
  }

  // 4. Authenticate user with Agently (link code auto-generated)
  const result = await auth.authenticateUser({
    context: {
      identifier: "user123",
      email: "[email protected]",
      username: "johndoe",
      role: "admin",
    },
    tokens,
    // linkCode is automatically generated
  });

  if (result.success) {
    console.log("✓ User authenticated successfully!");
    console.log("Status:", result.status);
    console.log("Session ID:", result.sessionId);
  } else {
    console.error("✗ Authentication failed:", result.error);
  }
}

Error Handling

import {
  EncryptionError,
  ConfigurationError,
  TokenExpiredError,
} from "@agently-org/sdk";

try {
  await auth.authenticateUser({
    context: {
      identifier: "user123",
      email: "[email protected]",
      username: "johndoe",
    },
    tokens,
    // linkCode is automatically generated
  });
} catch (error) {
  if (error instanceof ConfigurationError) {
    console.error("Config error:", error.message);
  } else if (error instanceof EncryptionError) {
    console.error("Encryption failed:", error.message);
  } else if (error instanceof TokenExpiredError) {
    console.error("Token expired:", error.details);
  }
}

TypeScript Support

Full TypeScript support with strict mode enabled:

const auth = new AgentlyAuth(config);
//    ^? AgentlyAuth

const result = await auth.authenticateUser({
  context: {
    identifier: "user123",
    email: "[email protected]",
    username: "johndoe",
  },
  tokens,
  // linkCode is automatically generated
});
//    ^? { success: boolean; status?: number; sessionId?: string; ... }

Your IDE will provide complete autocomplete and type checking!

Security Best Practices

  1. Never commit private keys to version control
  2. Use environment variables for all keys
  3. Rotate keys regularly in production
  4. Validate tokens before sending
  5. Check expiration to ensure tokens are valid
  6. Use HTTPS always (handled automatically by the SDK)
  7. Set appropriate expiration times for JWTs (default: 5 minutes)

License

MIT


Made with ❤️ for secure authentication