JavaScript / TypeScript SDK
@agentsecretstore/sdk — TypeScript-first SDK for Node.js 18+ and modern runtimes.
Installation
npm install @agentsecretstore/sdk
# or
yarn add @agentsecretstore/sdk
# or
pnpm add @agentsecretstore/sdkEnvironment setup
# .env (local dev only — never commit!)
ASS_AGENT_KEY=ass_live_your_key_hereProduction: 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
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>
// ── 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>
// ── 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 }>
// ── 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>
// ── 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>
// ── 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 expiresdeleteSecret(path, options?)
deleteSecret(path: string, options?: DeleteOptions): Promise<void>
// ── 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.
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
// ── 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.