Connect to Snowflake from the SDK

There are two distinct connection problems in Cortex Sandboxes, and they have different answers:

  • Your driver, outside the sandbox, needs credentials to call the Cortex Sandboxes API and create sandboxes. That is the first half of this page.
  • Your code, inside the sandbox, needs to connect back to Snowflake to query data. That is In-sandbox connections at the end, and it works differently: you supply nothing, because the platform provides the credential.

For a first run, the quickstart sets up a named connection with snow connection add. Come here when you need a specific connection, several connections in one process, or raw credentials.

How the SDK resolves a connection

If you name nothing, the SDK resolves a default from, in order:

  • The default connection in ~/.snowflake/connections.toml, the same file the snow CLI uses.
  • SNOWFLAKE_DEFAULT_CONNECTION_NAME, or default_connection_name in ~/.snowflake/config.toml, to choose which entry is the default.
  • The SNOWFLAKE_ACCOUNT and SNOWFLAKE_PAT environment variables. SNOWFLAKE_PAT is read first; SNOWFLAKE_TOKEN is accepted as a fallback for an OAuth session token.

The SDK also reads SNOWFLAKE_HOST, in place of SNOWFLAKE_ACCOUNT when you have a full hostname, and SNOWFLAKE_HOME when resolving connections.toml.

With nothing set, the error names what to do:

snowflake.sandbox has no endpoint to talk to: set SNOWFLAKE_ACCOUNT or
SNOWFLAKE_HOST in the environment, name a connection in
~/.snowflake/connections.toml, or pass one explicitly.

If you name a connection that cannot be resolved, the error names that instead: snowflake.sandbox could not resolve connection '<name>' from ~/.snowflake/connections.toml.

Supply credentials

Use any one of the following.

With the Snowflake CLI

Run snow connection add, then snow connection set-default <name>. This writes ~/.snowflake/connections.toml, which the SDK reads for the default connection. For a walkthrough, see the Cortex Sandboxes quickstart.

With environment variables

No CLI required:

export SNOWFLAKE_ACCOUNT=my_account
export SNOWFLAKE_PAT=my_programmatic_access_token

A programmatic access token is what most callers have.

Per call, with connection=

Pass connection= to use a specific entry from ~/.snowflake/connections.toml:

from snowflake.sandbox import Sandbox

with Sandbox.create(connection="my-conn") as sb:
    print(sb.exec(["echo", "ready"]).stdout)

connection= is accepted by every entry point that talks to the API, not just create(): Sandbox.connect(), Sandbox.list(), get_sandbox(), and destroy_sandbox() all take it. The handle carries it onward, so calls on a sandbox you created or reconnected to use the same connection without naming it again.

For a block, with using()

When several calls should share one connection, name it once for the block:

from snowflake.sandbox import Sandbox, using

with using("my-conn"):
    for sb in Sandbox.list(status="ready"):
        print(sb.name, sb.id)

using() is a convenience, not a requirement: each of those calls would also accept connection="my-conn" directly. It binds the connection to the block it wraps, so two threads or async tasks can hold different connections at once.

By default it leaves the session pooled for the next call. Pass close=True to release it at block exit instead, which is what you want for a one-off connection a long-lived process will not touch again:

with using("other_account", close=True):
    ...
# the session is closed here, not at process exit

close=True only closes a connection the SDK itself opened. A live connection or Snowpark Session you passed in stays yours.

With raw credentials

Pass a Config when you hold an account and token directly rather than a named entry:

from snowflake.sandbox import Config, Sandbox

cfg = Config(account="my_account", pat="my_token")
with Sandbox.create(connection=cfg) as sb:
    print(sb.exec(["echo", "ready"]).stdout)

From inside Snowflake

In a Streamlit in Snowflake app, a notebook, or a stored procedure you hold a Snowpark Session rather than a connection. Pass it directly:

from snowflake.snowpark.context import get_active_session
from snowflake.sandbox import Sandbox

session = get_active_session()
with Sandbox.create(connection=session) as sb:
    print(sb.exec(["echo", "ready"]).stdout)

Note

An earlier global configure() function has been removed. It stored credentials in a process-wide slot and its per-role slots could silently collide. Calling it now raises NotImplementedError naming the replacement.

In-sandbox connections

Code running inside a sandbox does not need credentials configured. The platform provides them, and get_snowflake_connection() resolves whichever mechanism your deployment used:

from snowflake.sandbox import get_snowflake_connection

conn = get_snowflake_connection()
cur = conn.cursor()
cur.execute("SELECT CURRENT_USER(), CURRENT_ROLE()")
print(cur.fetchone())

Prefer this for in-sandbox code, production included. It resolves the credential in order: SNOWFLAKE_PAT or SNOWFLAKE_TOKEN in the environment; a token file named by SNOWFLAKE_TOKEN_FILE_PATH, else /snowflake/session/token, together with SNOWFLAKE_ACCOUNT; then a [default] entry in the platform-rendered $SNOWFLAKE_HOME/connections.toml. Deployments differ in which of those they set, so code that reads only one of them fails where a credential is in fact present.

It also supplies three things that are easy to miss:

  • SNOWFLAKE_ACCOUNT_URL as a bare host. That variable carries a URL scheme and the connector wants a hostname, so passing it through unchanged fails.
  • role from SNOWFLAKE_ROLE and warehouse from SNOWFLAKE_WAREHOUSE. Without role, the connector falls back to your default role, which may not be the role the sandbox was created with.
  • A default login_timeout, so a sandbox with closed egress fails fast instead of hanging.

The helper is for in-sandbox use only, because the credential it reads exists only inside a sandbox. It also refuses keyword overrides that would redirect the credential (account, host, token), raising ValueError. Non-credential options pass through:

conn = get_snowflake_connection(warehouse="MY_WH", database="MY_DB", schema="PUBLIC")

The token the platform provides is a placeholder, not your account token, so the raw credential is not exposed to your code. Code in the sandbox can still make any Snowflake request your identity is authorized to make.

When you need to customize the connection

Most customization does not require building the connection yourself. get_snowflake_connection() forwards any non-credential option to snowflake.connector.connect(), so reach for the helper first:

conn = get_snowflake_connection(warehouse="MY_WH", database="MY_DB", schema="PUBLIC")

If you must construct the connection directly, strip the scheme from the host. SNOWFLAKE_ACCOUNT_URL carries a URL scheme, and the connector wants a bare hostname:

host = os.environ["SNOWFLAKE_ACCOUNT_URL"].split("://", 1)[-1].rstrip("/").split("/", 1)[0]

You don’t need to set up TLS trust. The sandbox already trusts the egress-proxy CA, so a connection you open with snowflake.connector.connect() verifies without extra configuration. The CA variables, such as REQUESTS_CA_BUNDLE and SSL_CERT_FILE, are reserved, so you can’t set them with env= when you create the sandbox.

Pass role=os.environ.get("SNOWFLAKE_ROLE") as well, or the connector uses your default role rather than the role the sandbox was created with.

Read every injected variable with .get() unless you know your deployment sets it. The platform skips an empty value rather than injecting KEY=, which reads as “set to empty” to in-sandbox code, so any of them can be absent.

Because the helper handles these details for you, prefer get_snowflake_connection() and pass your options to it.

Note

/snowflake/session/token is a backwards-compatibility symlink rather than the bind mount itself. The platform bind-mounts /snowflake/secrets and the token lands at /snowflake/secrets/snowflake-session/token. Reading either path is fine, and the platform points connections.toml at the symlink.