Code Interpreter

Configuration reference

Every environment variable, grouped by what it controls, with defaults and the ones that matter.

Configuration is entirely environment-variable driven. The Compose files inline development defaults; .env.example in the repository root is the annotated template to copy from.

Variables are read by different components. A variable set on the API does nothing on the sandbox runner and vice versa: the Component column below says where each one belongs. The Compose and Helm files already route them correctly.

Core mode

VariableDefaultComponentDescription
LOCAL_MODEtrue in ComposeAPI, workerBypasses authentication entirely and stamps a fixed local principal. Development only.
CODEAPI_HARDENED_SANDBOX_MODEtrueAPI, worker, runner, gatewayKeeps microVM + NsJail hardening on. Only disable for local debugging.

Authentication

VariableDefaultDescription
CODEAPI_AUTH_PROVIDERlibrechat-jwtlibrechat-jwt or none.
CODEAPI_ALLOW_AUTH_PROVIDER_NONEunsetMust be true for CODEAPI_AUTH_PROVIDER=none to start outside local mode.
CODEAPI_JWT_ISSUERlibrechatMust match the iss the signer mints.
CODEAPI_JWT_AUDIENCEcodeapiMust match the aud the signer mints.
CODEAPI_JWT_ALLOWED_ALGSEdDSAAccepted signature algorithms.
CODEAPI_JWT_KIDlc-codeapi-1Key id. A token with an unknown kid is rejected.
CODEAPI_JWT_PUBLIC_KEYunsetVerifier key, PEM or base64 DER. Escaped \n allowed.
CODEAPI_JWT_JWKS_JSONunsetInline JWKS document, as an alternative to a single key.
CODEAPI_JWT_PUBLIC_KEYS_DIRunsetDirectory of PEM files named by kid, for rotation.
CODEAPI_JWT_MAX_TTL_SECONDS300Token lifetime cap. Max 300.
CODEAPI_JWT_CLOCK_SKEW_SECONDS30Clock skew tolerance. Max 30.
CODEAPI_TENANT_ISOLATION_STRICTunsetWhen true, rejects requests whose auth context carries no tenant id.

See Authentication for the full setup.

Internal secrets

VariableDefaultDescription
CODEAPI_INTERNAL_SERVICE_TOKENdev value in ComposeShared token between components. When unset, file-object routes and tool-call session routes are unauthenticated.
CODEAPI_EGRESS_GRANT_SECRETdev value in ComposeSigns egress grants. 32+ bytes in production.
CODEAPI_EXECUTION_MANIFEST_PRIVATE_KEYtest key in ComposeEd25519 signing key. Worker only.
SANDBOX_EXECUTION_MANIFEST_PUBLIC_KEYtest key in ComposeEd25519 verifier. Sandbox runner only.

The manifest keypair inlined in the Compose files and values-local.yaml is publicly known: the same one is hardcoded in the unit tests. Replace it. See production hardening.

Execution manifests

VariableDefaultDescription
EXECUTION_MANIFEST_TTL_SECONDS300Manifest validity window.
EXECUTION_MANIFEST_MAX_UPLOAD_BYTESn/aUpload budget granted to one execution.
EXECUTION_MANIFEST_MAX_OUTPUT_FILESn/aOutput file count budget.
EXECUTION_MANIFEST_MAX_REQUESTSn/aTotal gateway requests one execution may make.
SANDBOX_REQUIRE_EGRESS_MANIFESTtrueRunner refuses unsigned execute requests.
CODEAPI_EGRESS_LEDGER_REQUIREDtrueGateway requires a live ledger entry per grant.

Redis

VariableDefaultDescription
REDIS_HOSTredisHostname.
REDIS_PORT6379Port.
REDIS_PASSWORDlocaldev in ComposePassword.
REDIS_TLSunsetSet true for managed Redis requiring TLS.
SESSION_CACHE_TTL86400Seconds a session→sessionKey mapping is cached.

Object storage

VariableDefaultDescription
MINIO_ENDPOINTminioS3 endpoint host.
MINIO_PORT9000Endpoint port.
MINIO_USE_SSLfalseTLS to the endpoint.
MINIO_ACCESS_KEYminioadminAccess key.
MINIO_SECRET_KEYminioadminSecret key.
MINIO_BUCKETtest-bucketBucket name.
MINIO_NO_PORTfalseOmit an explicit port: for gateways that must not receive one.
FILE_SERVER_PORT3000File server listen port.

Despite the names, any S3-compatible endpoint works; the file server also supports IRSA authentication on EKS.

Sandbox runner

VariableDefaultDescription
KVM_ENABLEDtruemicroVM mode. false is NsJail-only: weaker isolation.
KVM_DEVICE_PATH/dev/kvmDevice to map in.
SANDBOX_PACKAGES_DIRECTORY/pkgsWhere runtimes are mounted inside the runner.
SANDBOX_MAX_CONCURRENT_JOBS8Parallel executions per runner.
SANDBOX_MAX_PROCESS_COUNT100PID limit inside the sandbox.
SANDBOX_RUN_TIMEOUT300000Run wall-clock limit (ms). Also the ceiling for a request's own run_timeout.
SANDBOX_RUN_CPU_TIME300000Run CPU-time limit (ms).
SANDBOX_COMPILE_TIMEOUT30000Compile phase limit (ms).
SANDBOX_RUN_MEMORY_LIMIT-1Run memory cgroup limit in bytes; -1 is unlimited.
SANDBOX_OUTPUT_MAX_SIZE65536Max stdout/stderr bytes before truncation.
SANDBOX_MAX_OPEN_FILES2048rlimit nofile.
SANDBOX_MAX_FILE_SIZE10000000rlimit fsize (bytes).
SANDBOX_RLIMIT_AS4096Address space rlimit (MB).
SANDBOX_USE_CGROUPV2trueUse cgroups v2.
SANDBOX_PER_JOB_UIDStrueAllocate a distinct UID per concurrent job.
SANDBOX_JOB_UID_BASE200000First UID in the per-job pool.
SANDBOX_JOB_GID_BASE200000First GID in the per-job pool.
SANDBOX_WORKSPACE_REAPER_MAX_AGE_SECONDS3600Age after which orphaned workspaces are reclaimed.
SANDBOX_EXECUTE_BODY_LIMIT50mbMax execute request body.
SANDBOX_LOG_LEVELINFOLog verbosity.
SANDBOX_ALLOWED_LOCAL_NETWORK_PORT0The single host port the sandbox may reach: the egress gateway.
SANDBOX_FORWARD_TARGETn/aWhere that port forwards to.

microVM launcher

VariableDefaultDescription
LAUNCHER_VCPUS2vCPUs per sandbox microVM.
LAUNCHER_RAM_MIB2048RAM per sandbox microVM.
LAUNCHER_LOG_LEVEL3libkrun log verbosity.

Timeouts

VariableDefaultDescription
JOB_TIMEOUT300000Budget for one job (ms), and the default ceiling for run_timeout.
MAX_RUN_TIMEOUTJOB_TIMEOUTCeiling for a request's own run_timeout (ms). Capped at JOB_TIMEOUT.
JOB_WAIT_GRACE_MS15000Margin between the timeout layers (ms).
JOB_PRIME_ALLOWANCE_MSCODEAPI_DEPENDENCY_INSTALL_TIMEOUT_MSTime reserved for the sandbox's prime phase (ms).
JOB_POSTPROCESS_ALLOWANCE_MS60000Time reserved for post-run output uploads (ms).

A request may pass run_timeout (ms) to cap its own run. It is clamped down to MAX_RUN_TIMEOUT, and again to the runner's SANDBOX_RUN_TIMEOUT: a caller can only narrow the deployment's ceiling, never raise it. Setting MAX_RUN_TIMEOUT above JOB_TIMEOUT has no effect, since a run that outlives the waits watching it is the failure this ordering exists to prevent. Raise JOB_TIMEOUT instead.

curl -sX POST http://localhost:3112/v1/exec \
  -H 'Content-Type: application/json' \
  -d '{"lang":"py","code":"while True: pass","run_timeout":3000}'

The limit is enforced by NsJail's --time_limit, which takes whole seconds and is rounded up, so a run can overshoot the requested value by up to one second (never more, and never less than asked): run_timeout: 1001 permits two seconds.

A run that exceeds its budget is a successful HTTP response describing a killed process, not an error:

{ "status": "TO", "code": 137, "signal": "SIGKILL", "stdout": "", "stderr": "" }

The three layers are deliberately staggered by JOB_WAIT_GRACE_MS: the sandbox kills the run, the worker waits one grace longer than everything the sandbox does with the job, and the API waits one grace longer than the worker. Each layer therefore outlives the one it is waiting on, so the structured timeout above propagates to the caller instead of racing an outer give-up and surfacing as a generic 500. Raise JOB_TIMEOUT and the rest follow automatically.

A sandbox spends its budget in sequence, not in parallel, so the worker's layer has to cover the sum of every phase:

PhaseBounded bySpent
PrimeJOB_PRIME_ALLOWANCE_MS (default CODEAPI_DEPENDENCY_INSTALL_TIMEOUT_MS, 120000)Input downloads, workspace restore, any pip install
CompileSANDBOX_COMPILE_TIMEOUTBefore the run, for compiled languages like Java
RunSANDBOX_RUN_TIMEOUT or the request's run_timeoutThe program itself
PostJOB_POSTPROCESS_ALLOWANCE_MS (60000)Walking the workspace and uploading outputs, after the run ends
GatewayEGRESS_GATEWAY_REQUEST_TIMEOUT_MS x2In hardened mode, the grant-creation and result-restore round trips that bracket the call

The sandbox does not answer when the run ends: it still has to walk the workspace and upload artifacts. The post allowance is sized for ordinary output, not for the pathological case where every one of SANDBOX_MAX_OUTPUT_FILES hits its own 30-second upload timeout (with the defaults, ceil(50/8) * 30s = 210s, which means the file server is broken rather than busy). Raise it if a deployment routinely emits many large artifacts.

Most of these are the runner's variables. The service reads them to size its own layers, so if you raise one on the runner, set it on the API and worker too, or those layers under-provision by the difference. The shipped Compose files and Helm chart already forward all of them to every process that computes the ladder.

The ladder bounds one job's time inside a worker. Queue delay sits outside it: the API's wait starts at enqueue, the worker's budget only once a worker picks the job up. On a saturated queue the API's wait can therefore expire before the job finishes, and what the caller should do about it depends on whether it ever started:

ResponseMeaningRetry?
503The job never started and was removed from the queue.Yes, nothing is running.
504A worker had already claimed it. The execution continues unobserved and may still upload output files.No, a retry duplicates it.
200 + status: "TO"The run itself exceeded its budget and was killed.Not an error; fix the code or raise the budget.

The 503 is only ever returned on positive evidence that no worker picked the job up; anything ambiguous is reported as 504.

run_timeout is a cooperative cap: a client that omits it still gets the full SANDBOX_RUN_TIMEOUT, and with PYTHON_CONCURRENCY=1 one runaway submission occupies a worker's Python slot for that entire window. On a deployment reachable by untrusted callers, lower SANDBOX_RUN_TIMEOUT to what your workloads genuinely need and scale PYTHON_CONCURRENCY with it, rather than relying on callers to cap themselves.

Worker concurrency

VariableDefaultDescription
PYTHON_CONCURRENCY1Concurrent Python jobs per worker.
OTHER_CONCURRENCY8Concurrent non-Python jobs per worker.
JOB_WINDOW1000Job scheduling window.
WORKER_HEALTH_PORT3113Worker health/metrics port.

Python gets its own queue and a lower default because scientific workloads are heavier. See Operations.

Rate limits

Applied per principal on the API.

VariableDefaultApplies to
MAX_REQUESTS20Executions per window
RATE_LIMIT_WINDOW30000Execution window (ms)
UPLOAD_MAX_REQUESTS30Uploads per window
UPLOAD_LIMIT_WINDOW300000Upload window (ms)
DOWNLOAD_MAX_REQUESTS60Downloads per window
DOWNLOAD_LIMIT_WINDOW60000Download window (ms)
FETCH_MAX_REQUESTS120File list/metadata calls per window
FETCH_LIMIT_WINDOW60000Fetch window (ms)
MAX_FILE_SIZE26214400Per-file upload cap (25 MiB)
CODEAPI_HTTP_JSON_LIMIT50mbMax JSON request body

Language runtimes

VariableDefaultDescription
CODEAPI_LANGUAGESallComma-separated subset of python, node, bun, bash, java.
SANDBOX_PACKAGES_PATH./data/pkgsHost path where runtimes are cached.
FORCE_REBUILDunsettrue wipes and rebuilds the packages volume.
PYTHON_VERSION, NODE_VERSION, BUN_VERSION, JAVA_VERSIONpinnedOverride a runtime version.
PYTHON_SHA256, NODE_SHA256, BUN_SHA256, JAVA_SHA256pinnedChecksum for a custom version.

Downloads are verified against SHA-256 checksums pinned for the default versions. Override a version and package_init verifies against the provider's published checksum file instead; set the matching *_SHA256 to pin your own.

Persistent sessions

Off by default. See Persistent sessions.

VariableDefaultDescription
CODEAPI_PERSIST_SESSIONSfalseCarry files and Python variables across runs.
CODEAPI_SESSION_STATE_MAX_BYTES104857600Snapshot cap (100 MiB). Oversize snapshots are skipped; the run still succeeds.
CODEAPI_SESSION_STATE_TTL_SECONDS604800Idle expiry of the Redis pointer (7 days), refreshed each run.

Dynamic dependencies

Off by default. See Dynamic dependencies.

VariableDefaultDescription
CODEAPI_ALLOW_DYNAMIC_DEPENDENCIESfalseAllow per-job pip installs.
CODEAPI_DEPENDENCY_INDEX_URLhttps://pypi.org/simplePackage index the runner fetches from.
CODEAPI_DEPENDENCY_MAX_COUNT50Max packages per job.
CODEAPI_DEPENDENCY_INSTALL_TIMEOUT_MS120000Install timeout.
CODEAPI_DEPENDENCY_MAX_BYTES262144000Total install size cap.

Service URLs

Set by the Compose files and the chart; override only for custom topologies.

VariableCompose value
SERVICE_PORT3112
SANDBOX_ENDPOINThttp://sandbox-runner:2000/api/v2
EGRESS_GATEWAY_URLhttp://egress_gateway:3190
FILE_SERVER_URLhttp://file_server:3000
TOOL_CALL_SERVER_URLhttp://tool_call_server:3033
EGRESS_GATEWAY_PORT3190
TOOL_CALL_SERVER_PORT3033
TOOL_CALL_REQUEST_TIMEOUT300000
TOOL_CALL_SESSION_EXPIRY600
EGRESS_GATEWAY_MAX_FILE_BYTES10000000
EGRESS_GATEWAY_MAX_TOOL_CALL_BYTES1048576

Telemetry

OpenTelemetry tracing, off by default. On Kubernetes set otel.enabled=true.

VariableDescription
OTEL_EXPORTER_OTLP_ENDPOINTCollector endpoint.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTTraces-specific endpoint.
OTEL_EXPORTER_OTLP_HEADERSExtra headers.
OTEL_RESOURCE_ATTRIBUTESResource attributes.

On this page