This release is a pre-release and may not be stable for production use.
Usage
GMI AgentBox SDK (gmi-agentbox-sdk) is a thin Python client for AgentBox.
Install
python -m pip install gmi-agentbox-sdk
Requires Python 3.9+. TLS uses certifi.
Authenticate
To create an AgentBox API key, open API keys, then click Create API key. Store the key securely; it authenticates requests for your organization.
export GMI_AGENTBOX_API_KEY="your-api-key"
GMI_AGENTBOX_API_KEY is required when constructing AgentBoxClient() with no
api_key= argument.
Or pass it to the client:
from agentbox_sdk import AgentBoxClient
client = AgentBoxClient(api_key="your-api-key")
The default API root is production (used when GMI_AGENTBOX_BASE_URL is unset):
https://api.gmi-serving.com/v1/agents
Resource paths such as /deployments and /tasks are joined onto that root.
Override the full root with GMI_AGENTBOX_BASE_URL or AgentBoxClient(base_url=...).
Quickstart
import time
from agentbox_sdk import AgentBoxClient, SandboxFailed, SandboxWaitTimeout
client = AgentBoxClient()
# Available values vary by organization. Use the catalogue to select an IDC
# and a SKU for the Sandbox runtime.
idcs = client.idcs.list(runtime="sandbox")
# Choose an `idc_id` returned above. This is the production example value.
idc_id = "us-central-iowa16"
products = client.products.list(idc_name=idc_id, runtime="sandbox")
# Choose an `instance_type` returned above.
instance_type = "gmi.sandbox.small"
def wait_for_template(agent, timeout=600, poll_interval=3):
deadline = time.monotonic() + timeout
while True:
agent.refresh()
status = agent.template_build_status
if status == "ready" or status is None:
return
if status == "error":
raise RuntimeError(agent.template_build_error or "Sandbox image build failed")
if time.monotonic() >= deadline:
raise TimeoutError(f"Sandbox image is still {status!r} after {timeout}s")
print("...")
time.sleep(poll_interval)
agent = None
sandbox = None
try:
agent = client.agents.create(
title="agentbox-demo", # choose a unique name
image_url="docker.io/library/alpine:3.20",
idc=idc_id,
instance_type=instance_type,
runtime="sandbox",
)
print("Building Sandbox image; a new image can take several minutes.")
wait_for_template(agent)
sandbox = agent.launch(instance_type=instance_type)
sandbox.wait_until_running() # default timeout 300s
print(sandbox.status, sandbox.endpoint_url)
execution = sandbox.execute("echo hello")
print(execution.status, execution.exit_code, execution.data.get("stdout"))
except SandboxFailed as exc:
print("failed", exc.status, exc.message)
except SandboxWaitTimeout:
print("still not running", sandbox.status, sandbox.last_error)
finally:
if sandbox is not None:
sandbox.delete()
if agent is not None:
agent.delete()
Use client.idcs.list(runtime="sandbox") and
client.products.list(idc_name=..., runtime="sandbox") to discover available
Sandbox data centers and SKUs.
Register an Agent
agent = client.agents.create(
title="agentbox-demo",
image_url="docker.io/library/alpine:3.20",
idc=idc_id,
runtime="sandbox",
env=[{"name": "GMI_MODELS", "value": "llama", "secret": False}],
)
print(agent.slug, agent.launchable)
generated_api_keyis plaintext only on create (and rare patch retries).agent.launchableis false when the upstream template is missing.
Later:
agent = client.agents.get("agentbox-demo")
page = client.agents.list(page=1, page_size=20)
agent.update(title="renamed")
agent.delete()
Launch a Sandbox
sandbox = agent.launch(instance_type=instance_type)
# or: client.sandboxes.launch(agent.slug, instance_type=..., idc_name=agent.idc)
sandbox.wait_until_running(timeout=300, poll_interval=2.0)
sandbox.refresh()
print(sandbox.status, sandbox.last_error, sandbox.endpoint_url)
wait_until_running polls until running. It raises:
SandboxFailedif status iserror,deleted,stopped, orstoppingSandboxWaitTimeoutif the timeout elapses first
endpoint_url is empty until the sandbox is running, and can still be empty
after running. Do not assume an HTTP URL is always present.
Metadata and expiry
Both are sandbox-runtime only. metadata is your own labels.
timeout_seconds is the lifetime in seconds from now. Omit it to keep the
platform TTL and auto-renew. A positive value pins the expiry. Read the
effective timestamp from sandbox.expires_at after refresh() or
set_timeout().
sandbox = agent.launch(
instance_type=instance_type,
metadata={"session": "abc"},
timeout_seconds=3600,
)
sandbox.refresh()
print(sandbox.metadata, sandbox.expires_at, sandbox.expiry_pinned)
sandbox.set_timeout(6 * 3600)
page = client.sandboxes.list(metadata={"session": "abc"})
set_timeout works while the sandbox is running or paused. It can shorten or
extend the remaining lifetime, and it pins the sandbox so later reads do not
auto-renew it.
pause() pauses a running sandbox. Disk files are kept (except /tmp, which
is cleared on resume); memory and running processes are not. A paused sandbox
stops consuming run time. The call returns when the pause is accepted;
status is usually pausing. Poll with refresh() until it is paused.
paused_expire_at is the deadline to resume before the sandbox and its disk
are reclaimed.
sandbox.pause()
while sandbox.status != "paused":
time.sleep(2)
sandbox.refresh()
print(sandbox.paused_expire_at)
resume() wakes a paused sandbox. Omit timeout_seconds to keep the run time
that was left at pause. Set it (>= 60) to reset that run time and pin the
expiry. The call returns when the resume is accepted; status is usually
resuming. Poll with wait_until_running(). Resume is a cold start: disk
files come back except /tmp, processes are not restored, and the start
command is not re-run.
sandbox.resume()
sandbox.wait_until_running()
sandbox.resume(timeout_seconds=3600)
Snapshots
A snapshot saves a running sandbox so new sandboxes of the same Agent can
start from it. Creation is asynchronous: the snapshot starts creating; wait
for ready. Launching from a snapshot inherits its sizing and IDC, so
instance_type can be omitted.
snapshot = sandbox.create_snapshot(name="base")
snapshot.wait_until_ready(timeout=600)
clone = agent.launch(snapshot_id=snapshot.id)
clone.wait_until_running()
snapshots = agent.list_snapshots() # newest first
snapshot.rename("base-v2") # only when ready or error
snapshot.delete() # async; status becomes deleting
wait_until_ready() raises SnapshotFailed if the status becomes error,
deleting or delete_failed, and SnapshotWaitTimeout if the timeout
elapses first. A snapshot from client.sandboxes.create_snapshot() does not
know its Agent; poll it with client.agents.list_snapshots() instead.
Run commands and transfer files
# Finished command
result = sandbox.execute("echo hello")
print(result.status, result.exit_code, result.data.get("stdout"))
# Start a long-running command, then cancel it.
execution = sandbox.execute("sleep 120", wait=False)
if execution.accepted:
sandbox.cancel_execution(execution.id)
# File round trip
sandbox.upload_file(path="/home/user/input.txt", file=b"hello\n")
download = sandbox.download_file(path="/home/user/input.txt")
print(download.filename, download.content)
wait=False returns an accepted execution; retrieve its latest state with
sandbox.get_execution(execution.id). wait_timeout_seconds accepts values
from 1 through 25 and is omitted when wait=False. File paths must be absolute
and cannot contain . or .. segments.
List and filter sandboxes
page = client.sandboxes.list() # omits stopped and deleted
page = client.sandboxes.list(status=["running", "creating", "error"])
page = client.sandboxes.list(agent_id=agent.id, status="running")
page = client.sandboxes.list(metadata={"session": "abc"})
page = agent.sandboxes(metadata={"session": "abc"})
The default Sandbox list excludes stopped and deleted.
Pass status when you need those.
Delete
sandbox.delete() # one-way; the sandbox cannot be restarted
agent.delete() # does not stop or delete remaining sandboxes
Always delete sandboxes you launched in tests. They bill the Console account.
Log stream
The SDK supports log streaming when the Sandbox provides the logs_stream
capability:
if sandbox.capabilities.get("logs_stream"):
for event in sandbox.stream():
print(event.event, event.data)
if event.event == "status" and isinstance(event.data, dict):
break
When unavailable, this call raises an unsupported-runtime error. A backend can enable the capability without requiring an SDK update.
Template build logs
Sandbox Agents expose paged template build logs. Container Agents raise
NotSupportedError (HTTP 501). GMI does not persist these logs.
import time
from agentbox_sdk import GoneError
builds = agent.list_builds()
build_id = builds[0].id
offset = 0
while True:
try:
page = agent.build_logs(build_id, offset=offset)
except GoneError:
print("logs no longer available")
break
for entry in page.entries:
print(entry.level, entry.message)
offset = page.next_offset
if page.has_more:
continue
build = agent.get_build(build_id)
if build.status in ("ready", "error"):
try:
final = agent.build_logs(build_id, offset=offset)
except GoneError:
print("logs no longer available")
break
for entry in final.entries:
print(entry.level, entry.message)
if build.status == "error" and build.failure is not None:
raise RuntimeError(build.failure.message)
break
time.sleep(2)
has_more false only means nothing more is available right now. Keep polling
from next_offset while the build is waiting or building, then read one
last page after it reaches ready or error. 410 means the logs are gone,
including for a successful build.
Eligibility and metrics
entitlement = client.eligibility()
print(entitlement.eligible, entitlement.data_centers)
if sandbox.capabilities.get("metrics"):
batch = sandbox.metrics(start=start, end=end, kinds=["cpu", "memory"], step=60)
series = sandbox.metrics_timeseries(kind="cpu", start=start, end=end)
print(series.empty_reason, series.points)
kinds omitted means the API default (all 8 charts): gpu_util, gpu_mem,
cpu, memory, disk_read, disk_write, net_rx, net_tx. start /
end are unix seconds. Metrics are callable only when the Sandbox provides
the metrics capability; otherwise the service reports that the runtime does
not support them.
Concepts
| Name | Meaning |
|---|---|
idc / idc_name |
Data center identifier, not a region label. |
instance_type |
Billing SKU, not the product object name. |
Errors
from agentbox_sdk import (
AuthenticationError,
SandboxFailed,
SandboxWaitTimeout,
NotFoundError,
UnprocessableError,
)
try:
client.agents.get("missing")
except NotFoundError as exc:
print(exc.status_code, exc.message)
401 is AuthenticationError (for example, when the API key is invalid).
422 is UnprocessableError (locked field / template mismatch). 410 is
GoneError (template build logs reclaimed). 501 is NotSupportedError
(template build APIs on a container Agent) and is not retried as a server
error. See
Reference.
Metadata
Release files for gmi-agentbox-sdk 0.1.0b6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gmi_agentbox_sdk-0.1.0b6.tar.gz | 25.9 kB | Without provenance | Details for gmi_agentbox_sdk-0.1.0b6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gmi_agentbox_sdk-0.1.0b6-py3-none-any.whl | Python 3 | none | any | Details for gmi_agentbox_sdk-0.1.0b6-py3-none-any.whl |
Total release size: 47.0 kB
Release files / gmi_agentbox_sdk-0.1.0b6.tar.gz
| Download URL | gmi_agentbox_sdk-0.1.0b6.tar.gz |
|---|---|
| Size | 25.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
571ac29879c8993736a376b01b9e7d14df1c8fe6bdafc0b102b8a5bf0601eed2
|
|
BLAKE2b-256 checksum How to use checksums |
27487dfbd86471189814eae7436292b3b35e04f7f36bc2fb230d4a8026aefd05
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / gmi_agentbox_sdk-0.1.0b6-py3-none-any.whl
| Download URL | gmi_agentbox_sdk-0.1.0b6-py3-none-any.whl |
|---|---|
| Size | 21.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2381655a392e31f8e9559253513fd3fd28ecbaf7b44bfb51ab0a05d4c55926e5
|
|
BLAKE2b-256 checksum How to use checksums |
e57d6eaa8d04ccec6d9a134e08b71fbab4a14cefc95e47762ede2664919a5b5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for gmi-agentbox-sdk 0.1.0b6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.