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

@gravity-rail/sdk

v0.2.0

Published

Gravity Rail TypeScript SDK — API client for workspace management

Readme

@gravity-rail/sdk

TypeScript SDK for Gravity Rail — the AI-native operating system for organizations that communicate with people at scale.

Build AI assistants that handle voice calls, SMS, web chat, email, Discord, and Slack — all backed by configurable workflows, structured data collection, and real-time streaming. One SDK, every channel.

Installation

npm install @gravity-rail/sdk
# or
yarn add @gravity-rail/sdk
# or
pnpm add @gravity-rail/sdk

Zod schemas are available as an optional peer dependency:

npm install zod  # optional, for runtime validation

Quick Start

import { GravityRailClient } from '@gravity-rail/sdk';

const client = new GravityRailClient(
  process.env.GRAVITY_RAIL_API_KEY,
  'https://api.gravityrail.com'
);

// List all workflows in a workspace
const workflows = await client.getWorkflows(workspaceId);

// Get active chats across every channel
const chats = await client.getChats(workspaceId);

// Create a new member
const member = await client.createWorkspaceMember(workspaceId, {
  first_name: 'Jane',
  last_name: 'Doe',
  email: '[email protected]',
  role_id: roleId,
});

Authentication

API Key

Scoped API keys are the simplest way to authenticate. Create one from workspace settings or via the SDK:

const client = new GravityRailClient(
  'your-api-key',
  'https://api.gravityrail.com'
);

Keys can be scoped to specific permissions (read-only, workspace-limited, time-expiring) using the granular scope system.

OAuth2 with PKCE

For browser-based applications:

const client = new GravityRailClient(undefined, 'https://api.gravityrail.com');

// Handle step-up authentication when the API requires it
client.setEnhancedAuthHandler(async (authInfo) => {
  // Redirect to login or show auth modal
});

Member Identity Switching

Act on behalf of a specific workspace member:

client.setActingMember(memberUuid);
// All subsequent requests use this member's identity
const myChats = await client.getChats(workspaceId);
client.setActingMember(undefined); // reset

Core Concepts

Every Gravity Rail workspace is a self-contained environment with isolated data, workflows, and configuration. The SDK organizes its 500+ methods by domain:

| Domain | What it covers | |---|---| | Workflows | Multi-step conversational processes with branching logic, task assignment, and templates | | Assistants | AI personas with configurable models, voices, and a two-tier supervisor system | | Agents | Autonomous AI workspace members with their own identity, config, and multi-channel presence | | Chats | Conversations across all channels — labels, filters, summaries, message history, and export | | Members | Contacts and team — roles, labels, filters, custom fields, import/export, anonymous resolution | | Data Types | Schema-driven forms (14 field types) with computed fields and conversational collection | | Events | Trigger-based automation with CEL expressions | | Calendars | Scheduling, availability, event types, Google Calendar sync, and iCal feeds | | Files | Folder hierarchy with semantic search, role-based sharing, and public access | | Sites | Customer-facing portals with custom domains, page builder, and web crawling | | Communications | Phone numbers, SMS, email inboxes, and notification rules | | Toolkits | Custom tools, MCP server integrations, and AI model configuration | | Operator Groups | Live human routing with presence tracking and configurable strategies | | Qualifications | Skills evaluation with expression-based and rubric-based scoring | | Billing | API keys, subscriptions, and usage reports (AI, voice, SMS, storage) | | Integrations | Discord, Slack, Monday.com, FHIR, and OAuth app connections |

Usage Examples

Workflows & Assistants

// Create a multi-step workflow
const workflow = await client.createWorkflow(workspaceId, {
  name: 'Customer Onboarding',
  description: 'Guide new customers through setup',
});

// Create an AI assistant
const assistant = await client.createAssistant(workspaceId, {
  name: 'Onboarding Guide',
  model: 'claude-sonnet-4-20250514',
  bio: 'A friendly assistant that helps new customers get started.',
});

// Add a supervisor for quality assurance
const supervisor = await client.createSupervisor(workspaceId, {
  name: 'QA Reviewer',
  model: 'claude-sonnet-4-20250514',
  instructions: 'Review assistant responses for accuracy and tone.',
});

// Build from templates
const templates = await client.getWorkflowTemplates(workspaceId);
await client.createWorkflowFromTemplate(workspaceId, {
  template_id: templates[0].id,
});

Chat Operations

// Get conversations across all channels
const chats = await client.getChats(workspaceId);

// Full message history with tool calls
const messages = await client.getChatMessages(workspaceId, chatId);
const toolCalls = await client.getChatToolCallMessages(workspaceId, chatId);

// Trigger an AI response
await client.sendAssistantMessage(workspaceId, chatId);

// Direct messaging between members
const dm = await client.findOrCreateDMChat(workspaceId, { member_id: targetMemberId });
await client.sendChatMessage(workspaceId, dm.id, { content: 'Hey!' });

// Export for analysis
const exported = await client.exportChat(workspaceId, chatId);

// Organize with labels and filters
await client.createChatLabel(workspaceId, { name: 'VIP', color: '#FFD700' });
await client.createChatFilter(workspaceId, { name: 'Unresolved', conditions: { needs_response: true } });

Structured Data Collection

// Define a schema — AI assistants collect this conversationally
const dataType = await client.createDataType(workspaceId, {
  name: 'Contact Form',
  slug: 'contact-form',
  is_collection: true,
  fields: [
    { name: 'Full Name', field_type: 'text', required: true },
    { name: 'Email', field_type: 'email', required: true },
    { name: 'Priority', field_type: 'dropdown', options: ['Low', 'Medium', 'High'] },
    { name: 'Score', field_type: 'formula', formula: 'Priority == "High" ? 100 : 50' },
  ],
});

// Or create records programmatically
const record = await client.createDataRecord(workspaceId, dataType.id, {
  field_values: { 'Full Name': 'Alice Chen', 'Email': '[email protected]', 'Priority': 'High' },
});

// Query and upsert
const records = await client.getDataRecords(workspaceId, dataType.id);
await client.upsertDataRecord(workspaceId, dataType.id, {
  match_field: 'Email',
  field_values: { 'Email': '[email protected]', 'Priority': 'Medium' },
});

Communication Channels

// Phone — initiate an outbound AI voice call
const numbers = await client.getPhoneNumbers(workspaceId);
await client.initiateCall(workspaceId, {
  phone_number_id: numbers[0].id,
  to_number: '+15551234567',
  workflow_id: workflowId,
});

// Email — manage inboxes and threads
const inboxes = await client.getInboxes(workspaceId);
const threads = await client.getInboxThreads(workspaceId, inboxes[0].id);
const emails = await client.getThreadEmails(workspaceId, inboxes[0].id, threadId);

// Notifications
await client.createNotificationRule(workspaceId, {
  name: 'New chat alert',
  event_type: 'chat.created',
  channel: 'email',
});

Toolkits & MCP Servers

// Connect an MCP server for custom AI tool capabilities
const server = await client.createMcpServer(workspaceId, {
  name: 'Internal Tools',
  url: 'https://tools.example.com/mcp',
});
await client.testMcpServerConnection(workspaceId, server.id);

// Discover tools, resources, and prompts
const tools = await client.getMcpServerTools(workspaceId, server.id);
const resources = await client.getMcpServerResources(workspaceId, server.id);

// Or build custom tools directly
await client.createCustomTool(workspaceId, toolkitId, {
  name: 'lookup_order',
  description: 'Look up an order by ID',
  input_schema: {
    type: 'object',
    properties: { order_id: { type: 'string' } },
    required: ['order_id'],
  },
});

Calendar & Scheduling

const calendar = await client.createCalendar(workspaceId, { name: 'Appointments' });

// Check availability and book
const slots = await client.getAvailableSlots(workspaceId, calendar.id, {
  start_date: '2025-03-01',
  end_date: '2025-03-07',
  duration_minutes: 30,
});

await client.createCalendarEvent(workspaceId, calendar.id, {
  title: 'Consultation',
  start_time: slots[0].start,
  end_time: slots[0].end,
  attendees: [{ member_id: memberId }],
});

// Sync with Google Calendar
await client.linkCalendarToGoogle(workspaceId, calendar.id, {
  google_calendar_id: 'primary',
});

Event Automation

// Trigger-based automation with CEL conditions
await client.createEventRule(workspaceId, {
  name: 'VIP Follow-up',
  trigger: 'task.exited',
  condition: '"vip" in member.labels',
  actions: [{
    type: 'send_ai_message',
    delay_minutes: 60,
    config: { message: 'Thank you for your time today.' },
  }],
});

// Scheduled events (CRON)
const event = await client.createEvent(workspaceId, {
  name: 'Daily Check-in',
  schedule: '0 9 * * *',
  target_filter: { labels: ['active'] },
});

// Trigger manually
await client.runEvent(workspaceId, event.id);

Operator Groups & Live Handoff

// Route conversations to live human operators
const group = await client.createOperatorGroup(workspaceId, {
  name: 'Support Team',
  routing_strategy: 'round_robin',
  timeout_seconds: 30, // falls back to AI if no one accepts
});

await client.addGroupMember(workspaceId, group.id, { member_id: agentMemberId });
const operators = await client.getLiveOperators(workspaceId);

Sites & Portals

// Build customer-facing portals with AI chat built in
const site = await client.createSite(workspaceId, {
  name: 'Help Center',
  slug: 'help',
  domain: 'help.example.com',
});

await client.createPage(workspaceId, site.id, {
  title: 'Getting Started',
  slug: 'getting-started',
  content: '# Welcome\nHere is how to get started...',
});

// Import existing documentation automatically
await client.crawlSite(workspaceId, site.id, { url: 'https://docs.example.com' });

Workspace Management

// Export/import full workspace configuration
const config = await client.exportWorkspace(workspaceId);
const preview = await client.previewWorkspaceImport(targetId, config);
await client.importWorkspace(targetId, config);

// White-label: provision client workspaces
const clientWs = await client.createClientWorkspace(workspaceId, {
  name: 'Acme Corp',
  product_id: productId,
});
await client.provisionClientWorkspace(workspaceId, clientWs.id);

Type System

Full TypeScript types for every API entity:

import type {
  Workspace, Member, Chat, Task, Workflow, Assistant,
  DataType, DataRecord, EventRule, Calendar, Site,
  PhoneNumber, Inbox, OperatorGroup, Qualification,
  Subscription, ApiKey, Agent, MemberRole,
} from '@gravity-rail/sdk';

Zod Schemas

Runtime validation schemas via a separate import (requires zod):

import { taskSchema, memberSchema, workflowSchema } from '@gravity-rail/sdk/schemas';

const task = taskSchema.parse(apiResponse);

const result = memberSchema.safeParse(formData);
if (!result.success) {
  console.error(result.error.flatten());
}

Scopes & Permissions

The SDK includes the complete scope system for building OAuth apps and managing API key permissions:

import { SCOPES, ScopeCategory, ScopeManager, SCOPE_PRESETS } from '@gravity-rail/sdk';

// Browse available scopes by category
const chatScopes = Object.values(SCOPES).filter(
  (s) => s.category === ScopeCategory.CHATS
);

22 scope categories covering every domain: workspace, members, chats, DMs, assistants, workflows, assignments, automations, data types, records, files, sites, agents, calendars, inboxes, phones, webhooks, apps, labels, analytics, operator, and org.

Error Handling

import { GravityRailClient, ApiError } from '@gravity-rail/sdk';

try {
  const task = await client.getTask(workspaceId, taskId);
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`${error.status}: ${error.message}`);
    // 403 → check API key scopes
    // 404 → verify workspace and entity IDs
    // 429 → rate limited, back off
  }
}

Compliance

Gravity Rail is built for HIPAA compliance. The SDK enforces:

  • Data isolation — every workspace has a dedicated database schema
  • Scoped access — API keys enforce granular permissions at the scope level
  • Feature flags — workspaces can enable HIPAA_COMPLIANCE for stricter data handling
  • Audit trails — all operations are logged for compliance reporting

Related

License

MIT