environment_id when you start sessions.
Creating an environment starts no compute. Compute starts only when you run a setup test or start a session. Each top-level session gets its own fresh sandbox, so two sessions on the same environment never share files. Subagents and teammates that a session starts share that session’s sandbox.
The TypeScript samples assume the rl client from Client setup. For every field, default, and limit, see Environment reference.
Before you begin
- You need the organization developer or admin role to create, change, test, or delete environments. The organization user role can view environments and their setup runs. See Organizations and roles and API keys.
- Setup runs start real compute, the same kind a session uses.
- Decide which hosts the sandbox must reach, such as package registries or
github.com. New environments start with no internet access.
How an environment becomes usable
An environment without a setup script is usable as soon as you create it. An environment with a setup script is usable only after a setup run passes for its current configuration. What success means for an environment. A session can start on the environment when either of these is true:setup_verification.statusisnot_applicable, because there is no setup script.setup_verification.statusisverified,staleisfalse, and the service kept a reusable image of the prepared sandbox. In the console, the Setup column reads Verified.
startSession returns 422 environment_not_verified, and details.next_action names the call that fixes it.
When a setup run passes, the service saves the prepared sandbox as a reusable image. New sessions start from that image, so they don’t repeat the setup work. In rare cases the service can’t boot the saved image and runs the setup script once on the new session’s own compute instead.
Choose a runtime
A runtime (theprovider field) is the kind of sandbox the environment runs on. List the runtimes you can select. Today the list contains runs, shown in the console as Agent runner: managed Linux compute with a persistent workspace, network policy, and setup verification. Always choose a runtime from this list rather than hard-coding one.
- Console
- TypeScript
- cURL
- In the sidebar, click Environments.
- Click Create environment.
- Open the Runtime menu. It lists the same runtimes, and you can’t change the choice after you create the environment.
description for each runtime. The list is the same for every organization and supports If-None-Match for caching.
Create an environment
This example creates an Agent runner environment with 2 vCPU, 4 GiB of memory, a 20 GiB workspace, and a setup script that installs two pinned Python packages. Its network policy allows only the two Python package hosts the script needs.verify=true starts a setup run as soon as the environment is saved.
- Console
- TypeScript
- cURL
- In the sidebar, click Environments, then click Create environment.
- Enter a Name and choose Agent runner for Runtime.
- For Internet access, choose Enabled. The console offers only Enabled or No access. To allow only specific hosts, use the API as in the other tabs, or edit the policy later as shown in Control network access.
- Under Compute, choose CPU and click Standard (2 vCPU, 4 GiB).
- Under Storage and lifecycle, set Workspace disk (GiB) to
20. - Paste the script into Setup script, or pick one from Start from a template.
- Click Save and test setup. The Setup test panel streams the run’s log.
verify=true started a run, setup_verification.status is running and active_setup_run_id names the run to follow.
environment_id to start sessions, and active_setup_run_id to follow the setup run.
A few behaviors to know:
verifynever loses your save. If the environment has no setup script,verify=trueis ignored. If the run can’t start, the environment is still saved andsetup_warningscontains averify_not_startedentry; start the run yourself withcreateEnvironmentSetupRun. Starting the run needs the same permission ascreateEnvironmentSetupRun.- Creates are not idempotent. Retrying a create that timed out can make a second environment with the same name. List environments before you retry.
- Network access is closed by default. Omitting
network_policystores{"version":"v1","rules":[]}, which blocks every host. Send{}only when you deliberately want unrestricted outbound access. - Privileged Docker is off by default.
privilegeddefaults tofalsewhatever network policy you choose.
List and get environments
listEnvironments returns every environment in your organization, newest first, with the full configuration. It is not paginated, and deleted environments are left out. getEnvironment returns one environment. An unknown, deleted, or other-organization id returns 404 not_found.
- Console
- TypeScript
- cURL
- In the sidebar, click Environments. The table shows each environment’s Name, ID, Provider, Resources, and Setup status.
- Search by name, ID, or provider.
- Click a name, or choose Edit from its action menu, to open the full configuration.
environments is null, not an empty array, when the organization has no environments.
Start from a setup template
Templates are starting-point scripts for common stacks:python-uv (Python with uv), node-npm (Node with npm), system-tools (Debian packages with apt), and gpu-pytorch (PyTorch with CUDA). Copy one into setup.script and edit it. A template is a copy, not a link: later template changes never change your environment.
Every template downloads packages, so it needs network access. Choosing a template doesn’t change the network policy. Allow the hosts the script uses, or choose Enabled for Internet access.
- Console
- TypeScript
- cURL
- Open the environment form.
- Next to Setup script, open Start from a template and pick one.
- Edit the script for your project. The form shows From: and the template title while you work.
accelerator is true on templates that assume a GPU. The response also repeats the list under templates, an older name for items.
Write the setup script
The setup script runs on fresh compute after the sandbox starts and before the agent’s first turn. It runs as the sandbox user in a bash login shell withset -eo pipefail. In a setup run, it gets the environment’s variables and network policy, but no session credentials such as vault grants.
- One command per line. The first failing line ends the run, and the result names that line.
- Don’t wrap lines in
bash -lc. The script already runs under bash, and the wrapper’s quoting is a common failure. - Pin versions. The run proves the exact script, so unpinned installs can drift from what was proven.
- Put Python packages in
/workspace/.venv. The sandbox selects that virtual environment for the agent’s commands automatically. Install through its interpreter, for exampleuv pip install --python /workspace/.venv/bin/python. - Don’t rely on
export,source, aliases, or shell functions. The agent’s commands run in a new shell, so none of these carry over. - Use
sudofor apt. The script doesn’t run as root. - Put files the agent needs under
/workspace. The workspace persists for the life of the session’s sandbox.
setup.timeout_seconds bounds the whole script; it defaults to 600 and accepts 10 through 3600. A script that runs past the timeout fails with exit code 124.
The service saves the script with Windows line endings converted and trailing whitespace removed. setup_warnings flags risky lines such as curl | sh, unpinned installs, and bash -lc wrappers. Warnings are advice; they never block a save or a run.
Verify the setup script
A setup run starts fresh compute from the environment, runs the setup script exactly as a session would, records every line of output, checks the compute, saves a reusable image, and releases the compute. The result becomes the environment’ssetup_verification.
Only one setup run can be in flight per environment. Your organization can have 4 manual setup runs in flight at once.
Start a setup run
Skip this step if you created or updated the environment withverify=true.
- Console
- TypeScript
- cURL
- In Environments, open the environment.
- In the Setup test panel, click Test setup.
202 Accepted with the queued run.
409 setup_run_in_progress with that run’s id in details.setup_run_id. An environment with no setup script returns 400 invalid_request, because there is nothing to verify.
Wait for the result
PollgetEnvironmentSetupRun until status is succeeded, failed, or cancelled. Pass wait_seconds to have the server hold the request until the run finishes or the wait ends. The server caps each wait at 5 seconds, so loop until the status is terminal.
- Console
- TypeScript
- cURL
- Watch the Setup test panel. It shows each phase and streams the log.
- The status reads Setup verified. on success, or shows the hint and failing line on failure.
next_action names the call to make next, such as polling again or reading the log.
A setup run moves through these statuses:
phase tells you where the run is or where it ended: provision, gpu_check, setup, profile, commit (saving the reusable image), or cleanup. Only a failure in setup points at your script.
What success means for a setup run. status is succeeded, and the environment now reads setup_verification.status: "verified" with stale: false for the configuration the run tested. Sessions can start. If the script passed but the image step failed, the console shows Setup passed, but its reusable image failed. and sessions still return environment_not_verified; run setup again.
Other outcomes:
failedrecords a failed verdict. Sessions can’t start until a later run passes.cancelledrecords nothing. If the environment wasverifiedand unchanged when the run started, it staysverified. If it readrunning, it goes back tonever.- Re-verifying doesn’t interrupt sessions. While a new run is in flight on a verified, unchanged environment, it stays
verifiedand sessions keep starting. The console shows Re-testing. In every other case, starting a run sets the status torunning, replacing an earlierfailedor stale verdict.
Read the log
The log interleaves four streams:stdout, stderr, marker (the script line about to run), and system (notes about phases outside your script). Secrets are redacted before the log is stored.
Read from the start with after=0. Each page returns up to limit lines (default 500, maximum 2000) and a next_after cursor. To tail a live run, pass next_after as after on the next call with wait_seconds=0, and wait about two seconds between calls. Stop when status is terminal and a page comes back empty.
- Console
- TypeScript
- cURL
- Open the environment. The Setup test panel streams the log of the selected run.
- Under Recent runs, pick an earlier run to read its log.
truncated is true; the beginning of the log is kept, and the last 2 KiB of stderr stays in the run’s stderr_tail.
List setup runs
listEnvironmentSetupRuns returns the environment’s recent runs, newest first. It includes manual runs (kind: "manual", which you start) and session runs (kind: "session", recorded when a session ran setup on its own compute, with its session_id). The newest manual run is the one setup_verification describes. limit accepts 1 through 50 and defaults to 50.
- Console
- TypeScript
- cURL
- Open the environment.
- Read the Recent runs list in the Setup test panel.
setup_runs is an empty array when no run has been requested.
Cancel a setup run
Cancel a manual run that isqueued, provisioning, or running, for example after you spot a mistake in the script. The run stops, its compute is released, and active_setup_run_id is cleared. A cancelled run records no verdict.
- Console
- TypeScript
- cURL
- Open the environment while a run is in flight.
- In the Setup test panel, click Cancel run. The status reads Cancelled.
409 setup_run_finished, and nothing changes. A session run returns 400 invalid_request; stop the session instead.
Fix a failed setup run
On a failed run, readhint first. Then read failed_line, failed_command, exit_code, and stderr_tail. Fetch the full log only if those don’t explain the failure. The same summary appears in the environment’s setup_verification.last_run.
When
phase is anything other than setup, the failure happened outside your script; retry once before you change anything. failure_code classifies the failure with the same codes session failures use, such as environment_setup_failed, sandbox_capacity_unavailable, or sandbox_provision_timeout.
Control network access
network_policy controls which hosts the sandbox can reach. It applies to the setup script, the agent’s commands, package downloads, and websites opened by the sandbox browser. Outbound traffic that no rule allows is blocked.
Some traffic doesn’t leave from the sandbox, so the policy doesn’t govern it: model calls, calls to the agent’s MCP servers, and the web_search and web_fetch tools. Control those in the agent’s configuration. See Tools.
Rules are checked in order, and the first match wins. For the rule grammar, see Network policy.
Allow specific hosts
A policy change must prove you saw the current access settings. Read the environment, then send its currentnetwork_policy and privileged values in expected_access along with the new policy. This example allows the hosts that git and the gh CLI use for GitHub. Attaching a GitHub credential in a vault doesn’t open these hosts; the environment’s policy must allow them.
- Console
- TypeScript
- cURL
The console can’t edit individual host rules. Under Internet access, choose Enabled for unrestricted access or No access to block everything, then click Save environment. Choosing either replaces a saved custom policy. Use the API for host rules.
verify=true started a new run, so the environment reads running until that run finishes. Some fields are omitted here.
network_policyin a PATCH replaces the whole policy. Include every rule you want to keep.expected_accessis required when a PATCH changes a saved policy other than{}(including the default no-internet policy), or turnsprivilegedon. Without it the API returns428 precondition_required. If either value changed since your read, it returns412 precondition_failed; read the environment again and retry.- Closing access (changing
{}to a restricted policy, or turningprivilegedoff) doesn’t needexpected_access. - Omitting
network_policyorprivilegedin a PATCH keeps the saved value.
Update an environment
An update is partial: omitted fields keep their saved values. A few fields replace the saved value as a whole:setupreplaces the whole setup object. Send bothscriptandtimeout_secondsto keep both.{"script": ""}removes the script.resourcesreplaces the whole compute size.env_varsandmountsreplace the whole map or list. Send{}or[]to clear them.
verify=true to start a setup run in the same call.
This example raises compute to 4 vCPU and 8 GiB and raises the idle stop to one hour.
- Console
- TypeScript
- cURL
- In Environments, click the environment name, or choose Edit from its action menu.
- Under Compute, click Heavy (4 vCPU, 8 GiB).
- Under Storage and lifecycle, set Idle stop after (seconds) to
3600. - Click Save and test setup, or Save environment to save without testing. Runtime is read-only after creation.
409 revision_conflict. Read the environment again and retry.
Delete an environment
Deleting removes the environment from lists and reads, and new sessions can’t use it. Sessions that are running keep their sandbox, and past session history stays readable. There is no restore, so create a new environment if you need it back.- Console
- TypeScript
- cURL
- In Environments, open the environment’s action menu.
- Click Delete.
- In the Delete environment dialog, click Delete.
What can go wrong
For the full error catalog and retry guidance, see Errors.
Limits
For compute, disk, and lifecycle limits, see Environment reference. For every product limit, see Limits.
Next steps
Environment reference
Every field, default, compute size, sandbox path, and network rule.
Start a session
Combine a usable environment with an agent and start work.
Authenticate with vaults
Give agents credentials without putting secret values in the environment.
Deliverables and artifacts
Where agents save the files you asked for.