On this page

Files & Exec

The Files and Exec APIs are how you (or an AI agent) interact with a Sandbox. Together they’re the substrate for everything else: generating code, running builds, starting servers.

Files

Write

Parent directories are created as needed. Existing files are overwritten.

Read

const content = await sandbox.files.read("/workspace/package.json")
const parsed = JSON.parse(content)
curl https://api.miosa.ai/api/v1/sandboxes/$SBX/files/read?path=/workspace/package.json 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Export generated artifacts

Use exports when an agent creates files that a user should download from your product: HTML, PDFs, CSVs, ZIPs, screenshots, reports, or build folders.

For one file, exports return a direct download URL for that file. For multiple files, exports return an archive download URL. This is the same low-level model as copying or downloading sandbox files: the sandbox remains the working filesystem, and your product decides which paths become user-visible artifacts.

Use this pattern for artifact products:

1. Agent writes files under /workspace/artifacts or /workspace/dist.
2. Your backend calls createExport with the exact paths users should receive.
3. Your UI stores the returned export descriptor on the task or run.
4. User clicks Download.
5. Your backend streams the direct file or tar archive from MIOSA.

Examples:

Agent outputExport path
Landing page HTML/workspace/dist/index.html
Built app folder/workspace/dist
PDF report/workspace/artifacts/report.pdf
Sales CSV/workspace/artifacts/leads.csv
Screenshot set/workspace/artifacts/screenshots
Generated project/workspace or a filtered build folder

Do not make users scrape files out of terminal output. If a run produces a deliverable, turn it into an export and attach it to the run, task, or project record in your product.

For agent platforms, treat the sandbox filesystem as the working surface and exports as the user-facing contract. The agent can create many intermediate files under /workspace, but your backend should promote only approved paths into named artifacts.

Product patternWorking pathsExported artifact
Lovable/Replit/Genspark-style app builder/workspace, /workspace/distsource ZIP, build folder, preview, deployment URL
Polsia-style operator/workspace/research, /workspace/artifactsreports, CSVs, campaign copy, generated app bundles
cofounder.co-style company OS/workspace/agents, /workspace/receipts, /workspace/artifactsmilestone documents, decisions, status reports
Nebula-style virtual deviceshared /workspace plus computer screenshotsselected files, screenshots, logs, device receipts

Store the export id, label, paths, size, MIME type when available, and download URL on your own run record. That gives users a stable artifact history even if the sandbox later pauses, forks, or continues generating new files.

List

const entries = await sandbox.files.list("/workspace")
for (const e of entries) {
  console.log(e.type, e.path, e.size)
}
curl https://api.miosa.ai/api/v1/sandboxes/$SBX/files/list?path=/workspace 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Watch

Stream filesystem events:

for await (const event of sandbox.files.watch("/workspace")) {
  console.log(event.type, event.path)
  // event.type: "create" | "modify" | "delete"
}

Watch is implemented as Server-Sent Events. See Events for the SSE event shape.

Filesystem layout

PathPurpose
/workspaceWorking directory; this is where agents write app code
/home/sandboxUser home
/tmpTemporary scratch (cleared on sandbox destroy)
/opt/venvPre-installed Python virtualenv (miosa-sandbox and Python templates)
/usr/local/binSystem binaries

Generally, write inside /workspace and let your build tooling handle node_modules, virtualenvs, etc. Production publish freezes /workspace (excluding cache dirs) as the source snapshot. See Publishing.

Exec

Run commands inside the sandbox.

One-shot

Blocks until the command exits (or timeoutMs elapses). Returns exit_code, stdout, stderr, and duration_ms.

Detached (long-running servers)

await sandbox.exec({
  cmd: "node",
  args: ["server.js"],
  cwd: "/workspace",
  detached: true,
})

Returns immediately with a job_id. The server keeps running. Use Previews to expose its port.

Streaming

For real-time stdout/stderr (e.g. tail an agent’s compile output):

for await (const chunk of sandbox.exec.stream({
  cmd: "pnpm",
  args: ["dev"],
})) {
  if (chunk.type === "stdout") process.stdout.write(chunk.data)
  if (chunk.type === "stderr") process.stderr.write(chunk.data)
  if (chunk.type === "exit") console.log("exit:", chunk.exit_code)
}

Implemented as SSE. See Streaming Exec.

Terminal

Need an interactive PTY (for remote dev or AI agents driving CLIs)?

const terminal = await sandbox.terminal()
terminal.send("ls /workspace\n")
for await (const out of terminal.output) {
  process.stdout.write(out)
}

Terminals are WebSocket-based with xterm.js-compatible ANSI passthrough. See API Reference: Terminal for protocol details.

Process management

For detached exec jobs:

const job = await sandbox.exec({ cmd: "npm", args: ["start"], detached: true })

await sandbox.jobs.get(job.id)            // current state
await sandbox.jobs.stop(job.id)           // SIGTERM, then SIGKILL after grace
await sandbox.jobs.list()                 // all detached jobs

Detached jobs survive until you explicitly stop them or the sandbox is destroyed.

Idempotency

Exec is not idempotent. Running npm install twice runs it twice. If you need idempotent retries, store a marker file:

const marker = "/workspace/.deps-installed"
const exists = await sandbox.files.exists(marker)
if (!exists) {
  await sandbox.exec({ cmd: "npm", args: ["ci"] })
  await sandbox.files.write(marker, new Date().toISOString())
}

File writes are idempotent: same path, same content, same result.

Limits

LimitDefaultTunable
Max file size per write100 MBYes (plan-dependent)
Max files per sandbox1,000,000Yes
Max exec stdout buffer10 MBStream mode bypasses this
Max exec durationtimeout_ms parameter, default 30 s; pass 120000 for npm/pip installsYes; detached has no limit
Max concurrent detached jobs100Yes

See also

Was this helpful?