> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gmicloud.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK reference

> Classes and methods in the gmi-agentbox-sdk Python package.

```bash theme={null}
python -m pip install gmi-agentbox-sdk
```

```python theme={null}
from agentbox_sdk import AgentBoxClient
```

Requires Python 3.9+. For workflows and examples, start with the [Quickstart](https://docs.gmicloud.ai/agentbox-sdk/quickstart.md).

## Client

### `AgentBoxClient`

```python theme={null}
AgentBoxClient(api_key=None, base_url=None, *, timeout=30.0)
```

Creates a client.

**Parameters**

* `api_key` (*str, optional*): API key. Defaults to the `GMI_AGENTBOX_API_KEY` environment variable. Raises `ValueError` if neither is set.
* `base_url` (*str, optional*): API root. Defaults to `GMI_AGENTBOX_BASE_URL`, then `https://api.gmi-serving.com/v1/agents`.
* `timeout` (*float*): Request timeout in seconds. Default `30.0`.

**Attributes**

* `agents`: Agent operations. See [Agents](#agents).
* `sandboxes`: Sandbox operations by ID. See [Sandboxes](#sandboxes).
* `snapshots`: Snapshot operations by ID. See [Snapshots](#snapshots).
* `idcs`, `products`: Data center and size catalog. See [Catalog](#catalog).

### client.eligibility

```python theme={null}
client.eligibility() -> Eligibility
```

Returns whether your organization can launch, and in which data centers.

**Returns**: `Eligibility` with `eligible` (*bool*) and `data_centers` (*list*).

## Catalog

### client.idcs.list

```python theme={null}
client.idcs.list(*, runtime=None) -> list[Idc]
```

Lists data centers. Pass `runtime="sandbox"` for sandbox data centers.

**Returns**: a list of `Idc`, each with `idc_id` (use this as `idc` / `idc_name`) and `name`.

### client.products.list

```python theme={null}
client.products.list(*, idc_name=None, runtime=None) -> list[Product]
```

Lists sizes available in a data center.

**Returns**: a list of `Product`, each with `instance_type` (the size ID to launch with) and `price`.

## Agents

### client.agents.create

```python theme={null}
client.agents.create(*, title, image_url=None, idc=None, instance_type=None,
                     runtime=None, start_cmd=None, env=None, ports=None,
                     image_credential=None, short_desc=None, ...) -> Agent
```

Creates an Agent and starts its image build. Does not start a sandbox.

**Parameters**

* `title` (*str*): Agent name.
* `runtime` (*str*): `"sandbox"` for sandboxes.
* `idc` (*str*): Data center ID. Required when `runtime="sandbox"`.
* `instance_type` (*str*): Size ID. Required when `runtime="sandbox"`.
* `image_url` (*str, optional*): Container image.
* `start_cmd` (*str, optional*): Command the sandbox runs on start.
* `env` (*list\[dict], optional*): Environment variables, each `{"name", "value", "secret"}`.
* `ports` (*list\[dict], optional*): Port definitions.
* `image_credential` (*dict, optional*): Private registry login, `{"username": ..., "secret": ...}`.
* `short_desc` (*str, optional*): Short description.

**Returns**: `Agent`.

**Raises**: `UnprocessableError` (422) when a sandbox Agent has no `idc` or `instance_type`.

### client.agents.get

```python theme={null}
client.agents.get(slug) -> Agent
```

### client.agents.list

```python theme={null}
client.agents.list(*, page=1, page_size=20) -> Page
```

**Returns**: `Page` of `Agent`.

### client.agents.update

```python theme={null}
client.agents.update(slug, **fields) -> Agent
```

Updates the given fields. Locked fields raise `UnprocessableError` (422).

### client.agents.delete

```python theme={null}
client.agents.delete(slug) -> None
```

**Raises**: `ConflictError` (409) while the Agent still has sandboxes. It can still return 409 for a few seconds after the last one is deleted; retry.

### Agent

| Property | Type | Description |
| - | - | - |
| `id` | *str* | Agent ID |
| `slug` | *str* | Stable identifier used by `get`, `update` and `delete` |
| `title` | *str* | Name |
| `idc` | *str* | Data center ID |
| `image_url` | *str* | Container image |
| `runtime` | *str* | Runtime, for example `sandbox` |
| `template_build_status` | *str* | Image build status: `waiting`, `building`, `ready` or `error` |
| `template_build_error` | *str* | Build error message when the build failed |
| `env` | *list* | Environment variables |
| `generated_api_key` | *str* | Generated model API key. Returned only by `create`, and only when `env` includes `GMI_MODELS`. Read it before you call `refresh()` or `update()`; they clear it |
| `launchable` | *bool* | Whether a sandbox can launch from this Agent |

Methods on `Agent`:

| Method | Description |
| - | - |
| `refresh() -> Agent` | Reloads the Agent. |
| `update(**fields) -> Agent` | Same as `client.agents.update`. |
| `delete() -> None` | Same as `client.agents.delete`. |
| `launch(...) -> Sandbox` | See `agent.launch` below. |
| `sandboxes(*, page=1, page_size=20, metadata=None) -> Page` | Lists this Agent's sandboxes. |
| `list_snapshots() -> list[Snapshot]` | Lists this Agent's snapshots, newest first. |
| `list_builds() -> list[TemplateBuild]` | Up to the 100 newest image builds. |
| `get_build(build_id) -> TemplateBuild` | One image build. |
| `build_logs(build_id, *, offset=0, limit=100, level=None) -> BuildLogPage` | One page of build logs. |

### agent.launch

```python theme={null}
agent.launch(*, instance_type=None, idc_name=None, env=None, display_name=None,
             metadata=None, timeout_seconds=None, snapshot_id=None, ...) -> Sandbox
```

Launches a sandbox and returns immediately. The sandbox starts as `pending`.

**Parameters**

* `instance_type` (*str*): Size ID. Required unless `snapshot_id` is set. Ignored when `snapshot_id` is set.
* `idc_name` (*str, optional*): Defaults to the Agent's data center. Must match it.
* `env` (*list\[dict], optional*): Environment variables for this sandbox. Use `"secret": True` for secrets.
* `display_name` (*str, optional*): Display name.
* `metadata` (*dict\[str, str], optional*): Your labels. Up to 32 keys; keys match `^[A-Za-z0-9_.-]{1,63}$`; values up to 256 characters; `source` and `task_name` are reserved.
* `timeout_seconds` (*int, optional*): Lifetime in seconds from launch, minimum 60. Omit for the platform default lifetime, which renews automatically. A value pins the expiry.
* `snapshot_id` (*str, optional*): Launch from a `ready` snapshot of this Agent.

**Returns**: `Sandbox`.

**Raises**: `BadRequestError` (400) for invalid metadata or a timeout under 60; `NotFoundError` (404) for an unknown snapshot; `ConflictError` (409) when the snapshot is not `ready`.

### agent.build\_logs

```python theme={null}
agent.build_logs(build_id, *, offset=0, limit=100, level=None) -> BuildLogPage
```

**Parameters**

* `offset` (*int*): Zero-based. Pass the previous page's `next_offset`.
* `limit` (*int*): 1 to 100. Default 100.
* `level` (*str, optional*): `debug`, `info`, `warn` or `error`.

**Returns**: `BuildLogPage` with `entries` (each `offset`, `level`, `message`, `timestamp`), `next_offset` and `has_more`.

**Raises**: `GoneError` (410) when the logs have expired.

## Sandboxes

Every method below exists on a `Sandbox` object, and on `client.sandboxes` with the sandbox ID as the first argument. For example, `sandbox.pause()` is the same as `client.sandboxes.pause(sandbox_id)`. The exceptions are `wait_until_running` and `refresh`, which exist only on a `Sandbox` object.

Some collection methods return a different type:

* `client.sandboxes.set_timeout`, `pause` and `resume` return `SandboxExpiry`, `SandboxPause` and `SandboxResume`, not a `Sandbox`.
* `client.sandboxes.create_snapshot` returns a `Snapshot` with no Agent slug. Its `wait_until_ready` and `refresh` raise `ValueError`. Use `sandbox.create_snapshot` when you need to wait for the snapshot.

### client.sandboxes.launch

```python theme={null}
client.sandboxes.launch(slug, *, instance_type=None, idc_name=None, ...) -> Sandbox
```

Same as `agent.launch`, by Agent slug. `idc_name` and `instance_type` are required unless `snapshot_id` is set. A missing value raises `ValueError`.

### client.sandboxes.list

```python theme={null}
client.sandboxes.list(*, agent_id=None, status=None, page=1, page_size=20, metadata=None) -> Page
```

**Parameters**

* `agent_id` (*str, optional*): Only this Agent's sandboxes.
* `status` (*str or list\[str], optional*): Filter by status. If omitted, `stopped` and `deleted` are excluded.
* `metadata` (*dict\[str, str], optional*): Exact match; all keys must match.

**Returns**: `Page` of `Sandbox`.

### client.sandboxes.get

```python theme={null}
client.sandboxes.get(sandbox_id) -> Sandbox
```

### sandbox.wait\_until\_running

```python theme={null}
sandbox.wait_until_running(*, timeout=300.0, poll_interval=2.0) -> Sandbox
```

Polls until the status is `running`.

**Raises**: `SandboxFailed` if the status becomes `error`, `deleted`, `stopped` or `stopping`; `SandboxWaitTimeout` if `timeout` passes first.

### sandbox.refresh

```python theme={null}
sandbox.refresh() -> Sandbox
```

Reloads the sandbox.

### sandbox.set\_timeout

```python theme={null}
sandbox.set_timeout(timeout_seconds) -> Sandbox
```

Sets the lifetime to now plus `timeout_seconds` (minimum 60) and pins it. Works while the sandbox is running or paused.

**Raises**: `BadRequestError` (400) if under 60 or above your account maximum; `ConflictError` (409) if the sandbox is not running or paused.

### sandbox.pause

```python theme={null}
sandbox.pause() -> Sandbox
```

Pauses a running sandbox. Returns when the pause is accepted; status is usually `pausing`. Poll with `refresh` until `paused`.

**Raises**: `ConflictError` (409) if the sandbox is not running.

### sandbox.resume

```python theme={null}
sandbox.resume(*, timeout_seconds=None) -> Sandbox
```

Resumes a paused sandbox. Returns when accepted; status is usually `resuming`. Poll with `wait_until_running`.

**Parameters**

* `timeout_seconds` (*int, optional*): Omit to keep the run time left at pause. A value (60 or more) restarts the lifetime and pins it.

**Raises**: `BadRequestError` (400) if `timeout_seconds` is under 60; `ConflictError` (409) if the sandbox is not paused.

### sandbox.execute

```python theme={null}
sandbox.execute(command, *, wait=True, wait_timeout_seconds=None) -> Execution
```

Runs a command.

**Parameters**

* `command` (*str*): Command to run.
* `wait` (*bool*): Wait for the command to finish. Default `True`.
* `wait_timeout_seconds` (*int, optional*): How long to wait, 1 to 25. Ignored when `wait=False`.

**Returns**: `Execution`. `accepted` is true when the command is still running.

### sandbox.get\_execution

```python theme={null}
sandbox.get_execution(execution_id) -> Execution
```

### sandbox.cancel\_execution

```python theme={null}
sandbox.cancel_execution(execution_id) -> Execution
```

### sandbox.upload\_file

```python theme={null}
sandbox.upload_file(*, path, file) -> list[dict]
```

**Parameters**

* `path` (*str*): Absolute destination path in the sandbox. No `.` or `..` segments.
* `file` (*bytes, str, PathLike or binary file*): Content, a local path, or an open binary file.

### sandbox.download\_file

```python theme={null}
sandbox.download_file(*, path) -> FileDownload
```

**Returns**: `FileDownload` with `content` (*bytes*), `filename` and `headers`.

### sandbox.shell

```python theme={null}
sandbox.shell(*, timeout=None)
```

Opens an interactive shell. Returns a `websocket-client` connection. See [Interactive shell](https://docs.gmicloud.ai/agentbox-sdk/shell.md) for the message format.

### sandbox.stream

```python theme={null}
sandbox.stream(*, timeout=None) -> Iterator[StreamEvent]
```

Yields status events. Each `StreamEvent` has `event`, `data` and `raw`.

### sandbox.create\_snapshot

```python theme={null}
sandbox.create_snapshot(*, name=None) -> Snapshot
```

Saves a running sandbox. See [Snapshots](#snapshots).

### sandbox.metrics

```python theme={null}
sandbox.metrics(...)
sandbox.metrics_timeseries(...)
```

Not supported on sandboxes. Raises `NotSupportedError` (501).

### sandbox.delete

```python theme={null}
sandbox.delete() -> None
```

Deletes the sandbox. This cannot be undone.

### Sandbox

| Property | Type | Description |
| - | - | - |
| `id` | *str* | Sandbox ID |
| `status` | *str* | Current status |
| `endpoint_url` | *str or None* | `None` until an endpoint is assigned. Can still be `None` for a short time after `running` |
| `agent_id`, `agent_slug` | *str* | Owning Agent |
| `display_name` | *str* | Display name |
| `instance_type` | *str* | Size ID |
| `idc_name` | *str* | Data center ID |
| `last_error` | *str* | Last error message |
| `capabilities` | *dict* | Features enabled for this sandbox |
| `metadata` | *dict\[str, str]* | Your labels |
| `expires_at` | *str* | Expiry time |
| `expiry_pinned` | *bool* | True when you set the expiry, so it does not renew automatically |
| `paused_at` | *str* | When the sandbox was paused |
| `paused_expire_at` | *str* | Deadline to resume before the sandbox is deleted |
| `source_snapshot_id` | *str* | Snapshot it launched from, if any |

### Execution

| Property | Type | Description |
| - | - | - |
| `id` | *str* | Execution ID |
| `status` | *str* | For example `running`, `succeeded`, `cancelled` |
| `exit_code` | *int or None* | Exit code once finished |
| `accepted` | *bool* | True when the command is still running |
| `data` | *dict* | Full result, including `stdout`, `stderr`, `stdout_truncated` and `stderr_truncated` |

## Snapshots

### sandbox.create\_snapshot

```python theme={null}
sandbox.create_snapshot(*, name=None) -> Snapshot
```

Saves a running sandbox. The snapshot starts as `creating`.

**Parameters**

* `name` (*str, optional*): Up to 255 characters. If omitted, a name is generated from the sandbox name and the time.

**Raises**: `PermissionDeniedError` (403) if you are not the sandbox's creator or an organization owner; `ConflictError` (409) if the sandbox is not running.

### snapshot.wait\_until\_ready

```python theme={null}
snapshot.wait_until_ready(*, timeout=300.0, poll_interval=2.0) -> Snapshot
```

**Raises**: `SnapshotFailed` if the status becomes `error`, `deleting` or `delete_failed`; `SnapshotWaitTimeout` if `timeout` passes first.

### snapshot.rename

```python theme={null}
snapshot.rename(name) -> Snapshot
client.snapshots.rename(snapshot_id, name) -> Snapshot
```

Only a `ready` or `error` snapshot can be renamed. `name` is 1 to 255 characters.

**Raises**: `BadRequestError` (400) for an invalid name; `ConflictError` (409) while the snapshot is still creating or being deleted.

### snapshot.delete

```python theme={null}
snapshot.delete() -> Snapshot
client.snapshots.delete(snapshot_id) -> SnapshotDeletion
```

Deletes asynchronously; status becomes `deleting`.

### Snapshot

| Property | Type | Description |
| - | - | - |
| `id` | *str* | Snapshot ID |
| `name` | *str* | Name |
| `status` | *str* | `creating`, `ready`, `error`, `deleting` or `delete_failed` |
| `status_reason` | *str* | Why it is `error` or `delete_failed` |
| `agent_id` | *str* | Owning Agent |
| `source_sandbox_id` | *str* | Sandbox it was saved from |
| `idc_name` | *str* | Data center; sandboxes launched from it run here |
| `vcpu`, `ram_mb`, `disk_size_mb` | *int* | Size inherited at launch |
| `created_at`, `ready_at` | *str* | Timestamps |

## Errors

Service and connection errors derive from `AgentBoxSDKError`. Invalid input raises a plain `ValueError`. Service errors derive from `APIError`, which has `status_code`, `message`, `code` and `details`. See [Errors and limits](https://docs.gmicloud.ai/agentbox-sdk/errors-and-limits.md) for the full table.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.