Quickstart for platform users

Provision isolated storage for your customers' runtimes end to end: tenant, grant, signed mount ticket, inject, mount, revoke.

For platforms whose backends provision storage on behalf of their own customers: sandbox runtimes (Daytona, Modal, your own), AI agent platforms, ML training services, anything where each of your customers gets isolated storage they don't sign up to Tonbo for. End-to-end: sign up, model a tenant, grant a runtime id workspace access, create a short-lived mount ticket, inject the config into the customer runtime, mount, run, clean up.

Read this if your backend is provisioning storage per customer task. For the single-machine "I just want to mount my workspace" path, see Quickstart instead.

Prerequisites: a Node.js backend, an API key from your profile at user.tonbo.dev. Your sandbox VM image needs the artifacts CLI installed (one line at image-build time).

1. Sign up and get an API key

Register at user.tonbo.dev. From your profile, generate an API key.

export TONBO_API_KEY=<your key>

This key authenticates your backend. Never inject it into customer-facing runtimes.

2. Install the SDK

npm install @tonbo/artifacts
import { Artifacts } from '@tonbo/artifacts';
const artifacts = new Artifacts();

3. The mental model

A short chain: your root user (this API key) owns tenants (your customers); each tenant scopes runtimes (your tasks or sandboxes, identified by an opaque id you choose); an access grant lets a tenant or runtime mount a workspace; and a mount ticket is the short-lived signed file a runtime mounts with. Your root credential stays on your backend; runtimes receive tickets only.

See Multi-tenancy model for the full diagram and lifecycle, and Temporary mount credentials for the authorization detail.

4. Choose a runtime id for the task

const tenantSlug = 'acme';
const runtimeId = taskId;

The tenant is your customer or account boundary; the runtime id is the access scope for one container, VM, task, or agent run. Both are plain strings you choose. You do not pre-create a runtime row.

5. Provision or choose a workspace

Workspace provisioning runs through the CLI today: the create step initializes the workspace's storage from the machine that runs it, so it isn't available over the plain HTTP API. Run the CLI from your backend host with the same API key (no browser login involved), or pre-provision a pool of workspaces ahead of task time:

export TONBO_API_KEY=<your key>
artifacts workspace create task-4711

Workspaces are the filesystem namespaces. Some platforms create one workspace per task; others reuse a workspace across several runtimes under the same tenant. If your platform needs to provision workspaces over the HTTP API, reach out.

6. Create a short-lived mount ticket

This is the one call that matters. createMountTicket auto-creates the tenant (if new) and a runtime-scoped grant, then signs a short-lived ticket — all in one request.

const { mount_ticket } = await artifacts.platform.createMountTicket(tenantSlug, runtimeId, {
  workspace: `<your-handle>/task-${taskId}`,
  mode: 'rw',
  ttlSeconds: 3600,
});

What you should see: a signed mount ticket expiring one hour from now. It authorizes this runtime to mount that one workspace only, in rw mode. Your account API key never leaves your backend.

That single call is the fast path. You only need explicit createTenant / createAccessGrant calls for tenant metadata, a tenant-wide grant shared by every runtime, or to authorize a runtime without issuing a ticket yet. See Tenants and grants.

7. Inject the mount ticket into your runtime

The runtime needs the mount ticket available as a secret-backed file before artifacts mount runs:

/run/tonbo/artifacts/mount-ticket.json

How you inject depends on your orchestration. The common shapes are a Kubernetes secret volume, an init-time file write, or a microVM/containerd secret mount. The mount-ticket.json file must contain the JSON-serialized mount ticket returned by Orchestrator.

volumes:
  - name: tonbo-artifacts
    secret:
      secretName: tonbo-mount
      defaultMode: 0400
      items:
        - key: mount-ticket.json
          path: mount-ticket.json
containers:
  - name: agent
    volumeMounts:
      - name: tonbo-artifacts
        mountPath: /run/tonbo/artifacts
        readOnly: true

The Orchestrator returns { mount_ticket } to your backend. Your platform control plane delivers the config to the worker; Orchestrator does not relay or supervise the worker command.

8. Mount and use it in the VM

In your VM template, install the CLI once at image-build time (see Install). At VM boot, mount the workspace:

artifacts mount --ticket-file /run/tonbo/artifacts/mount-ticket.json /mnt/work

The customer's agent code uses /mnt/work like a regular local directory. No SDK in their code, no Tonbo awareness, no special API:

import fs from 'node:fs/promises';
await fs.writeFile('/mnt/work/output.txt', 'hello');

This is the value-prop your platform delivers: persistent shared filesystem across your customers' runtimes, using their existing code.

9. Tear down when the task ends

Revoke the runtime's grant, and delete the workspace if it was task-scoped:

await artifacts.platform.revokeAccessGrants({ tenantSlug, runtimeId });
await artifacts.workspaces.delete(`<your-handle>/task-${taskId}`);

Revocation propagates within about one second; the mount starts erroring on the next syscall. For revoking by grant id, tearing down a whole tenant, tenant-wide grants, and authorize-without-issue, see Tenants and grants.

Next steps