Skip to content

RelevanceAI/relevance-js-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Relevance AI JavaScript SDK

A comprehensive JavaScript/TypeScript SDK for building AI-powered applications with Relevance AI's workforce platform. Build, deploy, and scale AI workforces across any JavaScript runtime.

Description

The Relevance AI JavaScript SDK provides a unified interface for integrating AI workforces and agents into your applications. Whether you're building server-side applications, browser-based interfaces, or edge computing solutions, this SDK delivers consistent, type-safe access to Relevance AI's powerful agent ecosystem.

Key Features

  • Universal Compatibility: Works seamlessly across Node.js, Deno, Bun, Cloudflare Workers, and browsers
  • Event-Driven Architecture: Real-time updates via native EventTarget API
  • Type Safety: Full TypeScript support with comprehensive type definitions
  • Zero Dependencies: Built on web standards for minimal footprint

Quick Start

Get up and running in seconds:

import { Agent, createClient, EU_REGION } from "@relevanceai/sdk";

// Initialize client with your credentials
const client = createClient({
  apiKey: process.env.RELEVANCE_API_KEY,
  region: EU_REGION,
  project: process.env.PROJECT_ID,
});

// Load an agent
const agent = await Agent.get("agent-id");
// Start a conversation
const task = await agent.sendMessage("Hello, how can you help me today?");
// Listen for agent responses
task.addEventListener("message", ({ detail: { message } }) => {
  if (message.isAgent()) {
    console.log("Agent:", message.text);
  }
});

// Or use a workforce of agents

import { Workforce } from "@relevanceai/sdk";

// Load the workforce
const workforce = await Workforce.get("workforce-id");
// Start delegating
const task = await workforce.sendMessage("Analyze this complex dataset");

Installation

Choose the installation method for your runtime:

Node.js / Bun

npm install @relevanceai/sdk@latest
# or
yarn add @relevanceai/sdk@latest
# or
pnpm add @relevanceai/sdk@latest
# or
bun add @relevanceai/sdk@latest

Deno

deno add jsr:@relevanceai/sdk

Or import directly:

import { createClient } from "jsr:@relevanceai/sdk";

Cloudflare Workers

npm install @relevanceai/sdk@latest

Browser (with bundler)

npm install @relevanceai/sdk@latest

For bundlers that warn about node:crypto, create a shim:

// shims/crypto.js
export default window.crypto;

Configure your bundler to use the shim:

Browser (CDN)

<script type="importmap">
  {
    "imports": {
      "@relevanceai/sdk": "https://esm.run/@relevanceai/sdk"
    }
  }
</script>
<script type="module">
  import { createClient } from "@relevanceai/sdk";
  // Your code here
</script>

Usage

Authentication

The SDK supports two authentication methods for different use cases:

API Keys (server-side)

API keys grant full access to your project. Use these for server applications and secure environments:

import { createClient, AU_REGION } from "@relevanceai/sdk";

const client = createClient({
  apiKey: "sk-...",
  region: AU_REGION,
  project: "project-uuid",
});

You can also create a Key instance explicitly:

import { Client, Key, AU_REGION } from "@relevanceai/sdk";

const key = new Key({
  key: "sk-...",
  region: AU_REGION,
  project: "project-uuid",
});

const client = new Client(key);

Embed Keys (client-side)

For public-facing applications, use embed keys which are scoped to a specific public agent. Embed keys need to be generated and should be stored in your applications local storage or database. Each embed key corresponds to a single agent or workforce.

import { Key, createClient, US_REGION } from "@relevanceai/sdk";

const embedKey = await Key.generateEmbedKey({
  region: US_REGION,
  project: "project-uuid",
  agentId: "public-agent-id", // Must be a public agent
});

const client = createClient(embedKey);

Agents

Loading agents

// fetch all agents (with pagination)
const agents = await Agent.getAll({ pageSize: 20, page: 1 });

// fetch all agents with custom page size
const agents = await Agent.getAll({ pageSize: 50, page: 3 });

// fetch all agents using default options (pageSize: 20, page: 1)
const agents = await Agent.getAll();

// using the default client
const agent = await Agent.get("agent-id");

// or using a specific client
const agent = await Agent.get("agent-id", client);

// accessing agent properties
console.log(agent.name);
console.log(agent.avatar);
console.log(agent.description);

Sending messages

Use Agent#sendMessage() to send messages to an agent.

// create a new task
const task = await agent.sendMessage("What's the weather like today?");

// reply to existing tasks
await agent.sendMessage("What about tomorrow?", task);

// sending attachments
const contents = await Deno.readFile("./contract.pdf");
const contract = new File([contents], "contract.pdf", {
  type: "application/pdf",
});
await agent.sendMessage("Summarize this contract", [contract]);

Note: Agent#sendMessage() returns once the message is sent and doesn't wait for a response. See Tasks for handling message events.

Retrieving tasks

Fetch and filter tasks for an agent:

// specific task
const task = await agent.getTask("<task-id>");

// pagination
const tasks = await agent.getTasks({
  pageSize: 10,
  page: 1,
  sort: { updatedAt: "desc" },
});

// filtering
const activeTasks = await agent.getTasks({
  filter: { status: ["queued", "running", "idle"] },
});

// searching
const searchResults = await agent.getTasks({
  search: "weather",
  sort: { createdAt: "asc" },
});

Workforces

Loading workforces

// using the default client
const workforce = await Workforce.get("<workforce-id>");

// or with a specific client
const workforce = await Workforce.get("<workforce-id>", client);

// accessing workforce properties
console.log(workforce.name);

Sending messages

Use Workforce#sendMessage() to send messages to a workforce.

// create a new task
const task = await agent.sendMessage("What's the weather like today?");

// reply to existing tasks
await agent.sendMessage("What about tomorrow?", task);

Note: Workforce#sendMessage() returns once the message is sent and doesn't wait for a response. See Tasks for handling message events.

Retrieving tasks

Load existing workforce tasks.

const task = await workforce.getTask("<task-id>");

Tasks

Agents and workforces, subjects, all return an instance of a Task when sending messages. Tasks dispatch events as they would occur on the the subjects timeline in the Relevance AI workforce platform.

Available Events

  • update: Whenever a subject has been update.
  • message: Unified event for all message types
  • error: Error notifications

Listening for Events

// Listen for all messages (agent, user, and tool)
task.addEventListener("message", ({ detail: { message } }) => {
  // use message helpers to determine the message
  if (message.isAgent()) {
    console.log("Agent:", message.text);
  } else if (message.isUser()) {
    console.log("User:", message.text);
  } else if (message.isTool()) {
    console.log("Tool:", message.status);
  }
});

// catching errors
task.addEventListener("error", ({ detail: { message } }) => {
  console.error("Task error:", message.lastError);
});

Unsubscribing

It's important that you unsubscribe from tasks once they have moved out of scope in your application. This will prevent memory leaks by removing dead subscriptions.

task.unsubscribe();

Advanced Usage

Default Client Pattern

Use a singleton client throughout your application:

// Initialize once at startup
createClient({ apiKey, region, project });

// Access anywhere in your app
import { Client } from "@relevanceai/sdk";

const client = Client.default();

Multiple Clients

Manage multiple projects or authentication scopes:

import { Client, Key, EU_REGION } from "@relevanceai/sdk";

const projectOneKey = new Key({
  key: "sk-project1",
  region: EU_REGION,
  project: "project-1-id",
});

const projectTwoKey = new Key({
  key: "sk-project2",
  region: EU_REGION,
  project: "project-2-id",
});

const clientOne = new Client(projectOneKey);
const clientTwo = new Client(projectTwoKey);

// Use different clients for different agents
const agentOne = await Agent.get("agent-1", clientOne);
const agentTwo = await Agent.get("agent-2", clientTwo);

Examples

For complete working examples, check out the internal/examples directory:

  • Deno Examples (internal/examples/deno/):

    • (Agent) Creating tasks
    • (Agent) Getting a task
    • (Agent) Getting all agents
    • (Agent) Getting all tasks
    • (Agent) Getting an agent
    • (Workforce) Creating a task
  • Browser Example (internal/examples/browser/):

    • Full chat application with Preact
    • Real-time message handling
    • UI components for agent interactions

API Reference

Client

class Client {
  constructor(key: Key);

  static default(): Client;

  readonly key: Key;
  readonly region: Region;
  readonly project: string;

  isEmbedKey(): boolean;

  fetch<T>(endpoint: string, init?: RequestInit): Promise<T>;

  url(path: string): URL;
}

function createClient(keyOrOptions: Key | CreateClientOptions): Client;

interface CreateClientOptions {
  apiKey: string;
  region: Region;
  project: string;
}

Key

class Key {
  static async generateEmbedKey(options: GenerateEmbedKeyOptions): Promise<Key>;

  constructor(options: CreateKeyOptions);

  readonly region: Region;
  readonly project: string;
  readonly agentId?: string;
  readonly taskPrefix?: string;

  isEmbed(): boolean;

  fetchHeaders(): HeadersInit;

  toJSON(): CreateKeyOptions;
}

interface CreateKeyOptions {
  key: string;
  region: Region;
  project: string;
  agentId?: string;
  taskPrefix?: string;
}

interface GenerateEmbedKeyOptions {
  region: Region;
  project: string;
  agentId: string;
}

Agent

class Agent {
  static async get(id: string, client?: Client): Promise<Agent>;

  static async getAll(
    options?: GetAllOptions,
    client?: Client
  ): Promise<Agent[]>;

  readonly id: string;
  readonly name?: string;
  readonly description?: string;
  readonly avatar?: string;
  readonly createdAt: Date;
  readonly updatedAt: Date;
  readonly region: Region;
  readonly project: string;

  getTask(taskId: string): Promise<Task>;

  getTasks(): Promise<Task[]>;
  getTasks(options: GetTaskOptions): Promise<Task[]>;

  sendMessage(message: string): Promise<Task>;
  sendMessage(message: string, task: Task): Promise<Task>;
  sendMessage(
    message: string,
    attachments: (File | Attachment)[]
  ): Promise<Task>;
  sendMessage(
    message: string,
    attachments: (File | Attachment)[],
    task: Task
  ): Promise<Task>;
}

interface Attachment {
  fileName: string;
  fileUrl: string;
}

interface GetTaskOptions {
  pageSize?: number; // default: 100
  page?: number; // default: 1
  // default: { createdAt: "asc" }
  sort?: { createdAt: "asc" | "desc" } | { updatedAt: "asc" | "desc" };
  search?: string;
  filter?: {
    status?: TaskStatus[];
  };
}

interface GetAllOptions {
  pageSize?: number; // default: 20
  page?: number; // default: 1
}

Workforce

class Workforce {
  static async get(id: string, client?: Client): Promise<Workforce>;

  readonly id: string;
  readonly name: string;
  readonly region: Region;
  readonly project: string;

  getTask(taskId: string): Promise<Task>;

  sendMessage(message: string): Promise<Task>;
  sendMessage(message: string, task: Task): Promise<Task>;
}

Task

class Task<T extends Agent | Workforce = Agent> extends EventTarget {
  readonly id: string;
  readonly title: string;
  readonly status: TaskStatus;
  readonly subject: Agent | Workforce;

  isRunning(): boolean;

  getMessages(): Promise<AnyTaskMessage[]>;
  getMessages(options: { from: Date }): Promise<AnyTaskMessage[]>;

  subscribe(): void;

  unsubscribe(): void;

  addEventListener(type: string, listener: EventListener): void;

  removeEventListener(type: string, listener: EventListener): void;
}

type TaskStatus =
  | "not-started"
  | "idle"
  | "queued"
  | "running"
  | "action"
  | "completed"
  | "error";

Messages

abstract class GenericMessage {
  readonly id: string;
  readonly type: MessageType;
  readonly createdAt: Date;

  isAgent(): boolean; // Check if message is from agent
  isUser(): boolean; // Check if message is from user
  isTool(): boolean; // Check if message is a tool execution
  isAgentError(): boolean; // Check if message is an agent error
}

class AgentMessage extends GenericMessage {
  readonly text: string;
}

class UserMessage extends GenericMessage {
  readonly text: string;
}

class ToolMessage extends GenericMessage {
  readonly status: "cancelled" | "pending" | "running" | "completed" | "failed";
  readonly tool?: Tool; // Available when message is from a tool (not subagent)
  readonly toolOrAgentId: string; // ID of the tool or subagent

  isSubAgent(): boolean; // Check if this is a subagent execution
  subAgentTaskId: string | null; // Task ID if this is a subagent, null otherwise
}

class AgentErrorMessage extends GenericMessage {}

class WorkforceAgentMessage extends GenericMessage {}

class WorkforceAgentHandoverMessage extends GenericMessage {}

Tool

class Tool {
  readonly id: string;
  readonly name: string;
  readonly avatar?: string;
  readonly description?: string;
  readonly region: Region;
  readonly project: string;
  readonly parametersSchema: JSONSchema4;
}

Contributing

We welcome contributions to improve the SDK. Please follow these guidelines:

Development Setup

  1. Clone the repository
  2. Install Deno (primary development environment)
# Build npm package
deno run dnt

Code Style

  • Use TypeScript for all code
  • Follow existing patterns and conventions
  • Maintain 80-character line width where practical
  • Write clear, concise commit messages

Submitting Changes

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request with clear description

Roadmap

Current

  • Core client functionality
  • Task creation
  • Event-driven messaging
  • Multi-environment support
  • Workforce support

Upcoming Features

  • Streaming responses
  • File upload support
  • Enhanced error recovery
  • Agent and task management
  • Tool support

Future Considerations (2.0)

  • WebSocket support for real-time updates
  • Offline queue management
  • Tool building architecture
  • Voice modality

Support

License

MIT License. See LICENSE for details.

Security

For security vulnerabilities, please email [email protected] directly rather than using public issue trackers.

About

JavaScript/TypeScript SDK for building AI-powered applications with Relevance AI's workforce platform.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages