AI agents run arbitrary code in your sandbox. Without enforcement at the OS level, a single prompt injection can exfiltrate credentials, access cloud metadata, or pivot to internal services.
Drop-in runtime security for Vercel, E2B, Daytona, Cloudflare, Blaxel, Sprites, Modal, Runloop, and exe.dev sandboxes. One npm installpip install, three lines of code.
Available for TypeScript and Python
import { Sandbox } from '@vercel/sandbox'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await Sandbox.create({ runtime: 'node24' }); const sandbox = await secureSandbox(adapters.vercel(raw)); await sandbox.exec('npm install express'); // allowed await sandbox.exec('cat ~/.ssh/id_rsa'); // blocked
from pydantic_ai import Agent from vercel_sandbox import Sandbox from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import vercel raw = await Sandbox.create(runtime="node24") toolset = SecureSandboxToolset(vercel(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from vercel_sandbox import Sandbox from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import vercel raw = await Sandbox.create(runtime="node24") sandbox = await secure_sandbox(vercel(raw)) await sandbox.exec("npm install express") # allowed await sandbox.exec("cat ~/.ssh/id_rsa") # blocked
import Sandbox from '@e2b/code-interpreter'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await Sandbox.create(); const sandbox = await secureSandbox(adapters.e2b(raw)); await sandbox.exec('pip install pandas'); // allowed await sandbox.exec('cat ~/.aws/credentials'); // blocked
from pydantic_ai import Agent from e2b_code_interpreter import Sandbox from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import e2b raw = await Sandbox.create() toolset = SecureSandboxToolset(e2b(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from e2b_code_interpreter import Sandbox from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import e2b raw = await Sandbox.create() sandbox = await secure_sandbox(e2b(raw)) await sandbox.exec("pip install pandas") # allowed await sandbox.exec("cat ~/.aws/credentials") # blocked
import { Daytona } from '@daytonaio/sdk'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await new Daytona().create(); const sandbox = await secureSandbox(adapters.daytona(raw)); await sandbox.exec('node server.js'); // allowed await sandbox.exec('curl http://169.254.169.254/'); // blocked
from pydantic_ai import Agent from daytona_sdk import Daytona from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import daytona raw = await Daytona().create() toolset = SecureSandboxToolset(daytona(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from daytona_sdk import Daytona from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import daytona raw = await Daytona().create() sandbox = await secure_sandbox(daytona(raw)) await sandbox.exec("node server.js") # allowed await sandbox.exec("curl http://169.254.169.254/") # blocked
import { Container } from '@cloudflare/containers'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await Container.create(); const sandbox = await secureSandbox(adapters.cloudflare(raw)); await sandbox.exec('npm run build'); // allowed await sandbox.exec('sudo apt install nmap'); // blocked
from pydantic_ai import Agent from cloudflare_containers import Container from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import cloudflare raw = await Container.create() toolset = SecureSandboxToolset(cloudflare(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from cloudflare_containers import Container from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import cloudflare raw = await Container.create() sandbox = await secure_sandbox(cloudflare(raw)) await sandbox.exec("npm run build") # allowed await sandbox.exec("sudo apt install nmap") # blocked
import { SandboxInstance } from '@blaxel/sandbox'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await SandboxInstance.create(); const sandbox = await secureSandbox(adapters.blaxel(raw)); await sandbox.exec('python train.py'); // allowed await sandbox.exec('env | grep SECRET'); // blocked
from pydantic_ai import Agent from blaxel_sandbox import SandboxInstance from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import blaxel raw = await SandboxInstance.create() toolset = SecureSandboxToolset(blaxel(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from blaxel_sandbox import SandboxInstance from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import blaxel raw = await SandboxInstance.create() sandbox = await secure_sandbox(blaxel(raw)) await sandbox.exec("python train.py") # allowed await sandbox.exec("env | grep SECRET") # blocked
import { Sprite } from '@fly/sprites'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const raw = await Sprite.create(); const sandbox = await secureSandbox(adapters.sprites(raw)); await sandbox.exec('cargo build --release'); // allowed await sandbox.exec('cat /etc/shadow'); // blocked
from pydantic_ai import Agent from fly_sprites import Sprite from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import sprites raw = await Sprite.create() toolset = SecureSandboxToolset(sprites(raw)) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from fly_sprites import Sprite from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import sprites raw = await Sprite.create() sandbox = await secure_sandbox(sprites(raw)) await sandbox.exec("cargo build --release") # allowed await sandbox.exec("cat /etc/shadow") # blocked
import { secureSandbox } from '@agentsh/secure-sandbox'; import { modal, modalDefaults } from '@agentsh/secure-sandbox/adapters/modal'; const raw = modalSandbox; // your Modal sandbox instance const sandbox = await secureSandbox(modal(raw), { ...modalDefaults() }); await sandbox.exec('python train.py'); // allowed (ptrace enforcement) await sandbox.exec('cat ~/.aws/credentials'); // blocked
from pydantic_ai import Agent from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters.modal import modal, modal_defaults raw = modal_sandbox # your Modal sandbox instance toolset = SecureSandboxToolset(modal(raw), **modal_defaults()) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters.modal import modal, modal_defaults raw = modal_sandbox # your Modal sandbox instance sandbox = await secure_sandbox(modal(raw), **modal_defaults()) await sandbox.exec("python train.py") # allowed (ptrace enforcement) await sandbox.exec("cat ~/.aws/credentials") # blocked
import Runloop from '@runloop/api-client'; import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; const client = new Runloop(); const devbox = await client.devboxes.createAndAwaitRunning({ blueprint_id: 'my-bp' }); const sandbox = await secureSandbox(adapters.runloop({ client, id: devbox.id }), adapters.runloopDefaults()); await sandbox.exec('npm test'); // allowed await sandbox.exec('cat ~/.ssh/id_rsa'); // blocked
from pydantic_ai import Agent from runloop import Runloop from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import runloop, runloop_defaults client = Runloop() devbox = await client.devboxes.create_and_await_running(blueprint_id="my-bp") toolset = SecureSandboxToolset(runloop(client=client, id=devbox.id), **runloop_defaults()) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from runloop import Runloop from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import runloop, runloop_defaults client = Runloop() devbox = await client.devboxes.create_and_await_running(blueprint_id="my-bp") sandbox = await secure_sandbox(runloop(client=client, id=devbox.id), **runloop_defaults()) await sandbox.exec("npm test") # allowed await sandbox.exec("cat ~/.ssh/id_rsa") # blocked
import { secureSandbox, adapters } from '@agentsh/secure-sandbox'; // VM already created: ssh exe.dev new --name=my-vm --image=ubuntu:22.04 const sandbox = await secureSandbox(adapters.exe('my-vm'), adapters.exeDefaults()); await sandbox.exec('go build ./...'); // allowed (hybrid ptrace+seccomp) await sandbox.exec('cat /etc/shadow'); // blocked
from pydantic_ai import Agent from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import exe, exe_defaults # VM already created: ssh exe.dev new --name=my-vm --image=ubuntu:22.04 toolset = SecureSandboxToolset(exe("my-vm"), **exe_defaults()) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import exe, exe_defaults # VM already created: ssh exe.dev new --name=my-vm --image=ubuntu:22.04 sandbox = await secure_sandbox(exe("my-vm"), **exe_defaults()) await sandbox.exec("go build ./...") # allowed (hybrid ptrace+seccomp) await sandbox.exec("cat /etc/shadow") # blocked
import { freestyle as freestyleClient, VmSpec } from 'freestyle-sandboxes'; import { secureSandbox } from '@agentsh/secure-sandbox'; import { freestyle, freestyleDefaults } from '@agentsh/secure-sandbox/adapters/freestyle'; const fs = freestyleClient({ apiKey: process.env.FREESTYLE_API_KEY }); const { vm } = await fs.vms.create({ spec: new VmSpec() }); const sandbox = await secureSandbox(freestyle(vm), freestyleDefaults()); await sandbox.exec('npx tsx build.ts'); // allowed await sandbox.exec('cat ~/.ssh/id_rsa'); // blocked
from pydantic_ai import Agent from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters.freestyle import FreestyleClient, freestyle, freestyle_defaults async with FreestyleClient(api_key=FREESTYLE_API_KEY) as client: vm = await client.create_sandbox_vm() toolset = SecureSandboxToolset(freestyle(vm), **freestyle_defaults()) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters.freestyle import FreestyleClient, freestyle, freestyle_defaults async with FreestyleClient(api_key=FREESTYLE_API_KEY) as client: vm = await client.create_sandbox_vm() sandbox = await secure_sandbox(freestyle(vm), **freestyle_defaults()) await sandbox.exec("npx tsx build.ts") # allowed await sandbox.exec("cat ~/.ssh/id_rsa") # blocked
import { secureSandbox } from '@agentsh/secure-sandbox'; import { tensorlake, tensorlakeDefaults } from '@agentsh/secure-sandbox/adapters/tensorlake'; // `sb` is a connected Tensorlake sandbox (agentsh baked into the image) const sandbox = await secureSandbox(tensorlake(sb), tensorlakeDefaults()); await sandbox.exec('python build.py'); // allowed await sandbox.exec('cat ~/.ssh/id_rsa'); // blocked
from pydantic_ai import Agent from tensorlake.sandbox import SandboxClient from agentsh_secure_sandbox import SecureSandboxToolset from agentsh_secure_sandbox.adapters import tensorlake, tensorlake_defaults client = SandboxClient.for_cloud(api_key=TENSORLAKE_API_KEY) with client.create_and_connect(image="agentsh-sandbox-v0_20_3-i1") as sb: toolset = SecureSandboxToolset(tensorlake(sb), tensorlake_defaults()) agent = Agent("claude-sonnet-4-6", toolsets=[toolset])
from tensorlake.sandbox import SandboxClient from agentsh_secure_sandbox import secure_sandbox from agentsh_secure_sandbox.adapters import tensorlake, tensorlake_defaults client = SandboxClient.for_cloud(api_key=TENSORLAKE_API_KEY) with client.create_and_connect(image="agentsh-sandbox-v0_20_3-i1") as sb: sandbox = await secure_sandbox(tensorlake(sb), tensorlake_defaults()) await sandbox.exec("python build.py") # allowed await sandbox.exec("cat ~/.ssh/id_rsa") # blocked
Hosted sandboxes isolate code from your infrastructure, but they do not decide which files an AI agent may read, which commands it may run, or which domains it may contact. Secure Sandbox adds that missing execution layer. It wraps the provider sandbox, installs agentsh, and routes shell activity through policy so every operation is evaluated before it can expose credentials, fetch payloads, or move data to an unapproved destination.
The same wrapper shape works across TypeScript and Python. Teams can start with a
preset such as agentDefault, tighten network and file rules for
production, and keep the resulting audit trail as evidence of what the agent tried
to do. For the terms used by the SDK and policy layer, see the
Glossary.
In practice, this means the sandbox provider still handles isolation and lifecycle, while agentsh handles per-operation authorization inside that sandbox. A prompt injection can ask the agent to read credentials, install a suspicious package, or post files to an unknown host, but the wrapped process still has to pass file, command, package, network, and DLP policy. The SDK keeps that boundary close to the code that creates the sandbox, so application teams do not have to maintain a separate enforcement bootstrap for each provider.
The audit trail is part of the API surface. When a package install is blocked, a metadata endpoint is denied, or a command attempts to read a secret path, the session report shows the attempted operation and the rule that decided it. That makes Secure Sandbox useful for local prototyping and for production reviews: developers get a small wrapper, while security teams get deterministic evidence that policy was enforced below the model layer, independent of which prompt or agent framework initiated the action, and consistent across every supported sandbox provider. That consistency is the reason the wrapper can be used as a shared security control instead of a provider-specific demo.
The SDK is also meant to keep provider choice reversible. If one workload starts in E2B, another runs in Vercel, and a third needs Modal or Runloop for GPU or devbox behavior, teams can keep the same policy vocabulary around all of them. File rules, network allowlists, package checks, command restrictions, and secret redaction remain the operational contract even when the underlying sandbox changes. That makes migration and multi-provider deployments easier to review, because the security boundary is described once and then applied through the adapter that owns the actual sandbox handle.
Every command runs through the policy engine. Dangerous operations are denied before they reach the kernel.
Built on agentsh, the open-source execution-layer security engine. A lightweight Go binary replaces /bin/bash inside the sandbox, routing every operation through kernel-level enforcement before it reaches the host.
Enforcement is synchronous and adds <1ms per command. No background daemons, no network round-trips.
Extend any preset with your own rules. Allow specific APIs, open file paths, restrict ports — all as code. See the policy docs →
import { agentDefault } from '@agentsh/secure-sandbox/policies'; const policy = agentDefault({ network: [ { allow: ['api.stripe.com', 'api.openai.com'], ports: [443] } ], file: [ { allow: '/data/**', ops: ['read', 'write'] } ], }); const sandbox = await secureSandbox(adapters.e2b(raw), { policy });
from agentsh_secure_sandbox.policies import agent_default policy = agent_default( network=[ {"allow": ["api.stripe.com", "api.openai.com"], "ports": [443]} ], file=[ {"allow": "/data/**", "ops": ["read", "write"]} ], ) sandbox = await secure_sandbox(e2b(raw), policy=policy)
Built-in adapters for the major hosted AI sandbox providers. Each adapter maps the platform's SDK to the secure-sandbox interface with zero configuration.
Stop hoping your sandbox is safe. Know it is.
MIT licensed. Built by Canyon Road.