This guide shows you how to set and manage environment variables in CWSandbox instances. Use environment variables to pass non-sensitive configuration values, such as log levels or project identifiers, into your sandboxes. You can set them on individual sandboxes, share them across sandboxes in a session, or scope them to remote functions.
Don’t use environment variables for sensitive information such as API keys, passwords, or other secrets.
For sensitive values, use the Secret type instead. The server resolves secrets, and the client never sends them as raw values.
Basic usage
To make values available to processes running inside the sandbox, pass an environment_variables dictionary to Sandbox.run:
from cwsandbox import Sandbox
with Sandbox.run(
environment_variables={"LOG_LEVEL": "info"},
) as sandbox:
result = sandbox.exec([
"python",
"-c",
"import os; print(os.environ.get('LOG_LEVEL'));",
]).result()
print(result.stdout.strip()) # "info"
Session-level defaults
When you need the same variables in several sandboxes, define them once on a session instead of repeating them per sandbox. Individual sandboxes can override session defaults or add their own variables:
from cwsandbox import SandboxDefaults, Session
defaults = SandboxDefaults(
environment_variables={
"PROJECT_ID": "my-project",
"LOG_LEVEL": "info",
},
)
with Session(defaults) as session:
with session.sandbox() as sb1:
result = sb1.exec([
"python",
"-c",
"import os; print(os.environ.get('LOG_LEVEL'));",
]).result()
print(result.stdout.strip()) # "info"
# Override LOG_LEVEL and add new variable
with session.sandbox(
environment_variables={
"LOG_LEVEL": "debug", # Override session default
"MODEL_NAME": "gpt-4", # Add new variable
}
) as sb2:
result = sb2.exec([
"python",
"-c",
"import os; "
"print(os.environ.get('PROJECT_ID')); "
"print(os.environ.get('LOG_LEVEL')); "
"print(os.environ.get('MODEL_NAME'));",
]).result()
lines = result.stdout.strip().split("\n")
print(lines) # ["my-project", "debug", "gpt-4"]
Remote functions
Remote functions inherit environment variables from the session and can declare their own through the @session.function decorator. The SDK merges function-level variables with session defaults at call time:
with Session(defaults) as session:
@session.function(environment_variables={"MODEL_VERSION": "v2.0"})
def process(task_id: int) -> dict:
import os
return {
"task": task_id,
"project": os.environ.get("PROJECT_ID"), # From session defaults
"version": os.environ.get("MODEL_VERSION"), # From function decorator
}
result = process.remote(42).result()
print(result) # {"task": 42, "project": "my-project", "version": "v2.0"}
Environment variables are passed by reference. Subsequent function calls reflect mutations to the dictionary after decoration, as shown in the following example.
env_vars = {"MODEL_VERSION": "v2.0"}
@session.function(environment_variables=env_vars)
def process(task_id: int) -> dict:
import os
return {"version": os.environ.get("MODEL_VERSION")}
result = process.remote(42).result() # version: "v2.0"
env_vars["MODEL_VERSION"] = "v3.0" # Mutate the dictionary
result = process.remote(42).result() # version: "v3.0" (changed)