Node.js Host API¶
The isola-core package exposes an async host-side API for compiling sandbox
templates and running code inside isolated runtimes from Node.js.
This page documents the embedding SDK that runs in your host process. For the Python modules available inside Python guests, see Python Guest API. For the JavaScript globals available inside JS guests, see JavaScript Guest API.
Install¶
Lifecycle¶
The normal flow is:
await buildTemplate(...)await template.create(...)await sandbox.start()await sandbox.loadScript(...)await sandbox.run(...)or iteratesandbox.runStream(...)sandbox.close()
import { buildTemplate } from "isola-core";
const template = await buildTemplate("python");
const sandbox = await template.create();
try {
await sandbox.start();
await sandbox.loadScript("def hello(name):\n return f'hello {name}'");
const result = await sandbox.run("hello", ["world"]);
console.log(result);
} finally {
sandbox.close();
}
Runtime Resolution¶
Most users can skip manual runtime management and let buildTemplate(...)
handle runtime downloads automatically.
When runtimePath is omitted from buildTemplate(...), the SDK resolves the
runtime automatically, downloads the matching release asset on first use,
verifies its SHA-256 digest, and caches it under ~/.cache/isola/runtimes/.
Supported runtime names:
"python""js"
Use version to resolve a specific release tag. To use a runtime you unpacked
yourself, pass runtimePath and, for Python runtimes, runtimeLibDir.
Core Types¶
buildTemplate(...)¶
Builds and returns a reusable sandbox template using an internal SandboxContext.
buildTemplate(...) accepts:
runtime:"python"or"js"runtimePath: directory or path used to initialize the runtime bundleversion: optional release tag to resolve when auto-downloading a runtimecacheDir: template cache directory, ornullto disable cachingmaxMemory: template memory limit in bytesprelude: code injected before user scriptsruntimeLibDir: runtime library directory for manually provided Python runtimesmounts:MountConfig[]env:Record<string, string>
SandboxContext¶
Advanced API for explicitly owning a template compilation context. It exposes
the same template-building behavior as the top-level helper, plus explicit
close() ownership when you need to manage the context directly.
SandboxTemplate¶
Instantiates sandboxes from a compiled template.
create(...) accepts:
maxMemory: per-sandbox memory limit in bytesmounts:MountConfig[]env:Record<string, string>hostcalls:Record<string, (payload: JsonValue) => Promise<unknown>>http:trueto use the built-infetchbridge, or(req: HttpRequest) => Promise<HttpResponse>for a custom outbound HTTP policyhttpHandler: legacy alias forhttp
Sandbox¶
Runs guest code inside an instantiated sandbox.
await sandbox.start();
await sandbox.loadScript(code);
const result = await sandbox.run(name, args);
Public methods:
await start()await loadScript(code)await run(name, args?, kwargs?) -> JsonValue | nullrunStream(name, args?, kwargs?) -> AsyncGenerator<Event>close()await sandbox[Symbol.asyncDispose]()
Call start() before loading scripts or executing functions.
Arguments¶
run(...) and runStream(...) accept positional JSON-like values directly:
Pass kwargs as the third argument:
Use Arg to pass a named argument:
import { Arg } from "isola-core";
const result = await sandbox.run("greet", [
new Arg("World", "name"),
new Arg("Hi", "greeting"),
]);
The second argument must always be the positional args array. If you need to
pass a single object as a positional argument, wrap it in that array:
sandbox.run("echo", [{ hello: "world" }]).
Hostcalls¶
Register host callbacks when the sandbox is created. Each handler receives the decoded payload for its call name and must return a serializable value.
Guest sandboxes invoke these handlers with their runtime-specific guest APIs:
- Python guests use
sandbox.asyncio.hostcall(...) - JS guests use top-level
await hostcall(...)
Those guest-side call sites are documented separately in Python Guest API and JavaScript Guest API.
import { buildTemplate } from "isola-core";
const template = await buildTemplate("python");
const sandbox = await template.create({
hostcalls: {
lookup_user: async (payload) => {
const { user_id } = payload as { user_id: number };
return { user_id, name: `user-${user_id}` };
},
},
});
await sandbox.start();
await sandbox.loadScript(
"from sandbox.asyncio import hostcall\n" +
"\n" +
"async def lookup_user(user_id):\n" +
" return await hostcall('lookup_user', {'user_id': user_id})\n",
);
const result = await sandbox.run("lookup_user", [7]);
Events and Results¶
run(...) resolves to the final return value directly:
Use runStream(...) when you need yielded values or process output:
for await (const event of sandbox.runStream("compute")) {
switch (event.type) {
case "result":
console.log("intermediate:", event.data);
break;
case "end":
console.log("final:", event.data);
break;
case "stdout":
console.log("stdout:", event.data);
break;
case "stderr":
console.error("stderr:", event.data);
break;
case "error":
console.error("error:", event.data);
break;
case "log":
console.log("log:", event.data);
break;
}
}
Event is a union of:
{ type: "result"; data: JsonValue }{ type: "end"; data: JsonValue | null }{ type: "stdout"; data: string }{ type: "stderr"; data: string }{ type: "error"; data: string }{ type: "log"; data: string }
Filesystem and Environment¶
Use MountConfig to mount host paths into the guest:
dir_perms and file_perms accept:
"read""write""read-write"
Environment variables can be supplied in both template and sandbox config via
env: { KEY: "value" }.
HTTP Bridge¶
When guest code makes outbound HTTP requests, the sandbox calls the configured
http bridge. Pass http: true to use the built-in Node fetch pass-through,
or provide your own async handler to enforce a custom HTTP policy.
The guest-side request APIs used inside the sandbox are documented in Python Guest API and JavaScript Guest API.
import type { HttpRequest, HttpResponse } from "isola-core";
async function http(request: HttpRequest): Promise<HttpResponse> {
return {
status: 200,
headers: { "content-type": "text/plain" },
body: Buffer.from("hello world"),
};
}
const sandbox = await template.create({ http });
Request and response shapes:
HttpRequest = { method, url, headers, body }HttpResponse = { status, headers?, body? }
HttpRequest.body is Buffer | null.
HttpResponse.body may be:
Buffernull- omitted
Errors¶
buildTemplate(...), start(), loadScript(...), and run(...) reject when
runtime setup or execution fails.
runStream(...) yields { type: "error", data: string } events for sandbox
execution failures, and may still throw for setup or transport failures that do
not surface as stream events.