Cloud Run is already sandboxed and isolated, making it ideal for hosting AI agents. When you enable Cloud Run sandboxes, the sandbox command-line tool becomes available in your container. Use this command-line tool to
execute untrusted code written in any language, in a highly optimized sandbox environment, isolated from the rest of your container.
AI agents can leverage sandboxes to safely run sub-agents, perform computational tasks, or open browsers in a fast, isolated environment without risking the host system.
Cloud Run sandboxes provide the following key advantages:
Fast creation: Sandboxes are interactive and ready to execute commands almost instantly. By creating sandboxes within an existing Cloud Run resource where your agent runs, you reduce creation times when compared to creating a new Cloud Run resource for every task. This efficiency helps ensure that your agent remains responsive.
Security: Sandboxes isolate process execution. By default, sandboxes don't have access to the parent workload, environment variables, secrets, or the Google Cloud metadata server. All sandboxes are completely isolated from each other.
Access control and environment: Processes run with
sudoprivileges as a non-root user, letting you install tools using package managers such asapt,pip, ornpmduring execution. While the sandbox environment is ephemeral and deleted upon completion, you can use persistent directories or snapshots to save specific workspaces or map data to a Cloud Storage bucket.
Before you begin
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
- Install and initialize the gcloud CLI.
- Deploy a Cloud Run service in the second generation execution environment.
Enable sandboxes
When you enable sandboxes, your Cloud Run service deploys in the second-generation execution environment. To enable sandboxes in Cloud Run services, use the Google Cloud CLI or a YAML configuration:
gcloud
To deploy or update the service, specify the --sandbox-launcher flag:
To deploy a new service, run the following command:
gcloud beta run deploy SERVICE --image IMAGE_URL --sandbox-launcher
Replace the following:
- SERVICE: the name of your Cloud Run service.
- IMAGE_URL: a reference to the container image, for
example,
us-docker.pkg.dev/cloudrun/container/hello:latest. If you use Artifact Registry, the repository REPO_NAME must already be created. The URL follows the format ofLOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
To update an existing service, run the following command:
gcloud beta run services update SERVICE --sandbox-launcher
YAML
If you are creating a new service, skip this step. If you are updating an existing service, download its YAML configuration:
gcloud run services describe SERVICE --format export > service.yaml
Update your service YAML file to include the
sandboxLauncherattribute set totrueinside your container configuration:apiVersion: serving.knative.dev/v1 kind: Service metadata: name: SERVICE annotations: run.googleapis.com/launch-stage: BETA spec: template: spec: containers: - name: CONTAINER image: IMAGE_URL sandboxLauncher: true port: 8080Replace the following:
- SERVICE: the name of your Cloud Run service.
- CONTAINER: the name of your container.
- IMAGE_URL: a reference to the container image, for
example,
us-docker.pkg.dev/cloudrun/container/hello:latest. If you use Artifact Registry, the repository REPO_NAME must already be created. The URL follows the format ofLOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
Create or update the service using the following command:
gcloud run services replace service.yaml
The
gcloud run services replacecommand defaults to usingservice.yamlfile if present.
Sandboxes share the CPU and memory allocated to the host container. Make sure your main container limits for CPU and memory are sufficient to accommodate both your application and any active sandboxes you run at the same time.
Disable sandboxes
To disable the ability to launch a sandbox in your service, use the Google Cloud CLI or a YAML configuration:
gcloud
Update the service using the --no-sandbox-launcher flag by running the following command:
gcloud beta run services update SERVICE --no-sandbox-launcher
Replace SERVICE with the name of your service.
YAML
If you are creating a new service, skip this step. If you are updating an existing service, download its YAML configuration:
gcloud run services describe SERVICE --format export > service.yaml
Update your service YAML file to remove the
sandboxLauncherattribute inside your container configuration:apiVersion: serving.knative.dev/v1 kind: Service metadata: name: SERVICE spec: template: spec: containers: - name: CONTAINER image: IMAGE_URL port: 8080Replace the following:
- SERVICE: the name of your Cloud Run service.
- CONTAINER: the name of your container.
- IMAGE_URL: a reference to the container image, for
example,
us-docker.pkg.dev/cloudrun/container/hello:latest. If you use Artifact Registry, the repository REPO_NAME must already be created. The URL follows the format ofLOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
Create or update the service using the following command:
gcloud run services replace service.yaml
The
gcloud run services replacecommand defaults to usingservice.yamlfile if present.
Launch sandboxes
Once you enable sandboxes, you can launch sandboxes from within your container execution environment. The sandbox binary is located at /usr/local/gcp/bin/sandbox.
You can execute the binary by referencing its absolute path in your source code. For example, to print Hello inside your isolated sandbox, choose one of the following options:
Node.js
To execute the sandbox command from a Node.js application, include the following code:
exec(`/usr/local/gcp/bin/sandbox do -- /bin/echo "Hello"`, (e, stdout, stderr) => {
res.send({ stdout, stderr });
});
Python
To execute the sandbox command from a Python application, include the following code:
import subprocess
result = subprocess.run(
["/usr/local/gcp/bin/sandbox", "do", "--", "/bin/echo", "Hello"],
capture_output=True,
text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}
Go
To execute the sandbox command from a Go application, include the following code:
cmd := exec.Command("/usr/local/gcp/bin/sandbox", "do", "--", "/bin/echo", "Hello")
out, err := cmd.CombinedOutput()
Sandbox CLI
To execute the sandbox command directly from the command line, run the following command:
/usr/local/gcp/bin/sandbox do -- /bin/echo "Hello"
The examples in this guide use the sandbox command instead of its absolute path /usr/local/gcp/bin/sandbox.
To see the complete list of available commands, run the /usr/local/gcp/bin/sandbox -h command.
Use the sandbox command line capabilities
The sandbox command line tool contains commands to run, configure, and manage
sandboxes.
Run a command in your sandbox
You can execute an instruction in a new, ephemeral sandbox using the sandbox do
command. The sandbox do command performs the following tasks:
- Spins up a sandbox environment (
sandbox run). - Executes the command you specify (
sandbox exec). - Deletes the sandbox after successful execution (
sandbox delete).
For example, to perform a math calculation inside the sandbox, run the
following code snippets for your preferred language. Ensure that any command
or tool you run, such as python3, is installed in your container image:
Node.js
To execute the sandbox command from a Node.js application:
exec(`sandbox do -- /usr/bin/python3 -c "print(1+2)"`, (e, stdout, stderr) => {
res.send({ stdout, stderr });
});
Python
To execute the sandbox command from a Python application:
import subprocess
result = subprocess.run(
["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
capture_output=True,
text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}
Go
To execute the sandbox command from a Go application:
cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
out, err := cmd.CombinedOutput()
Sandbox CLI
To execute the sandbox command directly from the command line:
sandbox do -- /usr/bin/python3 -c "print(1+2)"
If you run a command by name without its absolute path, such as python3 instead of /usr/bin/python3, explicitly configure the PATH environment variable in the sandbox using the --env flag.
Persist data across different executions
Sandboxes are ephemeral by default. To persist data across different sandbox
executions within the same Cloud Run instance, you can import and export
workspace file system state using standard tar archive files. Alternatively,
you can configure bind mounts to share directories directly
between the host container and the sandbox environments.
Use the following flags when running the sandbox do command:
--export-tar: Captures modified overlay files into atararchive file upon completion.--import-tar: Extracts files from atararchive file into the sandbox before execution.--sync-tar: Performs a two-way sync by importing before execution and exporting upon completion.
For example, to pass data between two sandbox calls using archive files, run the following commands:
Write data inside a sandbox and export the state to an archive file:
sandbox do --write --export-tar=/tmp/work.tar \ -- /usr/bin/bash -c "mkdir -p /tmp/work && echo 'task-complete' > /tmp/work/status.txt"Import the archive file in a subsequent call to retrieve the data:
sandbox do --write --import-tar=/tmp/work.tar \ -- /usr/bin/bash -c "cat /tmp/work/status.txt"
Alternatively, to automatically import existing archive state and export new changes in a single command, use --sync-tar=/tmp/work.tar.
When a sandbox process terminates, Cloud Run permanently deletes
ephemeral overlay files that weren't exported to an archive file.
Run a command in the background
To run long-running processes, headless browsers, or background servers, such as
a background agent loop that continuously listens for incoming requests, use the
--detach flag.
For example, run the following command to start a detached sandbox with an idle or background program:
sandbox run my-web-server --detach -- /usr/bin/long_running_or_idle_program
You can use the detach flag to reuse the same sandbox for multiple tests. To
interact with or run additional commands inside a running detached sandbox, use
the sandbox exec command and target your sandbox by its name.
For example, to execute a test command inside your existing my-web-server
background sandbox, run the following command:
sandbox exec my-web-server -- /usr/bin/python3 -c "print('test-complete')"
Configure environment variables
Configure environment
variables on sandboxes
just like you would any other container. Sandboxes don't inherit environment
variables from the host container. You must explicitly provide them using
the --env flag when running the sandbox command.
For example, to pass a configuration variable into a sandbox, run the following command:
sandbox do --env AGENT_MODE="test" -- /usr/bin/bash -c "echo \$AGENT_MODE"
Avoid passing secrets using the env flag as they might be visible to the
sandbox processes.
Create file system snapshots
Deploy a named sandbox in the background to handle continuous tasks like web
servers or long-running agent workflows, execute commands against the sandbox
dynamically, and capture its modified file system state into a tar archive file.
For example, to deploy a background sandbox, write a file to its overlay, and snapshot its state to verify the data was captured, run the following commands:
Deploy a named sandbox in the background with write access enabled, creating a file within its workspace:
sandbox run --write my-sandbox --detach -- /usr/bin/bash -c "echo 'hi' > /tmp/hello.txt && sleep 1h"Create a snapshot of the running sandbox's modified file system using the
sandbox tarcommand:sandbox tar my-sandbox --file=/tmp/foo.tarExtract and verify that the snapshot archive file contains the data written inside the sandbox:
tar -xvf /tmp/foo.tarYou should see the following results:
./ ./tmp/ ./tmp/hello.txt
Configure networking
By default, all outbound traffic from the sandbox is blocked. To allow outbound network access, use the --allow-egress flag:
For example, to fetch data from an external endpoint, run the following command:
sandbox do --allow-egress -- /usr/bin/python3 -c 'import urllib.request; print(urllib.request.urlopen("https://google.com").getcode())'
This command returns the standard HTTP status code 200, indicating a successful
connection.
Access the file system
By default, processes you execute inside the sandbox have read-only access to the host container root file system. You can use the --write flag to enable writing to a temporary file system (tmpfs) overlay. However, the writes will be lost when the sandbox is deleted. To enable persistent writing to the host container, you can configure bind mounts.
Default read-only access
Inside the sandbox, processes can read files from the host container, and they can't write to the root file system.
The following examples assume you are executing commands from the root directory
(/) of your host container.
To verify default read-only access, run the following commands:
Create a Python script on the host container:
mkdir -p /tmp/my-scripts echo "print('hi')" > /tmp/my-scripts/task.pyVerify the file exists locally:
cat /tmp/my-scripts/task.pyExecute the file inside your sandbox:
sandbox do -- /usr/bin/python3 /tmp/my-scripts/task.pyThis command returns
hi, confirming that the sandbox has read access.If you attempt to write data directly to the sandbox root file system without additional configuration, the execution fails. For example, attempting to write to
/tmpinside the default sandbox returns a read-only file system error:Run the following command to write to the root file system:
sandbox do -- /usr/bin/bash -c "echo 'hi' > /tmp/testfile.txt"The command fails with the following error:
/usr/bin/bash: line 1: /tmp/testfile.txt: Read-only file system Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1
Share data using bind mounts
To allow processes inside the sandbox to write persistable data, attach a shared
volume using the --mount flag:
Create a shared volume directory on the host container and seed it with an initial file:
mkdir -p /tmp/my-volume echo 'read' > /tmp/my-volume/readwrite.txtExecute the sandbox to read the file from the bind mount path:
sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "cat /mnt/my-mount/readwrite.txt"This command returns
read.Execute the sandbox to write new data back to the host from inside the mount:
sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "echo 'write' > /mnt/my-mount/readwrite.txt"Verify on the host container that the sandbox successfully modified the file:
cat /tmp/my-volume/readwrite.txtThis command returns
write.
Configure read-only mounts
To grant the sandbox access to a host directory while explicitly preventing it
from modifying files, append the readonly attribute to the mount
specification.
For example, run the following command to test write restrictions on a read-only bind mount:
sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount,readonly -- /usr/bin/bash -c "echo 'fails' > /mnt/my-mount/hello.txt"
The write attempt fails with the following error:
/usr/bin/bash: line 1: /mnt/my-mount/hello.txt: Read-only file system
Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1
View logs
Cloud Run automatically captures sandbox lifecycle events, such as execution starts and exits, in Cloud Logging.
The sandbox CLI writes standard output (stdout) and standard error (stderr) from sandboxed commands directly to the standard streams of the invoking process. To view these logs in Cloud Logging, route the streams to your container's standard output and standard error:
Node.js
const { exec } = require('child_process');
const child = exec('sandbox do -- /usr/bin/python3 -c "print(1+2)"');
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
Python
subprocess.run(
["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
stdout=sys.stdout,
stderr=sys.stderr,
)
Go
cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
What's next
- Learn more about hosting AI agents on Cloud Run.
- Explore browser and OS automation in Cloud Run.
- Review the container runtime contract.