English
Distribute to Agents
Code Sandbox

Code Sandbox

Run code in an isolated sandbox environment to process your PuppyOne data safely.


What a code sandbox is

A code sandbox is an isolated execution environment. PuppyOne mounts your Content Node data into the sandbox so an agent can run arbitrary code against it.

Sandboxes are useful when you need to:

  • Perform complex computation or transformation on large JSON datasets
  • Run Python scripts for data analysis
  • Use tools like jq for batch processing structured data
  • Install third-party libraries for compute tasks
  • Run untrusted code inside a secure isolated environment

How it works

PuppyOne cloud                      Sandbox environment (isolated)
┌─────────────────────┐             ┌─────────────────────┐
│  Content Nodes      │  ──mount──► │  /workspace/        │
│  /products.json     │             │  /products.json     │
│  /docs/             │             │  /docs/             │
└─────────────────────┘             └──────────┬──────────┘

                                    Agent runs code in the sandbox

Your Content Nodes are mounted under /workspace/ inside the sandbox, so the agent can read and write them like local files. Depending on configuration, writes can sync back to PuppyOne.


Two sandbox backends

BackendTechnologyBest forStartup speed
E2BFirecracker microVMCloud, higher isolationAbout 1 second
DockerDocker containerSelf-hosting, flexible setupAbout 2 seconds

Create a sandbox

Via CLI

# Create an E2B sandbox in the cloud
puppyone access add sandbox "Python Runner" --type e2b
 
# Create a Docker sandbox for self-hosted use
puppyone access add sandbox "Data Processor" --type docker

Via API

curl -X POST https://api.puppyone.ai/api/v1/sandbox-endpoints \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Python Runner",
    "project_id": "proj_xxx",
    "runtime": "python",
    "sandbox_type": "e2b",
    "mounts": [
      {
        "path": "products",
        "mount_path": "/workspace/products",
        "mode": "rw"
      }
    ],
    "timeout": 30
  }'

Via dashboard

  1. Open Project -> Connections
  2. Click Add Connection and choose Sandbox
  3. Configure the sandbox name, runtime, and mounted nodes
  4. Create it

Sandbox configuration

Runtimes

RuntimePreinstalled toolsBest for
alpinebash, jq, coreutilsLightweight data processing
pythonPython 3.12, pip, jqData analysis and scripting
nodeNode.js 20, npm, jqJavaScript processing

Mount configuration

Each mount maps a content path from your project to a sandbox path:

{
  "mounts": [
    {
      "path": "products",
      "mount_path": "/workspace/products",
      "mode": "rw"
    },
    {
      "path": "docs",
      "mount_path": "/workspace/docs",
      "mode": "ro"
    }
  ]
}

Mount modes:

ModeDescription
rwRead/write. The agent can modify data, and changes sync back to PuppyOne
roRead-only. The agent can read but cannot modify

Timeout

The timeout parameter controls the maximum duration of a single execution in seconds. The default is 30 seconds, and the maximum is 300 seconds.


Execute code

Via API

curl -X POST https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec \
  -H "X-Access-Key: sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "python3 /workspace/script.py",
    "timeout": 30
  }'

Response example:

{
  "exit_code": 0,
  "stdout": "Done processing, 42 records total\n",
  "stderr": "",
  "duration_ms": 1250
}

Real-world examples

Process JSON with Python

Suppose you have a product list mounted at /workspace/products/pricing.json and want to filter expensive products and generate a report.

First create a sandbox and mount the data:

puppyone access add sandbox "Price Analyzer" --type e2b

Then run the analysis script:

curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "python3 -c '\''import json\nwith open(\"/workspace/products/pricing.json\") as f:\n    data = json.load(f)\nexpensive = [p for p in data[\"products\"] if p[\"price\"] > 100]\nprint(f\"Found {len(expensive)} expensive products:\")\nfor p in expensive:\n    print(f\"  - {p[\"name\"]}: ${p[\"price\"]}\")\nreport = {\"total\": len(data[\"products\"]), \"expensive_count\": len(expensive), \"expensive_products\": expensive}\nwith open(\"/workspace/products/analysis.json\", \"w\") as f:\n    json.dump(report, f, ensure_ascii=False, indent=2)\nprint(\"Report saved\")'\''"}'

Output:

Found 1 expensive product:
  - Gadget X: $149.99
Report saved

Because the mount mode is rw, the generated analysis.json automatically syncs back into PuppyOne as a new Content Node.

Query structured data with jq

jq is great for JSON processing, and it is preinstalled in every sandbox runtime.

# Extract all product names
curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "jq '\''[.products[].name]'\'' /workspace/products/pricing.json"}'
 
# Calculate average price
curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "jq '\''.products | map(.price) | add / length'\'' /workspace/products/pricing.json"}'
 
# Group by category
curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "jq '\''.products | group_by(.category) | map({category: .[0].category, count: length})'\'' /workspace/products/pricing.json"}'

Install third-party libraries

In the Python runtime, you can install extra libraries:

curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{sandbox_id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "pip install pandas && python3 -c '\''import pandas as pd\nimport json\nwith open(\"/workspace/products/pricing.json\") as f:\n    data = json.load(f)\ndf = pd.DataFrame(data[\"products\"])\nprint(df.describe())\nprint()\nprint(\"Grouped by category:\")\nprint(df.groupby(\"category\")[\"price\"].agg([\"count\", \"mean\", \"max\"]))'\''"}'

Read-only vs read/write

Read-only mode (ro)

Best for analysis-only workflows where agents must not modify data accidentally.

{
  "mounts": [
    {
      "path": "data",
      "mount_path": "/workspace/data",
      "mode": "ro"
    }
  ]
}

If the agent tries to write to a read-only mount, it receives a Permission denied error.

Read/write mode (rw)

The agent can modify data or create new files, and changes sync back to PuppyOne automatically.

{
  "mounts": [
    {
      "path": "data",
      "mount_path": "/workspace/data",
      "mode": "rw"
    }
  ]
}

Use this when the agent needs to generate reports, transform data formats, or update existing content.


FAQ

Sandbox startup times out

  1. E2B sandboxes usually start in around 1 second, so timeouts often point to a network issue
  2. For Docker sandboxes, make sure Docker is running
  3. In self-hosted environments, make sure the backend is configured with the correct sandbox backend

Execution times out

  1. The default timeout is 30 seconds, and you can increase it when creating the sandbox, up to 300 seconds
  2. For long-running jobs, consider splitting them into multiple runs
  3. Dependency installation such as pip install also counts toward execution time

Changes do not sync back

  1. Make sure the mount mode is rw, not ro
  2. Make sure the file is written inside the mounted path
  3. Sync may lag by a few seconds after writes

Tools are missing inside the sandbox

The default sandbox environment is intentionally minimal. You can install tools inside a command:

# Python sandbox
curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "pip install requests pandas"}'
 
# Alpine sandbox
curl -X POST "https://api.puppyone.ai/api/v1/sandbox-endpoints/{id}/exec" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"command": "apk add --no-cache curl"}'

Each sandbox execution runs in an isolated environment, so installed tools are not persisted. If you need a persistent custom environment, use the Docker backend and build a custom image.


Next steps