Overview

Oblien Documentation

Oblien gives you cloud workspaces that boot in milliseconds and run anything.

Every workspace is a hardware-isolated microVM with its own kernel, its own memory, and full root access. Use them to give your AI agent an environment it can control, deploy a service with a public URL, or spin up a dev environment you can SSH into. The workspace is the only primitive - what it becomes is up to you.

How people use workspaces

The most common pattern: give your AI agent a permanent workspace. It runs there, holds state, and stays alive between conversations. From that home, it can create more workspaces on demand - to isolate tasks, store user data, run untrusted code, or deploy a full application.

But agents aren't required. You can also:

  • Deploy a service - Run an API server, a queue worker, or a database as a permanent workspace. Map it to a custom domain.
  • Develop remotely - SSH into a workspace, install your stack, expose a port for live preview. The workspace is your dev machine.
  • Run CI/CD - Spin up ephemeral workspaces per build, run tests in full isolation, auto-destroy when done.
  • Execute untrusted code - Air-gapped throwaway VMs that auto-delete after a TTL. No internet, no persistence.
  • Host per-user sandboxes - One workspace per customer with scoped networking, credit quotas, and full isolation.
  • Multi-tenant SaaS - One namespace per customer with resource caps, spending quotas, overdraft policies, and per-namespace usage analytics.

Or combine them: an agent iterates in a dev workspace, then promotes it to production when it's ready.

Your Agent's HomePERMANENTmicroVMPersistent state, framework, SDK, API token - creates and controls workspacesAgent code · Persistent FS · SDK · API token · SSH · Public accessPRIVATE INTERNAL NETWORKQuick TaskRun code, auto-deleteTTL · air-gappedUser DataPer-user isolated DBpermanent · privateDeploymentLive app, public URLpermanent · publicTemp → permanent · private → public · air-gapped → connected - agent decides at runtimeEvery workspace is its own hardware-isolated microVM - not a container

Agent workspaces

The most powerful pattern: your agent gets a permanent workspace as its home. From there, it creates more workspaces on demand - for tasks, data, deployments, or anything else. Each is a separate VM, isolated from the agent and from each other:

  • Quick task - Execute untrusted code for 30 seconds in an air-gapped VM. Auto-deletes when done.
  • User data store - A permanent workspace per user running Postgres. No internet access. Only the agent can reach it over the private network.
  • Dev environment - A long-running workspace where the agent writes code, starts a dev server, and exposes a live preview URL.
  • Production deployment - The same workspace, mapped to a custom domain. It's a running server now.
  • SaaS sandbox - On-demand workspaces per user request, scoped so each sandbox can only access that user's data. Organized by namespace with spending quotas per customer.
  • Batch worker - Spin up 10 temporary workspaces in parallel, process a pipeline, collect results, auto-destroy.

Temporary or permanent. Private or public. Air-gapped or wired to other VMs. You decide at creation time - and you can convert between modes at any point. A temporary sandbox can become a long-lived deployment. A private workspace can get a public URL.

There are no fixed tiers. You compose workspaces however the problem demands.

Scoped control - no one gets god mode

API tokens are scoped. Whether it's your agent or your backend calling the API, permissions are explicit:

  • Which workspaces it can create and destroy
  • Which workspaces it can reach over the internal network
  • Which external hosts it can call
  • Whether it can expose ports publicly

You give each caller exactly enough power for its job - not the keys to everything.

Private networking - isolated by default, wired on demand

Every workspace is invisible to every other workspace by default - even on the same account. No implicit trust, no shared network. If you want workspace A to reach workspace B, you whitelist A's IP in B's ingress rules. Nothing else gets through.

Workspaces that are connected talk over Oblien's private internal network on 10.x.x.x IPs - direct VM-to-VM, no public internet, no roundtrip. You also control outbound: lock a workspace to only call specific external hosts or internal IPs, with everything else blocked at the network level.

Public access - expose ports, not VMs

Your workspace never gets a public IP. When you expose a port, Oblien's edge receives traffic, terminates HTTPS, and proxies it to your workspace's internal address. The VM itself stays off the internet - only the specific port you expose becomes reachable, only through the proxy.

  • Preview URLs - Expose port 3000 → get https://a1b2c3.preview.oblien.com instantly
  • Custom domains - Map app.yourdomain.com to any workspace port, TLS provisioned automatically
  • Revoke any port instantly - the URL stops working immediately
  • Up to 20 ports per workspace, each with its own URL

What this looks like

import Oblien from 'oblien';

const client = new Oblien({ clientId, clientSecret });
const ws = client.workspaces;

// ── Deploy a service ─────────────────────────────────────────
const api = await ws.create({
  name: 'production-api',
  image: 'node-20',
  mode: 'permanent',
  config: { cpus: 2, memory_mb: 4096 },
});
await ws.workloads.create(api.id, {
  name: 'server',
  cmd: ['node', 'server.js'],
  env: { PORT: '3000' },
});
await ws.publicAccess.expose(api.id, {
  port: 3000,
  domain: 'api.yourdomain.com',
});
// Live at https://api.yourdomain.com

// ── Your agent's permanent home ───────────────────────────────
const agent = await ws.create({
  name: 'my-agent',
  image: 'node-20',
  mode: 'permanent',
  config: { cpus: 4, memory_mb: 8192 },
});

// ── A throwaway sandbox - runs code and disappears ───────────
const sandbox = await ws.create({
  image: 'python-3.12',
  config: { ttl: '5m', remove_on_exit: true, allow_internet: false },
});
const sbRt = await ws.runtime(sandbox.id);
await sbRt.exec.run(['python3', '/task/run.py']);
// sandbox is gone

// ── A permanent data workspace for one user ──────────────────
const userData = await ws.create({
  name: `data-${userId}`,
  image: 'postgres-16',
  mode: 'permanent',
  config: {
    allow_internet: false,
    ingress: [agent.info.internal_ip],  // Only the agent can reach it
  },
});

// ── On-demand scoped sandbox per user request ────────────────
async function handleUserRequest(userId: string, code: string) {
  const userSandbox = await ws.create({
    image: 'node-20',
    config: {
      ttl: '10m',
      egress: [userData.info.internal_ip],  // Scoped - can only reach this user's data
      allow_internet: false,
    },
  });
  const rt = await ws.runtime(userSandbox.id);
  await rt.files.write({ fullPath: '/app/index.js', content: code });
  const result = await rt.exec.run(['node', '/app/index.js']);
  return result.stdout;  // Auto-deletes after TTL
}

One workspace or twenty. Permanent or 30 seconds. Private or public. You compose them however the problem demands.

Workspace capabilities

CapabilityDescription
Instant bootWorkspaces start in milliseconds - any Docker image
Command executionRun any command or long-running process inside the VM
File system APIRead, write, and manage files without SSH
WebSocket terminalFull browser or programmatic terminal with scrollback
Managed workloadsBackground processes with SSE log streaming and restart policies
Public endpointsExpose any port via HTTPS preview URL instantly
SSH gatewayConnect over SSH without a public IP or VPN
SnapshotsCapture and restore workspace state at any point
Live metricsCPU, memory, disk, and network streamed in real-time
Internal networkingPrivate IP communication between workspaces, no public exposure
Firewall controlPer-workspace ingress/egress rules, air-gap mode, dedicated outbound IP
NamespacesGroup workspaces by customer or environment with resource limits, spending quotas, and overdraft policies

Works with your stack

Oblien is not tied to any specific framework. If it runs code, it runs on Oblien.

AI agent frameworks

FrameworkPattern
Claude CodeDeploy as a persistent workload - survives reconnects, no process management needed
OpenCodeRun inside a workspace, point it at any model endpoint
OpenHandsMount workspace filesystem as the agent's working directory
LangChain / LangGraphWrap as a Tool - execute_code, run_browser, read_file, etc.
CrewAIEach agent or crew member gets its own isolated task workspace
AutoGenUse workspace exec as the code execution backend instead of Docker
Your own codeAny Python, Node.js, Go, or shell process running in a VM - no SDK required if you prefer REST

Languages & runtimes

StackHow
Node.jsimage: 'node-20' - npm, yarn, pnpm all work
Pythonimage: 'python-3.12' - pip, poetry, conda
Goimage: 'go-1.22' - native compilation
Rustimage: 'rust-1' - cargo, full toolchain
Postgresimage: 'postgres-16' - persistent database workspace
Docker imageAny public or custom Docker image as base

The pattern for agents: one permanent workspace is the agent's home, and it creates short-lived task workspaces for anything risky, heavy, or untrusted. For services and dev environments, the workspace itself is the product.

Documentation

Section
Use CasesArchitecture patterns - agents, services, dev environments, sandboxes
ArchitectureIsolation model, security stack, internal networking
Workspace docsFull workspace API - SDK, REST, concepts, billing
QuickstartRunning your first workspace in 5 minutes
API ReferenceEvery endpoint with SDK + REST + cURL examples
NamespacesMulti-tenant isolation, resource limits, quotas, and overdraft
Plans & CreditsResource limits and how billing works

Start building

npm install oblien
import Oblien from 'oblien';

const client = new Oblien({
  clientId: process.env.OBLIEN_CLIENT_ID!,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET!,
});

const ws = client.workspaces;

// Permanent workspace - runs a service, an agent, or a dev environment
const home = await ws.create({ image: 'node-20', mode: 'permanent' });

// Temporary workspace - runs a task and disappears
const task = await ws.create({
  image: 'python-3.12',
  config: { ttl: '5m', remove_on_exit: true },
});

// Turn any workspace into a deployment
const url = await ws.publicAccess.expose(home.id, { port: 3000 });
# Permanent workspace
curl -X POST https://api.oblien.com/workspace \
  -H "X-Client-ID: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "image": "node-20", "mode": "permanent" }'

# Temporary workspace - auto-deletes after TTL
curl -X POST https://api.oblien.com/workspace \
  -H "X-Client-ID: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "image": "python-3.12", "config": { "ttl": "5m", "remove_on_exit": true } }'

# Expose any workspace to the internet
curl -X POST https://api.oblien.com/workspace/$WORKSPACE_ID/public-access \
  -H "X-Client-ID: $CLIENT_ID" \
  -H "X-Client-Secret: $CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "port": 3000 }'

5-minute quickstart
Workspace API reference
Get your API keys