Skip to content

API reference

Auto-generated from colabctl's own docstrings and type hints. For the CLI, run colabctl --help (or colabctl <command> --help); for the MCP server, see Architecture.

Jobs

colabctl.backends.base

Provider abstraction: the batch-Backend contract.

Two complementary abstractions exist in colabctl:

  • :class:~colabctl.transport.base.TransportAdapterinteractive runtimes (allocate a warm GPU, run cells on a live kernel). Colab's native shape.
  • :class:Backend (this module) — batch jobs (submit code → poll → fetch result → cancel). The natural shape for Modal, Vertex, HF Jobs, etc.

The :class:~colabctl.backends.router.BackendRouter selects a backend by capability and fails over between them, so a Colab outage/quota/ban degrades to Modal or Vertex instead of failing. Colab is also exposed as a batch backend (:class:~colabctl.backends.colab.ColabBackend) so callers can use one job API across every provider.

JobSpec

Bases: BaseModel

What to run on a backend. Provide exactly one of code or script_path.

resolved_code
resolved_code()

Return the code to run (reads script_path if that's what was given).

JobInfo

Bases: BaseModel

A lightweight view of a submitted job.

JobResult

Bases: BaseModel

The outcome of a job.

JobState

Bases: StrEnum

BackendCapabilities

Bases: BaseModel

What a backend can do — used for routing and honest disclosure.

Routing & failover

colabctl.backends.router.BackendRouter

Selects among registered backends and fails over on infra errors.

candidates

candidates(spec, *, prefer=None)

Ordered backends that support spec.accelerator (prefer first).

cost_ranked async

cost_ranked(
    spec, *, prefer=None, spot=False, max_price_usd_hr=None
)

Capable backends priced and sorted cheapest-first.

Each candidate is paired with its cheapest price row for spec.accelerator (None if the catalog has no price for it). When max_price_usd_hr is set the ordering is fail-closed: any backend whose rate is above the cap — or that has no price to check against the cap — is dropped, so an empty result means "refuse", never "pick a pricier one". Unpriced backends sort last when no cap is given.

run async

run(
    spec,
    *,
    prefer=None,
    fallback=True,
    cheapest=False,
    spot=False,
    max_price_usd_hr=None,
)

Run spec on the best backend, failing over on infra errors.

With cheapest (or a max_price_usd_hr cap) candidates are ordered cheapest-first and filtered to those at-or-below the cap (fail-closed). Otherwise the fixed capability order applies, prefer first.

Cost engine

colabctl.cost.price

GPU price model + source chain + cheapest-price catalog.

GpuPrice normalizes every backend/feed to a SkyPilot-catalog-shaped row (on-demand + spot $/hr per accelerator), so prices are diffable and joinable. PriceSource is the pluggable feed interface; PriceCatalog is the consumer facade that queries an ordered source chain and always falls back to the in-repo static table — so cheapest-routing and the USD cap always have a number to reason about, even with every live feed down.

The static source provides a zero-network floor. HTTP-backed live sources implement the same ABC, with the static table retained as a fallback.

GpuPrice

Bases: BaseModel

One normalized price row: a backend's on-demand (and optional spot) $/hr.

rate
rate(*, spot=False)

Effective $/hr: the spot price when requested and available, else on-demand.

PriceCatalog

Cheapest-price lookup over an ordered PriceSource chain + a static fallback.

prices async
prices(*, accelerator=None)

Rows from the first source that returns any (then the static fallback).

cheapest async
cheapest(
    accelerator,
    *,
    spot=False,
    backends=None,
    max_usd_hr=None,
)

The lowest-rate eligible row (spot/on-demand), or None if nothing qualifies.

per_backend async
per_backend(accelerator, *, spot=False, backends=None)

The cheapest row per backend for accelerator, sorted by rate — the dry-run view.

PriceSource

Bases: ABC

A pluggable GPU price feed. Implementations are lazy-imported and httpx-only.

prices abstractmethod async
prices(*, accelerator=None)

Return price rows, optionally filtered to one accelerator.

Remote execution (@remote)

colabctl.sdk.remote.remote

remote(
    func=None,
    *,
    gpu="T4",
    transport="cli",
    keep=False,
    client=None,
    timeout=None,
    requirements=None,
    env=None,
    track=None,
    project=None,
    entity=None,
)

Decorator: run the wrapped function on a Colab GPU.

Usable as @remote or @remote(gpu="A100", requirements=["torch"], env={...}). requirements are pip-installed and env injected on the runtime before the call; cloudpickle is pinned to the host's version to avoid the by-value-pickle skew. The returned callable runs synchronously by default; call .aio(...) for the awaitable form.

track="wandb" or "mlflow" turns on experiment tracking: creds are pulled from the secret store and injected as env (never baked into code), the library is installed + autolog enabled on the runtime, the run is tagged with a job id, and the run id/URL is captured into the audit ledger (colabctl audit). project/entity set W&B's.

Experiment tracking

colabctl.tracking

Experiment-tracking integration for Weights & Biases and MLflow.

Opt-in via track="wandb"|"mlflow" on @remote / a detached job. The design is pure environment injection — colabctl never imports wandb/mlflow itself; credentials come from the secret store and travel only as environment variables (never baked into pickled code), and the tracking library is installed + imported on the runtime. Two-way lineage:

  • outbound — the run is tagged with COLABCTL_JOB_ID (via env vars the library honours at init: WANDB_RUN_GROUP/WANDB_TAGS for W&B, extra_tags for MLflow), so you can find the run from the job id.
  • inbound — the on-runtime preamble prints a framed lineage line (run id + URL) that the client parses and records into the append-only audit ledger, so you can find the job from the run (durable — unlike anonymous/offline W&B runs which expire).

Verified against the 2026 docs: W&B env vars override wandb.init() kwargs (our injection wins); the legacy wandb.integration.*.autolog LLM helpers were removed, so the durable one-liner is wandb.init(sync_tensorboard=True); MLflow has no URL builder, so it's hand-built from the tracking URI; for MLflow, basic-auth (user+pass) overrides the token.

resolve_tracking_env

resolve_tracking_env(
    track, job_id, *, secret_get, project=None, entity=None
)

Env vars to inject for track, with creds pulled from the secret store.

secret_get(account) returns the secret or None. Returns {} for an unknown/absent tracker. Fail-open: if no credential is found, W&B gets WANDB_MODE=disabled so the shipped function still runs end to end instead of blocking on a login prompt (MLflow has no disabled mode — it would fall back to an ephemeral local store, which the caller should warn about). Outbound lineage (group/tags) is injected as env so the shipped code needs no edit.

requirements_for

requirements_for(track)

The pip requirement to add so the runtime can import the tracker.

Errors

colabctl.errors.ColabctlError

Bases: Exception

Base class for every error raised by colabctl.

Subclasses set :attr:code (a stable SCREAMING_SNAKE identifier), :attr:category (the system layer), and optionally :attr:remediation (a one-line fix hint).

to_dict

to_dict()

A machine-readable view: {error, code, category, message[, remediation, ...]}.

Subclasses with extra context (argv, exit code, accelerator, traceback) extend this.