JSPM

@switchy-ai/sdk

0.3.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 15
  • Score
    100M100P100Q75587F
  • License MIT

Official TypeScript/JavaScript SDK for Switchy — the shared AI workspace for small teams.

Package Exports

  • @switchy-ai/sdk
  • @switchy-ai/sdk/mcp

Readme

@switchy-ai/sdk

Official TypeScript / JavaScript SDK for Switchy — the shared AI workspace for small teams.

Install

npm install @switchy-ai/sdk

Optional, only if you want live chat updates:

npm install ably

Hello world

Ten lines: list your Spaces, save a memory, search for it.

import { Switchy } from '@switchy-ai/sdk';

const client = new Switchy({ apiKey: process.env.SWITCHY_API_KEY! });

const { projects: spaces } = await client.spaces.list();
const space = spaces[0];

await client.memory.create({
  content: 'Launching the new pricing page on May 15.',
  visibility: 'SPACE',
  spaceId: space.id,
});

const hits = await client.memory.search({ query: 'when do we launch?' });
console.log(hits[0].memory.content);

What you can do

The SDK mirrors the v2 REST API one-to-one. Each namespace is fully typed.

client.spaces.list({ page, limit })
client.spaces.get(id)
client.spaces.create({ name, description, tags }, { idempotencyKey })

client.sessions.list(spaceSlug)
client.sessions.create(spaceSlug, { name, participantUserIds, defaultAgent })
client.sessions.get(spaceSlug, sessionId)
client.sessions.update(spaceSlug, sessionId, { title, model })
client.sessions.archive(spaceSlug, sessionId)

client.messages.list(spaceSlug, sessionId, { before, limit })
client.messages.send(spaceSlug, sessionId, { body, parentMessageId })
client.messages.react(spaceSlug, messageId, '👍')

client.memory.list({ visibility, spaceId, limit })
client.memory.create({ content, visibility, spaceId, tags, sourceUrl })
client.memory.search({ query, spaceId, limit })
client.memory.delete(memoryId)

client.members.list(orgId)
client.members.updateRole(orgId, userId, 'ADMIN')
client.members.remove(orgId, userId)

client.invitations.list(orgId)
client.invitations.create(orgId, { email, role: 'MEMBER' })
client.invitations.accept(token)

client.billing.credits()
client.billing.checkout({ plan: 'team', interval: 'annual' })
client.billing.portal(returnUrl)
client.billing.topup({ pack: 'medium' })

client.mcp.list()
client.mcp.create({ displayName, mentionSlug, endpointUrl, authType, secret })
client.mcp.delete(id)
client.mcp.test(id)

client.keys.list()
client.keys.create({ name, scopes })

Realtime

Subscribe to live messages, typing indicators, reactions, and member events in one Space session. Requires the optional ably peer dependency.

const channel = client.realtime(space.slug, session.id);

const sub = await channel.subscribe((event) => {
  switch (event.type) {
    case 'message': console.log('new message:', event.message.body); break;
    case 'typing':  console.log(`${event.userId} is ${event.state}-typing`); break;
    case 'reaction': console.log(`reaction ${event.emoji} ${event.delta}`); break;
    case 'member':  console.log(`${event.userId} ${event.action}`); break;
  }
});

// later
await sub.unsubscribe();

MCP client

Switchy is also an MCP server. From any MCP-capable client (Claude Desktop, Cursor, your own code) you can call Switchy's tools over JSON-RPC.

import { McpClient } from '@switchy-ai/sdk';

const mcp = new McpClient({ apiKey: process.env.SWITCHY_API_KEY! });

const { memories } = await mcp.searchMemory({ query: 'launch readiness' });
const { space } = await mcp.getSpace('product');
await mcp.actAsUser('user_abc').postMessage({
  sessionId: 'sess_123',
  content: 'Just shipped the migration guide.',
});

See /docs/mcp for the full tool list and scopes.

Errors

Every method returns the unwrapped resource on success. On failure it throws a typed error you can instanceof-check:

import { ValidationError, ForbiddenError, RateLimitError } from '@switchy-ai/sdk';

try {
  await client.spaces.create({ name: '' });
} catch (err) {
  if (err instanceof ValidationError) console.error(err.issues);
  else if (err instanceof ForbiddenError) console.error('not allowed');
  else if (err instanceof RateLimitError) console.error(`retry in ${err.retryAfter}s`);
  else throw err;
}

The full error table — codes, HTTP status, when each fires — is at /docs/api/overview.

Idempotency

Every POST accepts an idempotencyKey. If you retry the same call with the same key within 24 hours, the server replays the original response instead of creating a duplicate.

const key = crypto.randomUUID();
await client.messages.send(slug, sessionId, { body: 'hi' }, { idempotencyKey: key });

Migrating from v0.2

v0.3 is the team-workspace SDK. The shape changed because the product changed. Quick map:

v0.2 v0.3
client.chat.complete({ model, message }) client.messages.send(spaceSlug, sessionId, { body: '@model message' })
client.chat.stream(...) Use client.realtime(...) for live AGENT replies.
client.namespaces.create({ name }) client.spaces.create({ name })
client.namespaces.list() client.spaces.list() then read .projects
client.memory.createFrame(ns, ...) client.memory.create({ content, visibility, spaceId })
client.memory.search({ query, namespaces }) client.memory.search({ query, spaceId })
client.sessions.create({ namespace }) client.sessions.create(spaceSlug, { name })
client.knowledgeGraph.* Removed. KG is internal in v2; use semantic memory search.
client.videos.* Removed. Re-shipping under /v1/videos later.

Big-picture changes:

  • Org context is implicit. Mint a key inside the org you want to talk to; the SDK doesn't need an orgId arg on most calls.
  • Visibility is required on memory writes. PRIVATE (only you), SPACE (Space members), ORG (everyone in the org).
  • The base URL changed from …/api/v1 to …/api. The SDK defaults; pass baseUrl if you target staging.
  • Errors are typed. Replace try { … } catch (e) { if (e.code === 'RATE_LIMIT_EXCEEDED') … } with instanceof RateLimitError.

If you minted a key under one org and used it in another org by accident in v0.2 — that's no longer possible. Keys lock to their minting org.

Configuration reference

new Switchy({
  apiKey: 'sk_live_...',         // required
  baseUrl: 'https://switchy.build/api',  // default
  timeout: 60_000,               // ms, default 60s
  maxRetries: 2,                 // 429 retries honouring Retry-After
  fetch,                         // custom fetch (tests / non-Node)
  userAgent: 'my-app/1.0',       // optional
});

License

MIT