@miosa/sdk
v1.2.28
Published
TypeScript SDK for the MIOSA API - cloud VM desktop infrastructure for AI agents
Maintainers
Readme
@miosa/sdk (TypeScript)
Official TypeScript / JavaScript SDK for MIOSA — the AI cloud platform for sandboxes, computers, deployments, and managed data.
Ships ESM + CJS. Full TypeScript types included — no @types/ package needed. Node.js 18+.
Install
npm install @miosa/sdk
# or
pnpm add @miosa/sdk
# or
yarn add @miosa/sdk
# or
bun add @miosa/sdkQuickstart
import { Miosa } from "@miosa/sdk";
const miosa = new Miosa({ apiKey: "msk_live_..." });
// Create or resume a persistent sandbox workspace, then work inside it.
const sbx = await miosa.sandboxes.createAgentWorkspace({
name: "my-build",
externalWorkspaceId: "customer-workspace-123",
});
await sbx.files.write("/workspace/hello.ts", `console.log("hello from miosa")`);
const result = await sbx.exec("npx tsx /workspace/hello.ts");
console.log(result.stdout); // hello from miosa
// Expose a live preview URL
const url = await sbx.expose(3000);
console.log(url); // https://3000-<slug>.sandbox.miosa.ai
// Keep progress. Pause preserves the workspace so the next session can resume.
await sbx.snapshots.create("after-hello-world");
await sbx.pause();What's included
| Resource | Description |
|---|---|
| miosa.sandboxes | Lightweight code-execution VMs — exec, files, snapshots, previews |
| miosa.computers | Full Linux desktop VMs with desktop control for agents |
| miosa.deployments | Versioned production releases with rollback |
| miosa.databases | Managed Postgres / Redis lifecycle |
| miosa.storage | S3-compatible object storage |
| miosa.volumes | Persistent block storage |
| miosa.apiKeys | Programmatic API key management |
| miosa.usage | Usage reports per workspace, per external tenant |
| miosa.settings | Workspace config, branding, BYOK provider keys |
| miosa.webhooks | Outgoing tenant webhooks — CRUD, test, delivery history |
| miosa.openComputers | BYOC host management — register your own machines |
| miosa.devices | Unified device facade for sandbox/computer list, exec, files, previews |
| miosa.connectors | Provider credentials and short-lived runtime tokens |
| miosa.runtimeEnv | Inherited tenant/workspace/project runtime environment variables |
| miosa.completions | OpenAI-compatible chat completions with SSE streaming |
| miosa.embeddings | OpenAI-compatible embedding vectors |
Connect vs Egress
Use Connect when your product needs to manage provider credentials for agents, sandboxes, computers, or deployments. Connect owns the product-level contract: connectors, installations, project links, inherited defaults, short-lived tokens, white-label attribution, and runtime bindings.
Use Egress when you need the low-level security boundary: encrypted secret
storage, outbound host allowlists, placeholder token exchange, and audit logs.
Egress is the enforcement layer under Connect. Most white-label apps should
call miosa.connectors and runtime binding helpers first; only call
miosa.secrets, miosa.network, or miosa.audit when you are building
security/admin controls directly.
// Product-level credential setup.
const connector = await miosa.connectors.create("anthropic", {
name: "workspace-claude",
scope: "workspace",
externalWorkspaceId: "clinic-iq",
value: process.env.ANTHROPIC_API_KEY,
});
// Runtime-level materialization: the sandbox sees ANTHROPIC_API_KEY, but your
// app does not get the raw provider key back from MIOSA.
await miosa.connectors.materializeDefaults({
workspaceId: "workspace-id",
resourceType: "sandbox",
resourceId: sbx.id,
target: "agent",
externalWorkspaceId: "clinic-iq",
});Agent workspaces
For AI builders, code assistants, and white-label agent products, the sandbox
is the development machine. Do not run builds on the user's laptop and upload
the result as the primary flow. Create or resume a stable sandbox workspace,
write files under /workspace, run package installs/tests/builds inside the
sandbox, expose previews from the sandbox, and publish from that sandbox.
const sbx = await miosa.sandboxes.getOrCreate({
name: "acme-marketing-page",
templateId: "miosa-sandbox",
persistent: true,
timeoutSec: 86_400,
idleTimeoutSec: 1800,
snapshotExpirationDays: 30,
keepLastSnapshots: 1,
externalWorkspaceId: "acme",
externalUserId: "jane",
waitUntilReady: true,
});
await sbx.files.writeMany([
{ path: "/workspace/package.json", content: `{"scripts":{"dev":"vite --host 0.0.0.0"}}` },
{ path: "/workspace/index.html", content: `<main id="app"></main>` },
]);
for await (const event of sbx.exec.stream("cd /workspace && npm install && npm run dev -- --port 3000")) {
console.log(event);
}
const preview = await sbx.previews.create(3000);
console.log(preview.url);For platform agents that plan work outside the sandbox and then hand execution to a runtime inside the sandbox/computer, use the unified device API:
await miosa.agentRuntimeProfiles.create({
workspaceId: "clinic-workspace",
name: "ClinicIQ Claude Code",
runtime: "claude-code",
isDefault: true,
connectors: [
"anthropic/cliniciq",
{
uid: "refero",
type: "mcp",
managed: true,
serverUrl: "https://api.refero.design/mcp",
},
],
env: {
ANTHROPIC_API_KEY: "miosa-managed:anthropic/cliniciq",
},
metadata: {
model: "claude-opus-4.8",
whiteLabelClient: "cliniciq",
},
});
await miosa.devices.writeFile(sbx.id, {
path: "/workspace/PLAN.md",
content: "# Build plan\nUse the customer profile and export /workspace/out.",
});
const build = await miosa.devices.exec(sbx.id, {
command: "npm install && npm run build",
cwd: "/workspace",
timeoutMs: 600_000,
});
const artifact = await miosa.devices.readFile(sbx.id, {
path: "/workspace/out/report.pdf",
});createAgentWorkspace() is a convenience wrapper around getOrCreate() with
builder defaults: a 24-hour activity cap, thirty-minute idle snapshot/pause,
readiness waiting, 30-day snapshot-retention metadata, keep-last-snapshot
metadata, and metadata that marks the sandbox as an agent workspace.
That mirrors the Vercel-style persistent-sandbox model without keeping CPU
running forever: activity extends the running session, idle workspaces are
checkpointed and paused, and later sessions resume from the checkpoint. Use
extend(86_400) before long builds, pause() when the user is done for now,
resume() for the next session, snapshots.create() for manual checkpoints,
and destroy() only when the workspace should be permanently deleted.
Sandbox sub-resources
Every Sandbox instance exposes composable sub-resources:
const sbx = await miosa.sandboxes.create();
// Files
await sbx.files.write("/workspace/app.py", "print('hi')");
const text = await sbx.files.readText("/workspace/app.py");
const entries = await sbx.files.list("/workspace");
const stat = await sbx.files.stat("/workspace/app.py");
// Exec — callable directly, or via .exec.run / .exec.stream
const result = await sbx.exec.run("python /workspace/app.py");
for await (const event of sbx.exec.stream("tail -f /var/log/app.log")) {
if ("line" in event) console.log(event.line);
}
// Snapshots
const snap = await sbx.snapshots.create("pre-migration");
const restored = await sbx.snapshots.restore(snap.id);
await sbx.snapshots.delete(snap.id);
// Previews
const preview = await sbx.previews.create(8000);
console.log(preview.url);
// Live SSE event stream
for await (const event of sbx.events.stream()) {
console.log(event.type, event.data);
}
// Pause / resume
await sbx.pause();
await sbx.resume();Publish from sandbox
Preview is mutable; publish creates a durable deployment version. Static output is served by MIOSA's artifact plane. Dynamic apps run in reconciled runtime VMs.
const deployment = await sbx.deploy({
name: "clinic-intake",
outputPath: "/workspace/dist",
entrypoint: "index.html",
});
console.log(deployment.url ?? deployment.deployment?.public_url);For dynamic/full-stack apps:
const deployment = await sbx.deploy({
name: "clinic-intake-api",
outputPath: "/workspace",
runCommand: "npm start",
port: 3000,
domain: "intake.apps.cliniciq.com",
});For workspace App Engine, publish from the same sandbox but choose the App Engine target:
const deployment = await sbx.deployDocker({
name: "lead-magnet",
path: "/workspace",
buildCommand: "npm run build",
runCommand: "npm start",
port: 3000,
});
console.log(deployment.url ?? deployment.public_url);App Engine runs app containers inside the workspace's dedicated MIOSA App Engine appliance VM. It is separate from normal MIOSA dynamic runtime VMs and is useful when a workspace needs many small apps, funnels, lead magnets, APIs, or client sites.
Always display the server-returned url / public_url. Do not hardcode
preview.miosa.app, api.miosa.app, or <tenant>.miosa.app.
Desktop control (Computers)
const computer = await miosa.computers.create({
name: "agent-desktop",
template_type: "miosa-desktop",
// Canonical fast desktop profile: 2 vCPU / 4 GB.
size: "small",
});
await computer.start();
await computer.wait(5);
const png = await computer.screenshot(); // Uint8Array
await computer.click(640, 400);
await computer.type("hello world");
await computer.key("Return");
await computer.scroll("down", 3);
await computer.drag(100, 100, 400, 400);
const result = await computer.bash("ls -la /home/user");
console.log(result.output);
// Authenticated platform desktop links are passwordless. Raw external viewer
// links are password-gated; rotate the one-time password when you need to share
// that raw URL outside the platform.
const rotated = await computer.rotateViewerPassword();
console.log(rotated.viewer_password);
await computer.destroy();White-label / multi-tenant
const sbx = await miosa.sandboxes.create({
externalWorkspaceId: "dental-office-123",
externalUserId: "dr-smith-456",
});
const sandboxes = await miosa.sandboxes.list({
externalWorkspaceId: "dental-office-123",
});White-label domain layers are separate:
sandbox preview: https://<port>-<slug>.sandbox.<preview-domain>
durable deployment: https://<slug>.<deployment-domain>
custom domain: https://app.customer.comTenant preview-domain management is available through miosa.tenant.previewDomain.
Tenant deployment-domain routing exists server-side; SDKs should consume
deployment public_url instead of reconstructing it.
Error handling
import { MiosaError } from "@miosa/sdk";
try {
await miosa.sandboxes.get("sbx_doesnt_exist");
} catch (e) {
if (e instanceof MiosaError) {
console.error(`${e.status} ${e.code}: ${e.message}`);
}
}The SDK retries 429 and 5xx automatically (3 retries, exponential backoff + jitter). Set maxRetries: 0 to disable.
Configuration
| Option | Env var | Default |
|---|---|---|
| apiKey | MIOSA_API_KEY | — |
| baseUrl | MIOSA_BASE_URL | https://api.miosa.ai/api/v1 |
| timeout | — | 30 000 ms |
| maxRetries | — | 3 |
const miosa = new Miosa({
apiKey: process.env.MIOSA_API_KEY!,
timeout: 60_000,
maxRetries: 5,
});Links
License
MIT
