SDK Usage
Everything the CLI does is available in Python. Import the client and helpers
from the top-level substratecloud package.
The client
from substratecloud import SubstrateCloud
client = SubstrateCloud() # token/base_url from env or config
client = SubstrateCloud(profile="staging") # named profile
The client exposes three resource managers — client.inventory,
client.instances, and client.ssh_keys — plus high-level helpers.
Use it as a context manager so the underlying HTTP connection is always closed:
with SubstrateCloud() as client:
items = client.inventory.list(gpu_type="A100")
Imperative lifecycle
# 1. Find capacity
item = client.inventory.find_cheapest(gpu_type="A100")
# 2. Launch (billing starts here)
instance = client.instances.create(inventory_gpu_id=item.id, name="exp-1")
# 3. Wait until it's ready
client.instances.wait_until_active(instance.id, timeout=600)
# 4. Use it — SSH in via instance.ip_address ...
# 5. Stop billing
client.instances.delete(instance.id)
The SDK methods instances.create() / instances.delete() map to the CLI
verbs substratecloud instance launch / substratecloud instance terminate
(the CLI has no create/delete subcommands).
Useful manager methods:
inventory.list(gpu_type=, location=, gpu_count=, max_price=)inventory.find_cheapest(gpu_type=, location=, min_count=, max_price=)inventory.find_with_fallback([{...}, ...])— try regions in orderinstances.list(),instances.get(id),instances.find_by_name(name),instances.find_by_tag(tag)instances.wait_until_active(id, timeout=)instances.delete(id),instances.delete_many([ids])ssh_keys.list(),ssh_keys.find_by_name(name)
client.run() — find + launch + wait in one call
from substratecloud import SubstrateCloud, DockerWorkload, Secret
client = SubstrateCloud()
wl = DockerWorkload(
image="vllm/vllm-openai:latest",
args=["--model", "mistralai/Mistral-7B-v0.1"],
env={"HF_TOKEN": Secret.from_env("HF_TOKEN")},
ports={8000: 8000},
)
inst = client.run(
workload=wl,
gpu="A100",
name="vllm-mistral",
region_preference=["Stockholm", "US East"],
max_price_per_hour=3.0,
ssh_key="my-laptop", # name or UUID
tags=["team:platform"],
wait=True, # block until active (default)
wait_timeout=600.0,
)
print(f"ssh {inst.ssh_user}@{inst.ip_address} -p {inst.ssh_port}")
Every run() is auto-tagged with actor:<user> and trace:<id> for audit.
Passing budget_limit= adds a budget:N tag — an audit tag only; it does not
auto-terminate the instance. See Cost Safety.
Fluent builder
Each builder call returns a fresh, immutable Launch you can chain and then
plan() / apply():
launch = (
client.gpu("H100", count=1, max_price=4.0, regions=["Stockholm"])
.docker("nginx:latest", ports={80: 80})
)
plan = client.plan(launch) # dry-run
inst = client.apply(launch) # launch
Workloads
Importable from the top-level package:
from substratecloud import DockerWorkload, BootScript, HealthCheck, InferenceServer
Docker
DockerWorkload(
image="vllm/vllm-openai:latest",
args=["--model", "mistralai/Mistral-7B-v0.1"],
env={"HF_TOKEN": Secret.from_env("HF_TOKEN")},
ports={8000: 8000}, # container: host
)
Boot script (preview)
Run shell steps on a bare VM, including cloning a repo at boot:
bs = BootScript(ports=[8080]).git_clone(
"https://github.com/your-org/your-repo.git", dest="/opt/app"
)
For private repos, supply a token via a secret (Secret.from_env("GIT_TOKEN")
in Python, or {from_env: GIT_TOKEN} in YAML) — resolved at submit time.
InferenceServer is a convenience preset for serving models. Runnable recipes
for each workload type live in the SDK repo under
examples/python/.
Secrets
The Secret type is a sentinel. It never appears in repr(), is resolved at
the moment the API request is built, and is redacted from structured logs.
from substratecloud import Secret
Secret.from_env("HF_TOKEN") # read from the environment at submit time
Secret.from_callable(read_hf_token, label="hf") # any callable provider (Vault / AWS SM / GCP SM)
Secret.literal("hf_xxx") # tests/dev only — emits a warning
Declarative manifests
Describe an instance in YAML and manage it with plan / apply / destroy
(CLI) or client.plan() / client.apply() / client.destroy() (SDK).
# minimal-docker.yaml
name: web-1
gpu:
type: A4000
count: 1
workload:
type: docker
image: nginx:latest
ports: { 80: 80 }
lifecycle:
budget_limit_usd: "25" # required unless you pass --no-safety-net
substratecloud plan minimal-docker.yaml
substratecloud apply minimal-docker.yaml
substratecloud destroy web-1
apply is idempotent: it looks for an existing instance tagged with the
manifest name and reuses it, so re-running is safe. Ready-made manifests live in
the SDK repo under
examples/manifests/.