Skip to main content

Overview

The @jinba-toolbox/sdk package provides a type-safe client library for consuming tools registered in Jinba Toolbox. It wraps the REST API with convenient methods for listing toolsets, executing tools, managing versions, and retrieving run history. Target consumers:
  • AI agents executing tools
  • CLI tools for automation
  • Third-party applications integrating with Jinba Toolbox
  • Developers building on Jinba Toolbox

Installation

# npm
npm install @jinba-toolbox/sdk

# pnpm
pnpm add @jinba-toolbox/sdk

# yarn
yarn add @jinba-toolbox/sdk

Quick Start

1

Import and create a client

import { createClient } from "@jinba-toolbox/sdk";

const client = createClient({
  apiKey: process.env.JINBA_TB_API_KEY!,
  organizationId: "org-id", // optional default
});
2

List your toolsets

const toolSets = await client.listToolSets();
console.log(toolSets);
3

Execute a tool

const result = await client.run("slack-tools", "post-message", {
  channel: "#general",
  text: "Hello from Jinba Toolbox!",
});

console.log(result.output);
// { ts: "1234567890.123456", channel: "C01234567" }

Client Configuration

The createClient function accepts a JinbaTBClientConfig object:
interface JinbaTBClientConfig {
  /** API base URL (default: https://toolbox-api.jinba.dev) */
  baseUrl?: string;
  /** API key for authentication */
  apiKey: string;
  /** Default organization ID (optional, can be overridden per request) */
  organizationId?: string;
  /** Request timeout in milliseconds (default: 30000) */
  timeout?: number;
}
Example with all options:
const client = createClient({
  baseUrl: "https://toolbox-api.jinba.dev",
  apiKey: "jtb_xxxxxxxxxxxx",
  organizationId: "org_abc123",
  timeout: 60000,
});
If you set organizationId in the constructor, you can omit it from individual method calls. Every method also accepts an optional orgId parameter to override the default.

API Reference

Organizations

// List organizations the authenticated user belongs to
const orgs = await client.listOrganizations();
// Returns: OrganizationWithRole[]

// Get organization details
const org = await client.getOrganization("org-id");
// Returns: Organization

ToolSets

// List toolsets in an organization
const toolSets = await client.listToolSets();
// Returns: ToolSet[]

// Get a toolset by slug (includes tools)
const toolSet = await client.getToolSet("slack-tools");
// Returns: ToolSet & { tools: Tool[] }

// Create a new toolset
const newToolSet = await client.createToolSet({
  slug: "slack-tools",
  name: { default: "Slack Tools" },
  description: { default: "Slack integration tools" },
  sandbox: {
    provider: "e2b",
    language: "typescript",
    packages: [{ name: "@slack/web-api" }],
    resources: { timeout: 60000 },
  },
  visibility: "private",
  tags: ["slack"],
});

// Update a toolset
await client.updateToolSet("slack-tools", {
  visibility: "public",
  tags: ["slack", "messaging"],
});

// Delete a toolset
await client.deleteToolSet("slack-tools");

Tools

// List tools in a toolset
const tools = await client.listTools("slack-tools");
// Returns: Tool[]

// Get a tool by slug
const tool = await client.getTool("slack-tools", "post-message");
// Returns: Tool

// Create a new tool
const newTool = await client.createTool("slack-tools", {
  slug: "post-message",
  name: { default: "Post Message" },
  description: { default: "Post a message to a Slack channel" },
  inputSchema: {
    type: "object",
    properties: {
      channel: { type: "string", description: "Channel name or ID" },
      text: { type: "string", description: "Message text" },
    },
    required: ["channel", "text"],
  },
  outputSchema: {
    type: "object",
    properties: {
      ts: { type: "string" },
      channel: { type: "string" },
    },
  },
  code: `// tool implementation code`,
});

// Update a tool
await client.updateTool("slack-tools", "post-message", {
  description: { default: "Post a message to any Slack channel" },
});

// Delete a tool
await client.deleteTool("slack-tools", "post-message");

Execution

// Execute a published tool
const result = await client.run("slack-tools", "post-message", {
  channel: "#general",
  text: "Hello!",
});
// Returns: RunResult

console.log(result.success);    // true
console.log(result.output);     // { ts: "...", channel: "..." }
console.log(result.durationMs); // 1234

// Execute a specific version
const result = await client.run(
  "slack-tools",
  "post-message",
  { channel: "#general", text: "Hello!" },
  { version: "1.2.0" }
);

// Test a tool (runs draft code, no published version required)
const testResult = await client.test("slack-tools", "post-message", {
  channel: "#test",
  text: "Testing...",
});

Versions

// List versions of a toolset
const versions = await client.listVersions("slack-tools");
// Returns: ToolSetVersion[]

// Publish a new version
const version = await client.publishVersion("slack-tools", {
  version: "1.3.0",
  releaseNotes: "Added thread reply support",
});
// Returns: ToolSetVersion

Run History

// List runs in an organization
const runs = await client.listRuns();
// Returns: Run[]

// Get run details
const run = await client.getRun("run_abc123");
// Returns: Run

Key Types

RunResult

The object returned from run() and test():
interface RunResult {
  runId: string;
  version: string;
  success: boolean;
  output?: Record<string, unknown>;
  error?: { name: string; message: string; traceback?: string };
  logs?: { stdout: string[]; stderr: string[] };
  durationMs?: number;
}

ToolSet

interface ToolSet {
  id: string;
  organizationId: string;
  slug: string;
  name: LocalizedText;
  description: LocalizedText;
  sandbox: SandboxConfig;
  visibility: "public" | "private" | "restricted";
  mcpEnabled: boolean;
  tags: string[];
  latestVersion?: string | null;
  publishedVersion?: string | null;
  createdAt: string;
  updatedAt: string;
}

Tool

interface Tool {
  id: string;
  toolSetId: string;
  slug: string;
  name: LocalizedText;
  description: LocalizedText;
  inputSchema: JSONSchema;
  outputSchema: JSONSchema;
  code: string;
  entrypoint?: string | null;
  createdAt: string;
  updatedAt: string;
}

Error Handling

The SDK throws JinbaTBError for non-2xx responses:
import { JinbaTBError } from "@jinba-toolbox/sdk";

try {
  const result = await client.run("my-toolset", "my-tool", { input: "data" });
} catch (error) {
  if (error instanceof JinbaTBError) {
    console.error(`Status: ${error.statusCode}`);
    console.error(`Message: ${error.message}`);
    console.error(`Details: ${JSON.stringify(error.details)}`);
  }
}
A 408 status code is thrown when a request exceeds the configured timeout.

Best Practices

  • Set a default organizationId in the constructor to avoid passing it to every method.
  • Use environment variables for the API key — never hard-code credentials.
  • Handle JinbaTBError to distinguish between client errors (4xx) and server errors (5xx).
  • Increase timeout for tool executions that run complex sandbox workloads.
  • Pin a version when calling run() if your application depends on deterministic behavior.