Volumes
E2B enables volumes per team. On a team without them, deploying a volume fails with VolumesNotEnabled.
Declare a shared volume
Section titled “Declare a shared volume”import * as E2B from "@alchemy.run/e2b";
export const Cache = E2B.Volume("Cache", {});Changing name replaces the volume and loses its files.
Mount it into a declared sandbox
Section titled “Mount it into a declared sandbox”import * as E2B from "@alchemy.run/e2b";import { Agent } from "./Agent.ts";import { Cache } from "./Storage.ts";
export const Builder = E2B.Sandbox("Builder", { template: Agent, mounts: [{ volume: Cache, path: "/cache" }],});E2B attaches volumes only when a sandbox is created, so changing mounts replaces the sandbox.
Mount it from a Worker
Section titled “Mount it from a Worker”// in the Worker's constructionconst cache = yield* E2B.MountVolume(Cache, { path: "/cache" });const sandboxes = yield* E2B.CreateSandbox(Agent);// in fetchconst sandbox = yield* sandboxes.create({ mounts: [cache] });MountVolume returns a reference with the entry’s fields, so it goes straight into mounts. Provide E2B.MountVolumeLive.
Mount it in a template program
Section titled “Mount it in a template program”import * as E2B from "@alchemy.run/e2b";import * as Effect from "effect/Effect";import { FileSystem } from "effect/FileSystem";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { Cache } from "./Storage.ts";
export default class Api extends E2B.Template<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const cache = yield* E2B.MountVolume(Cache, { path: "/cache" }); const fs = yield* FileSystem; return { fetch: Effect.gen(function* () { const files = yield* fs.readDirectory(cache.path); return yield* HttpServerResponse.json(files); }).pipe(Effect.orDie), }; }).pipe(Effect.provide(E2B.MountVolumeLive)),) {}Inside a template program, the mount becomes part of the template. Every sandbox created from it, with CreateSandbox(Api) or E2B.Sandbox({ template: Api }), mounts the volume.
A volume per user
Section titled “A volume per user”const volumes = yield* E2B.CreateVolume();// in fetch:const home = yield* volumes.getOrCreate(`home-${user}`);const sandbox = yield* sandboxes.create({ mounts: [{ volume: home, path: "/home/user/work" }] });Provide E2B.CreateVolumeHttp. Runtime volumes are not deleted when you destroy the Worker: call volumes.delete(home.volumeId) when the user goes away.
Read files without a sandbox
Section titled “Read files without a sandbox”const reports = yield* E2B.ReadVolume(Reports);// in fetch:const report = yield* reports.readText("/report.json");const entries = yield* reports.list("/");Provide E2B.ReadVolumeHttp. The client uses the volume’s own token, looked up with the host’s API key.
Write files without a sandbox
Section titled “Write files without a sandbox”const inputs = yield* E2B.WriteVolume(Inputs);// in fetch:yield* inputs.write("/task.json", JSON.stringify(task));yield* inputs.makeDir("/results");yield* inputs.remove("/old");E2B.ReadWriteVolume does both. A runtime volume’s files is a read-write client too.