Files
sentryagent-idp/sdk
SentryAgent.ai Developer aa5167835e feat: Phase 1 P1 — Dockerfile, AGNTCY alignment docs, Node.js SDK
Three remaining Phase 1 P1 deliverables:

1. Dockerfile — multi-stage build (builder + production), node:18-alpine,
   non-root USER node, .dockerignore excluding secrets and dev artifacts

2. AGNTCY alignment docs (docs/agntcy/) — README and alignment.md mapping
   all 6 AGNTCY domains to AgentIdP features with Phase 2/3 pending items noted

3. Node.js SDK (@sentryagent/idp-sdk) — TypeScript strict, zero any, native
   fetch (Node 18+), TokenManager with 60s auto-refresh, service clients for
   all 14 endpoints (agents, credentials, tokens, audit), AgentIdPError typed
   error hierarchy, full README

All three changes tracked under openspec/changes/ with tasks marked complete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 14:46:53 +00:00
..

@sentryagent/idp-sdk

Node.js SDK for the SentryAgent.ai AgentIdP — the open-source Identity Provider for AI agents.

Handles token acquisition and caching automatically. Covers all 14 AgentIdP API endpoints.


Requirements

  • Node.js 18 or later (uses native fetch)
  • A running AgentIdP server
  • A registered agent with a valid clientId and clientSecret

Installation

npm install @sentryagent/idp-sdk

Quick start

import { AgentIdPClient } from '@sentryagent/idp-sdk';

const client = new AgentIdPClient({
  baseUrl: 'http://localhost:3000',
  clientId: 'your-agent-id',       // the agent's agentId (UUID)
  clientSecret: 'your-client-secret',
});

// List agents — token is acquired and cached automatically
const { data: agents } = await client.agents.listAgents();
console.log(agents);

Configuration

const client = new AgentIdPClient({
  baseUrl: 'http://localhost:3000',
  clientId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  clientSecret: 'your-client-secret',
  // Optional: restrict scopes. Defaults to all four scopes.
  scopes: ['agents:read', 'tokens:read'],
});
Option Required Description
baseUrl Yes Base URL of the AgentIdP server
clientId Yes The agent's agentId (UUID)
clientSecret Yes The credential secret
scopes No OAuth 2.0 scopes to request. Defaults to all four.

Token management

The SDK fetches and caches access tokens automatically. A new token is requested when the cached token is within 60 seconds of expiry.

// Force a fresh token on the next request (e.g. after rotating credentials)
client.clearTokenCache();

Agent Registry

// Register a new agent
const agent = await client.agents.registerAgent({
  email: 'classifier-v2@myorg.ai',
  agentType: 'classifier',
  version: '2.0.0',
  capabilities: ['text-classification', 'sentiment-analysis'],
  owner: 'platform-team',
  deploymentEnv: 'production',
});
console.log(agent.agentId); // UUID assigned by AgentIdP

// List agents
const { data, total } = await client.agents.listAgents({ status: 'active', limit: 20 });

// Get a single agent
const agent = await client.agents.getAgent('a1b2c3d4-...');

// Update an agent
const updated = await client.agents.updateAgent('a1b2c3d4-...', {
  version: '2.1.0',
  capabilities: ['text-classification', 'sentiment-analysis', 'intent-detection'],
});

// Decommission (irreversible)
await client.agents.decommissionAgent('a1b2c3d4-...');

Credentials

// Generate a credential — clientSecret shown once, store it securely
const cred = await client.credentials.generateCredential('a1b2c3d4-...');
console.log(cred.clientSecret); // only available here

// List credentials
const { data: creds } = await client.credentials.listCredentials('a1b2c3d4-...');

// Rotate — same credentialId, new secret, old secret immediately invalid
const rotated = await client.credentials.rotateCredential('a1b2c3d4-...', 'cred-uuid');
console.log(rotated.clientSecret); // new secret — store immediately

// Revoke
await client.credentials.revokeCredential('a1b2c3d4-...', 'cred-uuid');

Token operations

// Introspect — check whether a token is active
const result = await client.tokens.introspectToken(someToken);
if (result.active) {
  console.log('Token is valid, expires at', result.exp);
} else {
  console.log('Token is expired or revoked');
}

// Revoke — immediately invalidates the token
await client.tokens.revokeToken(someToken);

Audit log

// Query audit events
const { data: events } = await client.audit.queryAuditLog({
  agentId: 'a1b2c3d4-...',
  action: 'token.issued',
  outcome: 'success',
  fromDate: '2026-03-01T00:00:00Z',
  toDate: '2026-03-31T23:59:59Z',
  limit: 50,
});

// Get a single event
const event = await client.audit.getAuditEvent('event-uuid');

Error handling

All API errors are thrown as AgentIdPError:

import { AgentIdPClient, AgentIdPError } from '@sentryagent/idp-sdk';

try {
  await client.agents.getAgent('non-existent-id');
} catch (err) {
  if (err instanceof AgentIdPError) {
    console.error(err.code);       // e.g. 'AgentNotFoundError'
    console.error(err.httpStatus); // e.g. 404
    console.error(err.message);    // human-readable description
  }
}

Available scopes

Scope What it allows
agents:read Read agent records
agents:write Create, update, decommission agents
tokens:read Introspect tokens
audit:read Query audit logs

License

Apache 2.0 — see LICENSE in the repository root.