Cua Docs

Create Fleet capacity

Create reusable Cloud Fleet capacity with Python or TypeScript.

Create a reusable pool before tasks claim computers from it. Python uses the Cua Sandbox SDK, the programming model for one isolated computer that can run locally or on Cloud Fleet capacity. TypeScript uses the Fleet SDK, which manages hosted Fleet lifecycle and routing; it is not a TypeScript Sandbox SDK.

Both paths below create the same Fleet resources: a one-replica pool, a VM template, and a server service for computer-server on port 8000. They do not claim a Sandbox.

Prerequisites#

  • Permission to manage pools at run.cua.ai.
  • OAuth client credentials.
  • A globally unique pool name written as a lowercase DNS label.

Set the shared values before continuing:

export CUA_CLIENT_ID="<your-client-id>"
export CUA_CLIENT_SECRET="<your-client-secret>"
export CUA_POOL_NAME="my-team-sandbox-pool"

Set CUA_FLEET_BASE_URL or CUA_TOKEN_URL only when you need different Fleet or OAuth endpoints.

Create the pool#

Install the Python Sandbox SDK in an isolated environment by saving this as create_fleet_capacity.py:

create_fleet_capacity.py
# /// script
# requires-python = ">=3.11,<3.14"
# dependencies = [
#   "cua-sandbox==0.7.0",
# ]
# ///
 
import asyncio
import os
 
from cua_sandbox import Image, Pool
 
 
IMAGE = (
    "public.ecr.aws/k5j5w0x5/cua-ubuntu-24.04"
    "@sha256:c1e601dbb748fdc467c663136f7592e308a91a3c19c309b75261544432826a57"
)
 
 
async def main() -> None:
    pool = await Pool.apply(
        Image.from_registry(IMAGE),
        name=os.environ["CUA_POOL_NAME"],
        replicas=1,
        cpu=4,
        memory_mb=4096,
        services={"server": 8000},
    )
    print(f"Fleet capacity is ready: {pool.name}")
 
 
asyncio.run(main())

Run it with Python 3.11–3.13 and uv:

uv run create_fleet_capacity.py

Pool.apply() derives and reconciles both the pool and its template. Use it only when this script owns their configuration.

What the operation changes#

Reconciliation creates the resources when they do not exist and updates their specifications when they do. The pool keeps one computer warm and continues to consume capacity until it is scaled down or deleted. It does not reserve that computer for a task; continue with Claim a Sandbox.

To consume capacity managed by another process or Terraform, do not reconcile it. Look up the existing pool instead:

pool = await Pool.get(POOL_NAME)

Pool names are globally unique across Cua accounts. A changed claim name does not resolve a pool namespace collision. HTTP 403 can also indicate payment, authorization, or template-policy failures, so inspect the operation and response before choosing a different name.

Delete capacity you own#

Delete a Fleet namespace only after all users have released their claims. Namespace deletion removes the pool, its template, and remaining resources; it is not per-task cleanup for shared capacity. deletePool(pool) removes only the pool resource and is insufficient for whole-Fleet cleanup.

await pool.delete()

If a process stops before cleanup completes, follow Recover interrupted cleanup instead of provisioning again just to obtain a deletion handle.