airflow.providers.common.ai.sandbox.boat

Boat backend for SandboxToolset.

Attributes

log

Classes

BoatSandboxBackend

Sandbox backend that runs agent commands in a Boat sandbox.

Module Contents

airflow.providers.common.ai.sandbox.boat.log[source]
class airflow.providers.common.ai.sandbox.boat.BoatSandboxBackend(*, boat_conn_id=None, org='personal', machine_type='default', ttl_seconds=3600, ready_timeout=300.0, request_timeout=30.0)[source]

Bases: airflow.providers.common.ai.sandbox.base.SandboxBackend

Sandbox backend that runs agent commands in a Boat sandbox.

Note

Experimental: this can change or be removed in a minor release of this provider. See Stable and experimental features.

Boat (formerly Ascii Box) is a hosted cloud-computer API: the Airflow worker needs only network access and an API key, with no local daemon or host virtualization.

Credentials come from a generic Airflow connection, resolved on first use: its password is the Boat API key, and its host, when set, the API base URL. Without a connection, the backend reads BOAT_API_KEY (required) and optional BOAT_BASE_URL (the full API base URL with its scheme) from the worker environment on first use.

Every sandbox is created with Boat’s noEnv flag, so it gets none of the account’s stored environment variables, secret files or credentials, and cannot act on the account or its other sandboxes. SandboxSpec.env is the only environment it receives.

Boat cannot enforce a deny-all, per-domain, or CIDR egress policy. create therefore refuses a SandboxSpec that asks for block_network=True, allow_egress_to, or allow_egress_to_cidrs, preserving the fail-closed contract. Pass SandboxSpec(block_network=False) (and set that on SandboxToolset) when open egress is acceptable.

Writes use Boat’s native file API, which accepts only paths that resolve under /home/user (where relative paths land) or /tmp. The parent directory is created first with mkdir -p in the guest, so a write anywhere else reaches the model as a recoverable error: mkdir’s own when the guest user cannot create the parent directory, and one carrying Boat’s invalid_path code when that directory exists or could be created. Reads use the inherited shell implementation, because the native read API takes no size parameter and would land a whole file in worker memory before max_bytes could reject it.

Parameters:
  • boat_conn_id (str | None) – Generic Airflow connection ID. Its password is the Boat API key and is required; its host, when set, is the full API base URL with its scheme, such as https://boat.dev/api/v1. None (default) reads BOAT_API_KEY and optional BOAT_BASE_URL from the worker environment instead.

  • org (str) – Boat wallet the sandbox is billed to, by organization id or name, or "personal" for the account’s own. Boat lets every member of an organization open, run commands in, and read and write files in a noEnv sandbox billed to it, so naming one puts them all inside the sandbox’s trust boundary. Default "personal", which also overrides the account’s active wallet.

  • machine_type (str) – Boat machine size: small, default, or large. Default "default".

  • ttl_seconds (int) – Server-side TTL in seconds after which Boat stops the sandbox even if the worker never destroyed it: a whole number from 1 to 2592000 (30 days). The sandbox is created without snapshots, so stopping it erases its disk. Default 3600.

  • ready_timeout (float) – Seconds allowed for provisioning, from the create request until the sandbox is ready. A create request that times out, fails in transport, or gets a server error is sent again with the same idempotency key, and again two seconds after each 409 idempotency_in_progress answer until ready_timeout runs out. Each resend gets what is left of ready_timeout plus request_timeout, so provisioning takes at most their sum. Default 300.

  • request_timeout (float) – HTTP timeout in seconds for a Boat API call that answers at once, such as the create request, a status check or a delete, and the time added to the operation’s own for a call that waits on one: a command’s deadline, or 120 seconds for a file write. Default 30.

name = 'boat'[source]

Short backend identifier (e.g. "sbx"), used in the toolset id.

create(*, spec=None)[source]

Provision one sandbox and return its handle (name or id).

spec of None means “no requirements stated”: the backend applies its own defaults and makes no guarantee. It is not the same as a default SandboxSpec, which is an explicit request for an isolated sandbox. The toolset always sends a concrete spec, so None only reaches a backend a caller drives directly.

Raise SandboxTerminalError if spec asks for something this backend cannot enforce, rather than provisioning something weaker than was asked for. It is terminal rather than recoverable because it states a configuration fact the model cannot see and cannot fix by retrying.

Every failure raised here is terminal, whichever class carries it. The model has no input into provisioning, so a SandboxError from create is not something it can work around; the toolset re-raises one as SandboxTerminalError and fails the task, so Airflow’s retry attempts the provisioning again.

run_command(sandbox, command, *, timeout, max_output_bytes)[source]

Run command through a shell in the sandbox, bounded by timeout seconds.

max_output_bytes bounds what the backend retains per stream while reading, so unbounded command output cannot exhaust worker memory before the toolset gets a chance to format it.

read_file(sandbox, path, *, max_bytes)[source]

Read a file from the sandbox.

Raise SandboxFileTooLargeError instead of transferring a file larger than max_bytes.

list_directory(sandbox, path)[source]

Return (name, is_dir) for each entry in a sandbox directory.

write_file(sandbox, path, content)[source]

Write content to path in the sandbox, creating parent directories.

The payload rides in the command itself, so this default is bounded by the guest’s command-line length. A backend that can stream stdin or upload directly should override.

destroy(sandbox)[source]

Request permanent deletion of the sandbox.

The API accepts the request and returns before teardown finishes, so a successful return means accepted, not gone.

Was this entry helpful?