ai-sandbox (Python SDK)
Section 8.3 / Build Order 41.
from ai_sandbox import Client
client = Client() # reads credentials written by `ai-sandbox login`
sandbox = client.launch(template="llama-3-8b") # gpu/provider/hours auto-defaulted
print(sandbox.jupyter_url)
Install
pip install -e .
Auth
Client() resolves credentials in this order: an explicit api_key= argument,
the AI_SANDBOX_API_KEY environment variable, then ~/.ai-sandbox/credentials.json
(written by ai-sandbox login — see the cli/ package — or by calling
client.device_login() directly). There is never a manual API-key
copy/paste step; login is always the browser-based device-authorization flow
described in Section 8.2. base_url resolves the same way, via
AI_SANDBOX_API_URL or the credentials file, falling back to
http://localhost:8000.
Token refresh
Access tokens are deliberately short-lived. device_login() and the CLI's
ai-sandbox login both also store a refresh_token alongside the access
token. When any request gets a 401, Client transparently exchanges the
refresh token for a new access token (POST /auth/refresh) and retries the
request exactly once — this happens automatically, with no code required on
your end. The backend rotates the refresh token on every use, so the new one
is persisted back to ~/.ai-sandbox/credentials.json immediately.
If the retry also 401s, the refresh token itself is gone (revoked by
ai-sandbox logout, or expired) and the original NotAuthenticatedError
propagates — that's a real "please log in again", not a transient failure to
retry around.
This exists because a live launch on 2026-07-27 had its access token expire
mid-poll and died with "Not logged in" while the GPU it had provisioned kept
billing, with no way to recover the instance id. Long-running calls
(launch()'s poll loop in particular) are safe across a token expiry now.
Live progress
client.launch(...) blocks and streams progress via an on_progress
callback (defaults to printing [ai-sandbox] <stage> lines) while the
request is in flight, and continues polling GET /sandbox/instances/{id}
if the server hands the launch off to background provisioning (rare — only
when the synchronous wait exceeds its own patience window, controlled by
poll_timeout_seconds / poll_interval_seconds). See
client.py's module docstring for the full design and its limits.
Errors
Every exception this SDK raises inherits from ai_sandbox.AiSandboxError, so
except AiSandboxError is always a safe catch-all. Beyond that, catch the
specific type when you need to react differently:
| Exception | Cause | Notes |
|---|---|---|
NotAuthenticatedError |
No credentials, or refresh also failed | Run ai-sandbox login, pass api_key=, or set AI_SANDBOX_API_KEY |
QuotaExceededError |
HTTP 402 — Gate A rejection | Projected cost exceeds remaining balance |
TemplateNotFoundError |
HTTP 404 on launch | Unknown template_id |
MissingExplicitGpuError |
HTTP 422 | custom-docker/benchmarking launches require an explicit gpu= |
InvalidLaunchRequestError |
HTTP 400 | Malformed request — e.g. neither/both of template/free_text_request set |
ProvisioningFailedError |
HTTP 503, or a definite RUNTIME_FAILED |
Every provider in the routing order failed |
FreeTextReviewQueuedError |
Section 7.4 Tier 2 | Not an HTTP error (still a 202) — no instance was created; the request is queued for admin review. Carries review_queue_id |
ProvisioningTimeoutError |
Client-side poll budget exhausted after a 202 handoff | The instance is real and still provisioning server-side — this is your poll timeout expiring, not a server failure. Carries sandbox_instance_id; keep polling with client.get_instance(...) yourself |
DeviceLoginTimeoutError |
device_login()'s device code expired (10 minute window) |
|
DeviceLoginDeniedError |
The user explicitly denied the device authorization request | |
AiSandboxAPIError |
Catch-all for any other non-2xx response | Carries .status_code and .body so nothing is silently swallowed |
QuotaExceededError, TemplateNotFoundError, MissingExplicitGpuError,
InvalidLaunchRequestError, and ProvisioningFailedError are all
AiSandboxAPIError subclasses, so they carry .status_code and .body too.
The mapping from HTTP status to exception type lives in
client.py's _raise_for_status() — see exceptions.py for the full
hierarchy and each type's docstring.
from ai_sandbox import Client, QuotaExceededError, ProvisioningTimeoutError
client = Client()
try:
sandbox = client.launch(template="llama-3-8b")
except QuotaExceededError as e:
print(f"Over budget: {e}")
except ProvisioningTimeoutError as e:
# The instance kept provisioning past our poll budget — it isn't lost.
sandbox = client.get_instance(e.sandbox_instance_id)
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_sandbox_platform-0.1.0.tar.gz.
File metadata
- Download URL: ai_sandbox_platform-0.1.0.tar.gz
- Upload date:
- Size: 31.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
859ff7371aebb9ded49b5491cee3409690462c83a4132354964e8a68c5c3294f
|
|
| MD5 |
0e0c6252167a090440349ddbcf0784f6
|
|
| BLAKE2b-256 |
6c7ceab7978524f21175b7b388b5f0d8dc0e2b70a212303202d562e0d82a1f1e
|
Provenance
The following attestation bundles were made for ai_sandbox_platform-0.1.0.tar.gz:
Publisher:
publish-packages.yml on NuovoForte-Co/Docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_sandbox_platform-0.1.0.tar.gz -
Subject digest:
859ff7371aebb9ded49b5491cee3409690462c83a4132354964e8a68c5c3294f - Sigstore transparency entry: 2568490851
- Sigstore integration time:
-
Permalink:
NuovoForte-Co/Docker@db633a9b97a9ec0da7af906c9f2bdefee5c597ec -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NuovoForte-Co
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-packages.yml@db633a9b97a9ec0da7af906c9f2bdefee5c597ec -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file ai_sandbox_platform-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ai_sandbox_platform-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afa640f177ce2ce132d3a603fe748c1b3ab8ce981418256ca3e534d3fcb78733
|
|
| MD5 |
9169ae0d174ac0f56a67eda3a7185dfd
|
|
| BLAKE2b-256 |
16ac97529a374355a8212d3e40d1c66bbdb2249b8c1f7414c6a016387e8acbf8
|
Provenance
The following attestation bundles were made for ai_sandbox_platform-0.1.0-py3-none-any.whl:
Publisher:
publish-packages.yml on NuovoForte-Co/Docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_sandbox_platform-0.1.0-py3-none-any.whl -
Subject digest:
afa640f177ce2ce132d3a603fe748c1b3ab8ce981418256ca3e534d3fcb78733 - Sigstore transparency entry: 2568490859
- Sigstore integration time:
-
Permalink:
NuovoForte-Co/Docker@db633a9b97a9ec0da7af906c9f2bdefee5c597ec -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NuovoForte-Co
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-packages.yml@db633a9b97a9ec0da7af906c9f2bdefee5c597ec -
Trigger Event:
workflow_dispatch
-
Statement type: