Agent Secret Store DocsSign up
🌐 SDKs

JavaScript / TypeScript SDK

@agentsecretstore/sdk — TypeScript-first SDK for Node.js 18+ and modern runtimes.

Installation

Shell
npm install @agentsecretstore/sdk
# or
yarn add @agentsecretstore/sdk
# or
pnpm add @agentsecretstore/sdk

Environment setup

Shell
# .env (local dev only — never commit!)
ASS_AGENT_KEY=ass_live_your_key_here

Production: use your secrets manager

In production, inject ASS_AGENT_KEY via your CI/CD platform's secret management (GitHub Actions Secrets, AWS Secrets Manager, GCP Secret Manager, etc.). Never commit it to source control.

Constructor

vault.ts
import { AgentVault } from '@agentsecretstore/sdk';

// Reads ASS_AGENT_KEY from process.env automatically
const vault = new AgentVault();

// Or provide the key explicitly (for testing / multi-tenant apps)
const vault2 = new AgentVault({
  agentKey: 'ass_live_your_key_here',
  baseUrl: 'https://api.agentsecretstore.com/v1', // default
  timeoutMs: 10_000,                              // default: 10s
  retries: 3,                                     // default: 3
});

getSecret(path, options?)

getSecret(path: string, options?: GetSecretOptions): Promise<Secret>

TypeScript
// ── getSecret ───────────────────────────────────────────────
// Retrieves a secret value by path.

const secret = await vault.getSecret('production/openai/api-key');

console.log(secret.value);      // "sk-proj-abc123..."
console.log(secret.version);    // 1
console.log(secret.path);       // "production/openai/api-key"
console.log(secret.tier);       // "sensitive"
console.log(secret.accessedAt); // Date object

// With options
const secret2 = await vault.getSecret('production/stripe/api-key', {
  version: 2,           // Fetch a specific version (default: latest)
  token: 'ast_tok_...', // Use a scoped token instead of master key
});

setSecret(path, value, options?)

setSecret(path: string, value: string, options?: SetSecretOptions): Promise<void>

TypeScript
// ── setSecret ───────────────────────────────────────────────
// Creates or updates a secret.

await vault.setSecret('production/openai/api-key', 'sk-proj-abc123...', {
  tier: 'sensitive',                    // 'standard' | 'sensitive' | 'critical'
  description: 'OpenAI production key',
  tags: { team: 'ml', env: 'prod' },    // Optional key-value metadata
  expiresAt: new Date('2025-12-31'),    // Optional secret expiry
});

// Minimal – just path + value (tier defaults to 'standard')
await vault.setSecret('staging/config/feature-flag', 'true');

listSecrets(namespace, options?)

listSecrets(namespace: string, options?: ListOptions): Promise<{ items: SecretMetadata[]; nextCursor?: string }>

TypeScript
// ── listSecrets ─────────────────────────────────────────────
// Lists secrets in a namespace (values not included).

const result = await vault.listSecrets('production/openai', {
  limit: 50,       // Max per page (default: 50, max: 200)
  cursor: undefined,
});

for (const item of result.items) {
  console.log(item.path);        // "production/openai/api-key"
  console.log(item.tier);        // "sensitive"
  console.log(item.version);     // 3
  console.log(item.updatedAt);   // Date
}

// Paginate
if (result.nextCursor) {
  const page2 = await vault.listSecrets('production/openai', {
    cursor: result.nextCursor,
  });
}

requestToken(options)

requestToken(options: TokenOptions): Promise<ScopedToken>

TypeScript
// ── requestToken ─────────────────────────────────────────────
// Issues a scoped, short-lived token.

const token = await vault.requestToken({
  scope: 'secrets:read:production/openai/*',
  ttlSeconds: 3600,               // 1 hour
  description: 'Inference agent', // Appears in audit log
  allowedIps: ['10.0.1.50'],      // Optional IP allowlist
  maxUses: null,                  // null = unlimited within TTL; 1 = single-use
});

console.log(token.value);          // "ast_tok_..."
console.log(token.scope);          // "secrets:read:production/openai/*"
console.log(token.expiresAt);      // Date
console.log(token.approvalStatus); // "approved" | "pending"

// If pending, wait for approval (dev/test only — use webhooks in prod)
if (token.approvalStatus === 'pending') {
  const approved = await vault.waitForApproval(token.approvalRequestId!, {
    timeoutMs: 120_000,
  });
}

rotateSecret(path, newValue, options?)

rotateSecret(path: string, newValue: string, options?: RotateOptions): Promise<RotateResult>

TypeScript
// ── rotateSecret ─────────────────────────────────────────────
// Rotate to a new value; previous version remains readable for
// a configurable window to allow graceful cutover.

const result = await vault.rotateSecret(
  'production/openai/api-key',
  'sk-proj-newvalue456...',
  {
    gracePeriodSeconds: 300, // Old version readable for 5 min (default: 0)
  }
);

console.log(result.newVersion); // 2
console.log(result.oldVersion); // 1 (still readable for 5 min)
console.log(result.expiresAt);  // when old version expires

deleteSecret(path, options?)

deleteSecret(path: string, options?: DeleteOptions): Promise<void>

TypeScript
// ── deleteSecret ─────────────────────────────────────────────
// Soft-delete (moves to trash, recoverable for 30 days).

await vault.deleteSecret('staging/openai/test-key');

// Hard-delete (permanent, no recovery)
await vault.deleteSecret('staging/openai/test-key', { permanent: true });

Error handling

All SDK methods throw typed errors. Always wrap vault calls in try/catch and handle each error type explicitly.

errorHandling.ts
import {
  AgentVaultError,
  AgentVaultAuthError,
  AgentVaultPermissionError,
  AgentVaultNotFoundError,
  AgentVaultRateLimitError,
  AgentVaultApprovalPendingError,
  AgentVaultNetworkError,
} from '@agentsecretstore/sdk';

try {
  const secret = await vault.getSecret('production/stripe/api-key');
} catch (err) {
  if (err instanceof AgentVaultAuthError) {
    // 401: Invalid or expired agent key / token
    console.error('Auth failed:', err.message);
  } else if (err instanceof AgentVaultPermissionError) {
    // 403: Valid token, but scope doesn't cover this path
    console.error('Scope violation:', err.path, err.requiredScope);
  } else if (err instanceof AgentVaultNotFoundError) {
    // 404: Secret path doesn't exist
    console.error('Secret not found:', err.path);
  } else if (err instanceof AgentVaultApprovalPendingError) {
    // 202: Secret requires approval before token can be issued
    console.log('Pending approval ID:', err.approvalRequestId);
  } else if (err instanceof AgentVaultRateLimitError) {
    // 429: Too many requests
    console.log('Retry after:', err.retryAfter, 'seconds');
  } else if (err instanceof AgentVaultNetworkError) {
    // Network timeout or connectivity issue
    console.error('Network error:', err.cause);
  } else if (err instanceof AgentVaultError) {
    // Base class for all SDK errors
    console.error('Vault error:', err.message, err.code, err.statusCode);
  }
}

TypeScript types

types.ts
// ── TypeScript types reference ──────────────────────────────

type SecretTier = 'standard' | 'sensitive' | 'critical';

interface Secret {
  path: string;
  value: string;
  version: number;
  tier: SecretTier;
  description: string | null;
  tags: Record<string, string>;
  createdAt: Date;
  updatedAt: Date;
  accessedAt: Date;
  expiresAt: Date | null;
}

interface SecretMetadata extends Omit<Secret, 'value'> {}

interface ScopedToken {
  value: string;           // "ast_tok_..."
  scope: string;           // "secrets:read:production/*"
  ttlSeconds: number;
  expiresAt: Date;
  description: string | null;
  allowedIps: string[] | null;
  maxUses: number | null;
  approvalStatus: 'approved' | 'pending' | 'denied';
  approvalRequestId: string | null;
}

interface AgentVaultOptions {
  agentKey?: string;       // Defaults to process.env.ASS_AGENT_KEY
  baseUrl?: string;        // Defaults to https://api.agentsecretstore.com/v1
  timeoutMs?: number;      // Default: 10000
  retries?: number;        // Default: 3
  retryDelay?: number;     // Default: 500 (ms, exponential backoff)
}

Node.js version

Requires Node.js 18+ for the native fetch API. If you're on Node.js 16, install node-fetch and import it before the SDK, or polyfill globalThis.fetch.

Python SDK

Async-native Python client with identical API surface.

REST API

Raw HTTP endpoints — integrate from any language.