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

@openmetadata/ai-sdk

v0.1.2

Published

OpenMetadata AI SDK for Node.js - Interact with OpenMetadata Dynamic Agents

Readme

@openmetadata/ai-sdk

TypeScript SDK for interacting with OpenMetadata Dynamic Agents.

Installation

npm install @openmetadata/ai-sdk

Requirements: Node.js >= 18.0.0 (uses native fetch)

Quick Start

import { AISdk } from '@openmetadata/ai-sdk';

// Initialize the client
const client = new AISdk({
  host: 'https://openmetadata.example.com',
  token: 'your-bot-jwt-token',
});

// Invoke an agent
const response = await client.agent('DataQualityPlannerAgent')
  .invoke('What tables have quality issues?');

console.log(response.response);
console.log('Tools used:', response.toolsUsed);

Usage

Synchronous Invocation

const agent = client.agent('DataQualityPlannerAgent');
const response = await agent.invoke('Analyze the orders table');

console.log(response.response);
console.log(response.conversationId);
console.log(response.toolsUsed);

Streaming Response

for await (const event of client.agent('DataQualityPlannerAgent')
  .stream('Analyze data quality')) {
  switch (event.type) {
    case 'start':
      console.log('Started conversation:', event.conversationId);
      break;
    case 'content':
      process.stdout.write(event.content || '');
      break;
    case 'tool_use':
      console.log('\nUsing tool:', event.toolName);
      break;
    case 'end':
      console.log('\nCompleted');
      break;
    case 'error':
      console.error('Error:', event.error);
      break;
  }
}

Multi-Turn Conversations

const agent = client.agent('DataQualityPlannerAgent');

// First message
const r1 = await agent.invoke('Analyze the orders table');
console.log(r1.response);

// Follow-up using the same conversation
const r2 = await agent.invoke('Now create tests for the issues you found', {
  conversationId: r1.conversationId,
});
console.log(r2.response);

List Available Agents

const agents = await client.listAgents();

for (const agent of agents) {
  console.log(`${agent.displayName}: ${agent.description}`);
  console.log(`  Abilities: ${agent.abilities.join(', ')}`);
}

// With pagination
const moreAgents = await client.listAgents({ limit: 20, offset: 10 });

Get Agent Information

const agent = client.agent('DataQualityPlannerAgent');
const info = await agent.getInfo();

console.log('Name:', info.displayName);
console.log('Description:', info.description);
console.log('Abilities:', info.abilities);
console.log('API Enabled:', info.apiEnabled);

Create Agents

const newAgent = await client.createAgent({
  name: 'MyCustomAgent',
  description: 'A custom agent for data analysis',
  persona: 'DataAnalyst',
  apiEnabled: true,
  abilities: ['search', 'query'],
});

console.log('Created agent:', newAgent.name);

Bots

// List all bots
const bots = await client.listBots();
for (const bot of bots) {
  console.log(`${bot.name}: ${bot.displayName}`);
}

// Get a specific bot
const bot = await client.getBot('my-bot-name');
console.log('Bot:', bot.name);

Personas

// List all personas
const personas = await client.listPersonas();
for (const persona of personas) {
  console.log(`${persona.name}: ${persona.description}`);
}

// Get a specific persona
const persona = await client.getPersona('DataAnalyst');

// Create a new persona
const newPersona = await client.createPersona({
  name: 'CustomAnalyst',
  description: 'A specialized data analyst',
  prompt: 'You are an expert data analyst who helps users understand their data...',
});
console.log('Created persona:', newPersona.name);

Abilities

// List all abilities
const abilities = await client.listAbilities();
for (const ability of abilities) {
  console.log(`${ability.name}: ${ability.description}`);
}

// Get a specific ability
const ability = await client.getAbility('search');
console.log('Ability:', ability.name);

Configuration Options

const client = new AISdk({
  // Required
  host: 'https://openmetadata.example.com',  // OpenMetadata server URL
  token: 'your-jwt-token',               // Bot JWT token

  // Optional
  timeout: 120000,    // Request timeout in ms (default: 120000)
  maxRetries: 3,      // Max retry attempts (default: 3)
  retryDelay: 1000,   // Base retry delay in ms (default: 1000)
});

Error Handling

The SDK provides specific error classes for different failure modes:

import {
  AISdk,
  AuthenticationError,
  AgentNotFoundError,
  AgentNotEnabledError,
  BotNotFoundError,
  PersonaNotFoundError,
  AbilityNotFoundError,
  RateLimitError,
  AgentExecutionError,
  NetworkError,
  TimeoutError,
} from '@openmetadata/ai-sdk';

try {
  const response = await client.agent('MyAgent').invoke('Hello');
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid token - please check your credentials');
  } else if (error instanceof AgentNotFoundError) {
    console.error(`Agent not found: ${error.agentName}`);
  } else if (error instanceof AgentNotEnabledError) {
    console.error(`Agent not API-enabled: ${error.agentName}`);
  } else if (error instanceof BotNotFoundError) {
    console.error(`Bot not found: ${error.botName}`);
  } else if (error instanceof PersonaNotFoundError) {
    console.error(`Persona not found: ${error.personaName}`);
  } else if (error instanceof AbilityNotFoundError) {
    console.error(`Ability not found: ${error.abilityName}`);
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited - retry after ${error.retryAfter} seconds`);
  } else if (error instanceof TimeoutError) {
    console.error(`Request timed out after ${error.timeoutMs}ms`);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof AgentExecutionError) {
    console.error('Agent execution failed:', error.message);
  }
}

Type Definitions

InvokeResponse

interface InvokeResponse {
  conversationId: string;  // ID for multi-turn conversations
  response: string;        // Agent's response text
  toolsUsed: string[];     // Tools used during execution
  usage?: Usage;           // Token usage statistics
}

StreamEvent

interface StreamEvent {
  type: 'start' | 'content' | 'tool_use' | 'end' | 'error';
  content?: string;        // Content for 'content' events
  toolName?: string;       // Tool name for 'tool_use' events
  conversationId?: string; // Available on 'start' and 'end'
  error?: string;          // Error message for 'error' events
}

AgentInfo

interface AgentInfo {
  name: string;            // Agent identifier
  displayName: string;     // Human-readable name
  description: string;     // Agent description
  abilities: string[];     // List of capabilities
  apiEnabled: boolean;     // Whether API access is enabled
}

BotInfo

interface BotInfo {
  name: string;            // Bot identifier
  displayName: string;     // Human-readable name
  description: string;     // Bot description
}

PersonaInfo

interface PersonaInfo {
  name: string;            // Persona identifier
  displayName: string;     // Human-readable name
  description: string;     // Persona description
  prompt: string;          // System prompt
}

AbilityInfo

interface AbilityInfo {
  name: string;            // Ability identifier
  displayName: string;     // Human-readable name
  description: string;     // Ability description
}

CreateAgentRequest

interface CreateAgentRequest {
  name: string;            // Required: unique identifier
  description: string;     // Required: agent description
  persona: string;         // Required: persona name
  displayName?: string;    // Human-readable name
  apiEnabled?: boolean;    // Enable API access
  abilities?: string[];    // List of ability names
  prompt?: string;         // Default task/prompt
  provider?: string;       // LLM provider
  botName?: string;        // Bot for actions
}

CreatePersonaRequest

interface CreatePersonaRequest {
  name: string;            // Required: unique identifier
  description: string;     // Required: persona description
  prompt: string;          // Required: system prompt
  displayName?: string;    // Human-readable name
  provider?: string;       // LLM provider
}

Environment Variables

For convenience, you can use environment variables:

const client = new AISdk({
  host: process.env.OPENMETADATA_HOST!,
  token: process.env.OPENMETADATA_TOKEN!,
});

License

Apache-2.0