Skip to content
Reference

JavaScript SDK

Use TypeSafe's official package, @typesafe-ai/sdk, for JavaScript and TypeScript, and point it at VAKYN MAX or your own server.

Install

npm install @typesafe-ai/sdk   # Node.js 20 or newer

The package ships ESM, CommonJS and TypeScript types. The examples use top-level await, so save them as .mjs files (or set "type": "module"). They were run against open-server with @typesafe-ai/sdk 0.6.0; the package's own reference is at docs.typesafe.ai.

Point it at VAKYN

OptionEnvironment variableDefault
baseURLTYPESAFE_BASE_URLhttps://api.typesafe.ai
apiKeyTYPESAFE_API_KEYnone, required
defaultModelTYPESAFE_DEFAULT_MODELjev-latest
logLevelTYPESAFE_LOG_LEVELwarn

Set baseURL to https://api.vakyn.com for VAKYN MAX, or to your server without /v1, and apiKey to a vk_… key issued there. Explicit options win over the environment:

import { TypeSafeClient } from "@typesafe-ai/sdk"; const client = new TypeSafeClient({  baseURL: "https://api.vakyn.com", // VAKYN MAX, without /v1  apiKey: "vk_your_key_here", // from vakyn.com/console/keys  timeout: 30_000, // milliseconds per attempt  retry: { maxRetries: 4 }, // 429 and 5xx are retried});console.log((await client.models.list()).map((m) => m.name));

Ask questions

systemOne({ state, questions }) sends one request. The helpers noul(), choice() and score() build questions, and the answer types follow from them: with TypeScript, answers.team.choice is typed as the union of your option names.

import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk"; // Reads TYPESAFE_BASE_URL (https://api.vakyn.com) and TYPESAFE_API_KEY from the environment.const client = new TypeSafeClient();const { answers } = await client.systemOne({  state: {    channel: "email",    customer: { plan: "team", seats: 12, months_active: 14 },    message: "Since this morning nobody on our team can sign in. We have a client demo at 3pm.",  },  questions: {    outage: noul("Is the customer unable to use the product?"),    team: choice("Which team should handle this?", {      billing: "Invoices, charges and refunds",      access: "Sign-in, passwords and permissions",      product: "Bugs and how-to questions",    }),    urgency: score("How soon does this need a reply?", ["Can wait", "Today", "Within the hour"]),  },});console.log(answers.outage.noul, answers.team.choice, answers.urgency.score);
Try it in the playground
  • noul(instructions?, criteria?), choice(instructions, criteria), score(instructions, levels); pass null for no instructions. score() needs at least two levels.
  • The result has model, answers and usage. Add .withResponse() to the call to also get requestId and the raw response.
  • await client.models.list() returns the array of models.

Errors and retries

Non-2xx responses reject with an APIError subclass carrying status, body, headers and requestId; RateLimitError also has retryAfterMs.

import {  APIConnectionError,  AuthenticationError,  BadRequestError,  RateLimitError,  score,  TypeSafeClient,  UnprocessableEntityError,} from "@typesafe-ai/sdk"; // Reads TYPESAFE_BASE_URL (https://api.vakyn.com) and TYPESAFE_API_KEY from the environment.const client = new TypeSafeClient();try {  const levels = Array.from({ length: 11 }, (_, i) => `level ${i}`); // one level too many  const { data, requestId } = await client    .systemOne({ state: "Rate this.", questions: { rating: score(null, levels) } })    .withResponse();  console.log(requestId, data.answers.rating.score);} catch (e) {  if (e instanceof BadRequestError) {    // 400: over a limit, or an unknown model    console.log(e.status, e.body.detail, e.requestId);  } else if (e instanceof UnprocessableEntityError) {    console.log(e.body.detail); // 422: the body does not match the schema  } else if (e instanceof AuthenticationError) {    console.log("check TYPESAFE_API_KEY"); // 401: missing, wrong or revoked key  } else if (e instanceof RateLimitError) {    console.log("server busy"); // 429 that outlasted the retries  } else if (e instanceof APIConnectionError) {    console.log("cannot reach the server"); // wrong base URL, server down, timeout  } else {    throw e;  }}

Retries: two by default, with backoff, on 408, 429 and 5xx and on connection errors, honoring retry-after. Override with retry: { maxRetries, … } on the client or per call. Timeouts are per attempt, in milliseconds (default 10,000); raise them for long documents on a CPU-only server. VAKYN MAX answers 402 when the balance is empty; see Errors.

Many requests

import { noul, TypeSafeClient } from "@typesafe-ai/sdk"; // Reads TYPESAFE_BASE_URL (https://api.vakyn.com) and TYPESAFE_API_KEY from the environment.const client = new TypeSafeClient();const messages = [  "Where is my parcel?",  "Please cancel my subscription at the end of the month.",  "Your app crashes when I open settings.",]; // The server queues what it can take and answers 429 beyond that;// the SDK retries 429 after the delay the server asks for.const results = await Promise.all(  messages.map((m) =>    client.systemOne({ state: m, questions: { cancel: noul("Does the customer want to cancel?") } }),  ),);results.forEach((r, i) => console.log(r.answers.cancel.noul.toFixed(2), messages[i]));

Differences from TypeSafe's hosted API

  • Use jev-latest or the name from models.list(); dated hosted model names are not available.
  • Keys start with vk_ and come from the VAKYN console or your own server.

Loading the docs…