Jobs
A Job is a finite container workload. Use one for training, batch inference, evaluation, data processing, builds, and any other task that should exit when its work is complete. Anycloud provisions a VM, runs one container, records the result, and tears the VM down unless you ask it to persist.
Use a Server instead when the process should stay online and receive HTTP traffic.
Submit a job
- CLI
- Python
anycloud submit ghcr.io/acme/train:latest \
--credentials my-aws \
--gpu-type h100:8 \
--spot \
--gpus all \
-- python train.py
import anycloud
from anycloud.types import CloudConfig
ac = anycloud.Client()
job = ac.submit(
"ghcr.io/acme/train:latest",
gpu="h100:8",
command=["python", "train.py"],
cloud_config=CloudConfig(credentials="my-aws", spot=True),
)
job.wait()
Choose hardware by GPU name when the accelerator matters, or by exact VM type
when the instance shape matters. See GPUs & VM Types
for that decision and submit reference for every
option.
Choose how code reaches the VM
Submit a prebuilt image
Build the application and its dependencies into an image when you want a hermetic artifact, have a non-Python workload, or deploy from CI:
anycloud submit ghcr.io/acme/trainer:sha-4d82f7a --gpu-type h100:8
Anycloud resolves the image to a registry digest before pulling it, so a mutable tag always resolves to the content available for that deployment.
Sync Python code from Git
Use @anycloud.function() when dependencies change slowly but Python code
changes often. The image supplies the runtime; Anycloud clones the submitted
Git commit into the container before calling the function:
import anycloud
@anycloud.function(
image="pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime",
gpu="h100:8",
)
def train(learning_rate: float, epochs: int = 100):
...
job = train.submit(0.001, epochs=50)
The repository and commit must be pushed, and the image must contain git.
Private repositories use the GitHub authentication established by
anycloud login. See Container Images for image
build and registry guidance.
Lifecycle
queuedprovisioninginitializingdownloadingsyncingif usedstartingrunningfinalizingif usedcompletederroredretrying⏳ queuedrecovering⏳ queuedfailedRequired retries exhaustedinvalidConfiguration rejectedterminatedStopped by a userInfrastructure setup failures are retried on a fresh VM, up to 100 setup attempts. Invalid configuration is not retried. A local API can have 50 deployments in the setup pipeline at once; that cap does not limit the number already running.
Use status to see the current phase and its events:
anycloud status <job-id> --watch
anycloud status <job-id> --verbose
Data and artifacts
Attach object storage when the job needs datasets, durable results, or recoverable state:
| Container path | Access | Behavior |
|---|---|---|
/mnt/input | Read-only | Downloaded before the container starts |
/mnt/output | Read-write | Uploaded about every 60 seconds and at exit |
/mnt/checkpoint | Read-write | Restored and uploaded for spot recovery |
See Buckets for configuration and sync behavior.
Spot recovery
Spot capacity costs less but may be reclaimed at any point. With --spot,
Anycloud detects preemption, cleans up the lost VM, provisions a replacement,
restores /mnt/checkpoint, and restarts the container.
from pathlib import Path
import json
checkpoint = Path("/mnt/checkpoint/state.json")
start_epoch = json.loads(checkpoint.read_text())["epoch"] if checkpoint.exists() else 0
for epoch in range(start_epoch, 100):
train_one_epoch(epoch)
checkpoint.write_text(json.dumps({"epoch": epoch + 1}))
Checkpoint changes sync about every 60 seconds, so checkpoint often and make
startup idempotent. The automatic checkpoint bucket is deleted with a
completed spot job unless --persist-bucket is set.
Compose jobs
Wait for dependent steps and use a bucket to pass durable data:
prep = ac.submit("ghcr.io/acme/prep:latest", output=ac.bucket("prepared"))
prep.wait()
train = ac.submit(
"ghcr.io/acme/train:latest",
gpu="h100:8",
input=ac.bucket("prepared"),
output=ac.bucket("models"),
)
train.wait()
For parallel work, use submit_many(), Function.map(), and JobGroup. See
Python SDK: JobGroup for fan-out and fan-in
patterns.
Operate and debug
anycloud list --status running
anycloud logs <job-id>
anycloud exec <job-id> "nvidia-smi"
anycloud terminate <job-id>
anycloud resubmit <job-id>
exec and live logs require the job execution environment to still exist.
When an output bucket is attached, logs are also copied under
.anycloud/logs/, preserving them after teardown. Exact lifecycle and
operation syntax is in Deployment commands.
Agent-operated jobs
The CLI supports coding agents that submit and monitor Jobs directly. Commands that print tables also provide structured output, and non-interactive deployments from Claude Code, Codex, Cursor, and Aider are tagged with the detected agent and session.
anycloud list --agent codex --json
anycloud list --session <session-id> --only-ids
anycloud status <job-id> --json
anycloud cost --agent codex --json
When an agent invokes list or cost, results default to that agent's own
session. This is cooperative scoping for usability, not an access boundary; an
explicit --session or --agent can select another scope.
Use anycloud docs for the documentation index and anycloud docs --all for
the full Markdown corpus. Pair autonomous sessions with
per-session Spend Controls.