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)
| Var | What it’s for |
|---|---|
SUPERJOLT_ENV_TOKEN | The one credential. Authenticates the SDK and the OpenAI-compatible LLM endpoint; resolves your project + environment server-side. |
SUPERJOLT_API_URL | Base URL for the Superjolt API — the SDK’s default. |
SUPERJOLT_LLM_URL | OpenAI-compatible LLM base URL (point any AI library here). |
SUPERJOLT_PROJECT_ID | Your project id (informational). |
SUPERJOLT_WEBHOOK_SECRET | Verifies 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.localblock (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.