Sandbox · AI agents

A runtime designed for code you didn't write.#

GocciaScript is meant for running untrusted or user-provided code in a host-controlled environment. Scripts receive only the data and capabilities the host provides, run with explicit limits, and return structured results that the host can inspect. Filesystem workflows use GocciaSandboxRunner: host paths are copied into a virtual filesystem as seed baselines, sandbox writes stay in that filesystem, and changes are surfaced as explicit diffs.

AI agent

LLM emits GocciaScript via a tool call

Goccia sandbox

explicit globals · seed baselines · capability gates · limits

Structured result

JSON

import baselinessandbox-only fsnested runScriptexplicit diffs
Virtual filesystem runner

Seeded files, not host mounts.#

GocciaSandboxRunner executes an entry path inside an isolated virtual filesystem. Seed paths and JSON seed config copy files into the sandbox before execution; they are import baselines, not live mounts. Source can import "fs" for sandbox filesystem operations and "goccia" for shell commands or nested execution.

run sandbox
./build/GocciaSandboxRunner /main.js \
  --seed-config=./sandbox.seed.json \
  --mode=bytecode \
  --diff
sandbox.seed.json
{
  "files": [
    { "from": "./project", "to": "/" },
    { "from": "./tools", "to": "/tools" },
    { "path": "/main.js", "text": "import fs from \"fs\";\nconsole.log(fs.readdirSync('/'));" },
    { "path": "/data.bin", "base64": "AQID" }
  ]
}
main.js
import fs from "fs";
import { $, runScript } from "goccia";

fs.mkdirSync("/out", { recursive: true });
fs.writeFileSync("/out/summary.txt", "ready\n");

const audit = runScript("/tools/audit.js", {
  sandbox: true,
  seed: ["/tools/audit.js", { from: "/out", to: "/input" }],
  diff: true,
});

console.log(await $`cat /out/summary.txt`.text());
console.log(audit.diff);
Tool-call comparison

One sandboxed call vs five.#

The same agent task — Summarize the latest transaction batch and find outliers. — solved with a typical tool stack and again with a single GocciaScript call. This comparison assumes each tool call depends on data discovered or produced by the previous step, so the calls cannot be parallelized without changing the task shape.

Each step expands to the request body for that turn — instructions, tool definitions, prior function calls, and function-call outputs. Token counts via gpt-tokenizer on GPT-5-family o200k_base tokenization.
Bash + jq

5 tool calls 1422 in 241 out

  1. 1
    bashdiscover108 39
    ls /tmp/agent/transactions/
  2. 2
    bashload166 42
    cat /tmp/agent/transactions/transactions.current.json
  3. 3
    bashsum313 50
    jq '[.[].amount] | add' /tmp/agent/transactions/transactions.current.json
  4. 4
    bashaverage382 52
    jq '[.[].amount] | add / length' /tmp/agent/transactions/transactions.current.json
  5. 5
    bashoutliers453 58
    jq '[.[] | select((.amount | abs) > 280)]' /tmp/agent/transactions/transactions.current.json
  • · values cross 5 process boundaries — possible to lose precision or quoting
  • · 5 round-trips ≈ 5× the prompt overhead and 5× the chance of a misstep
GocciaScript (single call)

1 tool call 223 in 138 out

  1. 1
    run_codeeverything223 138
    const total = transactions.reduce((s, t) => s + t.amount, 0);
    const avg = total / transactions.length;
    const stdev = Math.sqrt(
      transactions.reduce((s, t) => s + (t.amount - avg) ** 2, 0) / transactions.length
    );
    const outliers = transactions.filter((t) => Math.abs(t.amount - avg) > 2 * stdev);
    ({ total, avg, outliers });
  • all values stay in one sandbox — no serialization between steps
  • host gets a single structured JSON result back

Sandbox preview

Edit the script or globals and hit Run — the code runs in the same sandboxed runtime used by the server preview and returns a structured host result.

sandboxed script · script.js
globals · context.json
host result
press Run or ⌘+Enter