Using the SDK from your VM

What every VM gets at boot (SUPERJOLT_API_URL, SUPERJOLT_ENV_TOKEN, SUPERJOLT_LLM_URL), and how to call the LLM (OpenAI SDK or @superjolt/sdk), send/read email, and react to events — all off the one token.

Every Superjolt VM boots already authenticated to the platform. The provisioner writes a handful of env vars into the VM (/etc/superjolt-env, sourced before your app starts), and the SDK — or a stock OpenAI client — reads them. There are no provider API keys anywhere in your app; the environment token is the only credential.

What’s in the box (injected env vars)

VarWhat it’s for
SUPERJOLT_ENV_TOKENThe one credential. Authenticates the SDK and the OpenAI-compatible LLM endpoint; resolves your project + environment server-side.
SUPERJOLT_API_URLBase URL for the Superjolt API — the SDK’s default.
SUPERJOLT_LLM_URLOpenAI-compatible LLM base URL (point any AI library here).
SUPERJOLT_PROJECT_IDYour project id (informational).
SUPERJOLT_WEBHOOK_SECRETVerifies signed webhook envelopes, if you register a callback URL.

Install the SDK once:

npm install @superjolt/sdk

LLM — two ways, both zero-config

Any AI library, unmodified — point it at the injected OpenAI-compatible URL:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: process.env.SUPERJOLT_LLM_URL,
  apiKey:  process.env.SUPERJOLT_ENV_TOKEN,
});

const r = await client.chat.completions.create({
  model: 'gpt-4o-mini', // a concrete model id — see `llm.models()`
  messages: [{ role: 'user', content: 'summarise this' }],
});

The Superjolt SDK — same models, plus server-side platform tools (the gateway runs the tool loop for you):

import { llm } from '@superjolt/sdk';

const r = await llm.complete({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'refund order 123' }],
  tools: ['billing.refund', 'email.reply'], // names, not schemas
});

Pass concrete model ids (there are no aliases). Cheaper models stretch the free lifetime allowance furthest in dev. See LLM gateway for the model menu, allowance, and billing.

Email — send, read, and react

Every project has an inbox (<slug>@sandbox.superjolt.email out of the box; connect your own domain for production). All off the same token:

import { email, events } from '@superjolt/sdk';

// send
await email.send({ from: '[email protected]', to: '[email protected]', subject: 'hi', text: 'hello' });

// read the inbox
const inbox = await email.list({ folder: 'inbox', limit: 20 });
const full  = await email.read(inbox[0].id);

// react the moment mail arrives — no webhook, no public endpoint
events.listen(async (e) => {
  if (e.type === 'email.received') {
    await email.reply(e.data.messageId, { text: 'got it — looking into this now.' });
  }
});

See Email for the two tiers (sandbox vs your own domain), the three surfaces (SDK, webmail, IMAP), and sending limits.

Local dev — same code, same token

A project is free until you run a VM, so you build the whole app locally against the environment’s token. Get it two ways:

  • Ask your Superjolt MCP agent to set the project up — it mints the token and writes .env.local.
  • Grab it from the dashboard — the Config tab shows each environment’s injected SUPERJOLT_* vars; hit Reveal secrets and copy the ready-made .env.local block (SUPERJOLT_API_URL, SUPERJOLT_PROJECT_ID, SUPERJOLT_ENV_TOKEN, SUPERJOLT_LLM_URL).

Either way you get the same value a VM boots with — both read the environment’s one cached token. Tokens are neutral (tk_…) and resolve their environment server-side, so the exact same code runs unchanged once you deploy. LLM inference is real in local dev too, drawn from the free allowance. Run superjolt pull-config to pull this environment’s config vars into .env.local on top.