DocumentationPython client reference

Python client reference

Client(api_key=None, base_url=None, timeout=30.0, max_retries=2) pools HTTP connections. With no arguments it uses your saved login and the hosted service. Prefer a with block. Otherwise call close(). AsyncClient uses async with or await aclose() and mirrors the methods below.

Method Result / behavior
run(**brief) Accepted Workload. all parameters
run_file(path="nodus.toml") Accepted Workload from a workload file
assets Upload, import, list, and delete code or dataset assets
operations Typed version 1 workload and draft operations with contract discovery
pools Measure customer-owned GPU hosts, review forecasts, and configure Route
sandboxes Create, reconnect to, list, and control agent sandboxes
get(id) Refreshed Workload
list(limit=50, offset=0, status=None, scope=None) One page of workloads
list_page(limit=50, offset=0, status=None, scope=None) (workloads, next_offset)
iter_workloads(page_size=50, status=None, scope=None) Iterator over offset-based pages
wait(id, poll_seconds=2.0, timeout_seconds=None, progress=None, on_update=None) Terminal workload. Inspect succeeded
cancel(id, idempotency_key=None) Request cancellation. Returns None
events(id, after=0) One page of Event objects
iter_events(id, after=0) Iterator over event history
stream_events(id, poll_seconds=2.0) Poll events until terminal
artifacts(id) List of Artifact manifests
logs(id, stage=None, generation=None) Committed log text
live_logs(id, after="") Live log chunks, cursor, and truncation state
outputs(id) List of Output objects
download_output(id, name, destination, stage=None, overwrite=True) Verified local Path
routing(id) Placement-history dictionaries ordered by stage ID and generation
ledger(id) Ledger
set_webhook(url, secret=None) Webhook configuration response dictionary
get_webhook() / delete_webhook() Read configuration / remove it
healthz() / readyz() Deployment health/readiness dictionaries

Optional settings after resource IDs are keyword-only. For download_output, name and destination can also be positional. Status filters accept nodus.WorkloadStatus members, strings, comma-separated strings, or lists. Accepted status strings are accepted, planning, reserving, provisioning, running, recovering, completed, failed, and cancelled. The active preset selects nonterminal states and terminal selects completed, failed, and cancelled. Omit status for no status filter. Unknown statuses raise ValueError. Pagination uses offsets. Concurrent new submissions can shift pages. It is not a consistent historical snapshot.

Sandbox resources

nodus.Sandbox(name=..., image=...) is the direct get-or-create form. Reusing the same name reattaches without an image. It is a context manager that terminates on exit. Call close() to release only the local HTTP client while keeping the remote sandbox alive.

client.sandboxes.create(...) accepts an image, resource requirements, a budget, network policy, lifecycle, reservation, and continuity settings. It returns an accepted Sandbox handle. Read sandbox.state or call sandbox.refresh() before assuming the environment is ready.

client.sandboxes.from_id(ID) reconnects to a sandbox. list() returns one cursor-based page and list_page() also returns next_cursor. Iterating over client.sandboxes follows every page. The asynchronous client provides the same methods and client.sandboxes.iterate().

sandbox.exec(command, ...) accepts shell command text or an argument vector, queues a process, and returns SandboxExec. execution.iter_output() yields ordered SandboxOutputFrame objects with stream, data, and decoded text. execution.write(data, eof=False) sends stdin when it was enabled at execution creation. execution.wait() returns when the process is terminal. Check succeeded and exit_code. Call sandbox.terminate() to stop future execution and request resource cleanup.

Sandbox calls use idempotency keys for create, exec, stdin, and terminate. Supply a stable key when your application retries after an uncertain response. Generated keys protect the SDK transport retries within one method call. If create, exec, or terminate returns an invalid receipt, the SDK raises APIError with the sent key in error.payload["idempotency_key"]. Reuse that key with the original arguments to recover the same operation.

Workload offers refresh, wait, cancel, events, logs, artifacts, outputs, download, routing, and ledger methods without repeating the ID. Reads and waits with refresh() and wait() update it in place. Useful attributes are id, status, succeeded, is_terminal, route, stages, meter, cost_now_usd, links, and raw. Each WorkloadLink has kind and url. Captured wandb links are available before completion. Unknown server enum values remain strings for forward compatibility.

workload.download(destination=None) downloads all published customer outputs, including automatically collected folder archives when no files were declared, and returns a list of local Path objects. The default directory is outputs/WORKLOAD_ID, with each file at STAGE/NAME. await workload.download() is the asynchronous equivalent. Use download_output(name, destination, stage=...) for one specific file.

Method arguments

Argument Meaning and default
timeout HTTP request timeout in seconds, default 30.0. Separate from a workload deadline or wait timeout. Retry behavior
max_retries Additional request attempts, default 2, giving up to three total attempts. Downloads do not retry automatically
limit, page_size Workloads requested per page, default 50
offset Number of workloads to skip, default 0. list_page() returns the next offset, or None at the end
poll_seconds Finite nonnegative seconds between successful polls, default 2.0
timeout_seconds Finite nonnegative local wait duration in seconds, default None for no deadline. A timeout leaves the workload running
on_update Optional synchronous callback called with each successful workload read during wait(), including the terminal read. Available on sync and async clients
progress None detects an interactive terminal, True enables output, False waits silently. Live display
events(after), iter_events(after) Numeric sequence of the last event seen, default 0. Returns events with later seq values, oldest first. events() returns at most 100 per page
live_logs(after) Opaque next_cursor string from the previous response, default "" for the first page. This is not an event sequence. Live log response
logs(stage) Stage ID to select, default None for no stage filter
logs(generation) Stage attempt number to select, default None for no generation filter. Use a positive generation from the returned artifacts or live logs
download_output(name) Declared output name, not its path in the container
download_output(destination) Local file path with an existing parent directory
download_output(stage) Stage ID to disambiguate an output name published by multiple stages, default None
download_output(overwrite) True replaces the destination only after integrity verification. False refuses an existing target
idempotency_key Stable key for a logical submission or cancellation. Omission creates a fresh key per call. Character rules and retries
scope "mine" or "team". Omission sends no scope filter. Personal and team history

For all declared files, workload.download() creates directories and refuses to overwrite existing files. Use a new destination directory for another copy.

Models

Type Useful fields
Event seq, id, type, payload, created_at
StageRun id, status, completed_units, total_units, optional last_loss, metric_rate, metric_step, metric_total_steps, metric_epoch, metric_total_epochs
Artifact manifest_id, stage_id, generation, sequence, final, files, outputs
ManifestFile uri, sha256, bytes, media, is_tar
Output name, stage_id, sha256, bytes, download
Route sku, compute_class, fit_class, region, memory_gb, resources, prices and estimated cost
Meter settled_usd, accruing_usd, total_now_usd, accruing_rate_usd_hour, as_of, compute_settled_usd, platform_fee_settled_usd, subscription_settled_usd, compute_accruing_usd, platform_fee_accruing_usd
Ledger entries, charged_usd, settlement

Event has type and payload, not a message attribute. Output download helpers use the authenticated API endpoint. Treat returned download as server metadata rather than a URL to which you should forward credentials.

Route.sku is a catalog identifier, not a GPU model. When available, route.resources.get("accelerator") reports the device model and route.resources.get("device_memory_gb") reports its memory in GB. Missing metadata does not prove that no GPU was used. The terminal shows Not reported when it cannot identify the compute from the response. List responses may omit the route, so use client.get(ID) or workload.refresh() for current details.

Optional typed request dictionaries

Source, Requirements, Policy, ContinuitySpec, StageInput, and StageSpec are TypedDict helpers exported by nodus. They support autocomplete and static analysis while producing ordinary dictionaries:

Python
import nodus

requirements = nodus.Requirements(compute_class="accelerator", peak_memory_gb=24)
source = nodus.Source(image="pytorch/pytorch:2.8.0-cuda12.8-cudnn9-runtime", command=["python", "-c", "print(1)"])
stage = nodus.StageSpec(id="example", source=source)
# Supply requirements= and stages=[stage] to client.run(..., budget=5).

They do not add runtime validation or defaults. Existing plain dictionaries remain supported. Stage source commands are argv lists, not shell strings.

Personal and team history

Use client.list(scope="mine") for your submissions or scope="team" for the team. Scope also works with list_page() and iter_workloads() and combines with status filters. Personal history requires a member-associated credential. Listed workloads expose owner_user_id, which can be absent for shared keys or older submissions. Scope filters history and does not change team access.