Cortex Sandboxes limitations and FAQ

Feature availability

  • Status: Private preview. Access is enabled per account by Snowflake.
  • Compute: Sandboxes run on CPU.
  • Access control: Enabled per account during private preview. To request access, contact your Snowflake account representative. See Cortex Sandboxes concepts and security for the access model.

Private preview limitations

The following are not supported in private preview:

  • External base images. A base image must come from Snowflake: either a catalog image (a bare name such as sandbox-base, or NAME:TAG) or an image in your own Snowflake image repository (a hostless /db/schema/repo/image:tag path). Pulling a base image from Docker Hub, ECR, or any other external registry is not supported — a reference that names a registry host or carries a URL scheme is rejected. Adding layers on top of a base image is also temporarily unavailable and will return in a later release — install extra dependencies into the running sandbox instead, as shown in the FAQ below.
  • Non-Python SDK. The SDK is Python-only in private preview, and requires Python 3.11 or later.
  • Non-Linux images. Only Linux images are supported.
  • Formal SLA commitments. Private preview ships without an SLA.
  • Automatic expiry. No sandbox expires on its own. There is no TTL and nothing deletes an unused sandbox for you. Sandbox.create() has no expires_after or timeout parameter, so passing either raises a TypeError before any request is sent; a raw REST caller that sets the underlying field gets a 400. The platform suspends an idle sandbox (so it stops consuming compute) but does not remove it, so call sb.terminate() when you are done. To find sandboxes you no longer need, use Sandbox.list(), snow sandbox list, or Snowsight under AI » Sandboxes.
  • Filesystem snapshots and image mounts. snapshot_filesystem(), snapshot_directory(), mount_image(), and unmount_image() are surfaced on the SDK but have no backend, and raise SandboxNotImplementedError.
  • Port forwarding and tunnels. tunnels() and create_connect_token() raise SandboxNotImplementedError, so there is no tunnel to a port inside a sandbox and no way to mint short-lived credentials for one. Reach a sandbox through exec and the file and log APIs.
  • Server-side stage transfers. stage_put() and stage_get() return 501 on every backend. Mount the stage with StageMount and read or write through the mount instead.
  • Caller-supplied egress host lists. Naming arbitrary hosts on Egress is retired — hosts listed that way are not enforced and not reachable, so the SDK refuses them locally. Grant a host outside the platform baseline with an external access integration and name that instead.

The platform also enforces the following limits. Each is reported as an error on the request that exceeds it, except where noted.

  • 100 live sandboxes per user, per account by default. A create past the cap is refused with a 429. The cap is a guardrail against a runaway create loop rather than an exact limit: under concurrent creates, the number of live sandboxes can briefly exceed 100. Only terminated and failed sandboxes stop counting — a suspended sandbox still occupies a slot, so suspending one to stop it consuming compute does not free capacity. The service response names the live count, the cap, and the fix, but the Python SDK does not currently surface it: Sandbox.create() raises SandboxRateLimitError("rate-limited after N retries") with retry_after unset, which is indistinguishable from transient throttling. If you get that error with no retry_after, suspect this cap: retrying cannot clear it, so list your sandboxes and terminate what you no longer need.
  • 1 hour per exec. A larger timeout is clamped to one hour rather than refused, and an exec that reaches it raises SandboxExecTimeoutError. An untimed exec gets the same one-hour budget. For longer work, use a detached run (Sandbox.create(command=...)) and wait().
  • 25 MiB per file transfer. A client-side size check refuses an oversize transfer before any bytes move, so upload_file(), upload_dir(), write_text(), and write_bytes() raise SandboxFileTooLargeError up front, and read_text()/read_bytes() raise it mid-stream with the server’s 413 as a backstop. upload_dir() checks the whole tree first, so a tree never half-uploads; dry_run=True reports offenders in plan.oversized instead of raising. Mount a stage for bulk data.
  • 4 MiB per request body on every other route, including exec.
  • 16 brokered secrets per sandbox.
  • 64 environment variables, 16 KiB total. Some keys cannot be injected. Reserved by prefix: SNOWFLAKE_, SANDBOX_, and CNG_SECRET_, which the platform owns. Reserved by exact name: PATH, LD_PRELOAD, LD_LIBRARY_PATH, HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY, REQUESTS_CA_BUNDLE, SSL_CERT_FILE, SSL_CERT_DIR, and CURL_CA_BUNDLE. Those exist so an environment map cannot quietly disable a security control: the proxy and CA variables are what route and verify the sandbox’s egress, and the loader variables would let injected code preload a library into every process.
  • 32 stage mounts per sandbox. A mount path may not replace or shadow /etc, /usr, /bin, /sbin, /lib, /lib64, /proc, /sys, /dev, /boot, or /snowflake.
  • 32 MCP servers per sandbox.
  • 64 tags (labels), 8 KiB total. Tags can only be set at create; there is no relabel endpoint.
  • 1024 command arguments, 128 KiB total.
  • 256 bytes for a sandbox name. The reserved cntr_<24 lowercase hex characters> sandbox-ID form is rejected.

FAQ

What is Cortex Sandboxes?

Cortex Sandboxes is a secure, isolated execution environment for running AI-generated Python code, built into Snowflake and governed by your existing Snowflake security policies. You get a sandboxed container your AI agent can run code in, without your data leaving your Snowflake account.

How is it different from an external sandbox provider?

External sandbox providers run your code on their infrastructure, which means your data has to leave Snowflake. Cortex Sandboxes runs inside your Snowflake account—your masking policies, row-level security, and audit logs apply automatically, and nothing is shared with a third party.

How does it compare to Snowpark Container Services (SPCS)?

Cortex Sandboxes is designed for short-lived, per-task isolated containers that start quickly—the “one sandbox per agent invocation” pattern. SPCS is designed for long-running services and batch jobs. For agent workloads where you need to spin up many isolated environments and tear them down after each task, Sandbox is the right primitive. For persistent services, SPCS remains the right choice.

How does idle suspension work?

You do not have to terminate a sandbox to stop it consuming compute. An idle sandbox is suspended automatically and resumes on next use. The platform default idle window is 10 minutes.

To choose a different window, pass idle_suspend= to Sandbox.create() as a datetime.timedelta or a duration string such as "30m" or "1h30m". The resolution is minutes, so one minute is the smallest value you can set: anything finer, such as "90s", raises rather than being rounded, as do zero and negative values. Omit the argument to take the 10 minute default. On the CLI, snow sandbox run --detach applies a 24 hour window unless you pass --idle-suspend, because a detached run with no inbound traffic would otherwise suspend while still working.

To stop the compute now rather than waiting out the idle window, call sb.suspend() (or snow sandbox suspend). That banks the filesystem and tears the container down immediately, which is the fastest way to stop a sandbox consuming compute without deleting it.

What suspension does not do is delete the sandbox or release quota: a suspended sandbox still occupies one of your 100 live slots. Call sb.terminate() when the work is finished, and shorten idle_suspend if you want an abandoned sandbox to stop consuming compute sooner than the default.

Can I use my own secrets (API keys, database passwords) inside a sandbox?

Yes, with Snowflake SECRET objects. You declare a secret by name when you create the sandbox. The secret’s value is not placed in the container or the SDK. For how this works, see Cortex Sandboxes concepts and security.

Does it integrate with LangChain, LangGraph, CrewAI, or AutoGen?

Yes. The SDK is a plain Python library, so it works with any Python agent framework. Install whatever your agent needs into the running sandbox rather than assuming it is present:

from snowflake.sandbox import Image, Sandbox

sb = Sandbox.create(image=Image.from_catalog("sandbox-base"))
sb.exec(["pip", "install", "--quiet", "langgraph", "langchain-core"])

Public PyPI is in the platform egress baseline, so this needs no egress configuration and no external access integration. The packages are fetched from public PyPI itself — pypi.org and files.pythonhosted.org are on the always-on package-manager host set, which permits GET and HEAD only.

What happens if my sandbox crashes or hangs?

The SDK surfaces specific exceptions (SandboxExecError, SandboxExecTimeoutError) with the exit code, stdout, and stderr so your application can handle failures gracefully. You can call sb.logs() to inspect what the container was doing, and sb.terminate() to tear it down and start a fresh one.