Container image and command

image chooses the container environment where your code runs. A container image packages the runtime, system libraries, and installed dependencies. For example, pytorch/pytorch:2.8.0-cuda12.8-cudnn9-runtime selects an environment with PyTorch and CUDA libraries. Choose an image containing the packages your program needs.

command tells that environment which program to start and which arguments to pass. In command=["python", "train.py"], the first item starts Python and the second names the script. This list is also called an argument vector, or argv. The script must already be in the image or attached as uploaded code. Naming a local file in command does not upload it.

To attach your code, upload it with client.assets.upload() and pass the returned asset ID as source_asset_id. Nodus extracts that code into the workload working directory. See run your own Python script for a complete upload-and-run example.

In the HTTP API, source groups the image, command, and optional code asset. Python callers pass image, command, and source_asset_id directly to client.run(). The SDK builds the source object for you.

Argument Type Default / omission Workload file
image str python:3.11-slim for a single source image
command list[str] or str No command is sent command
framework "train_eval" Absent framework = "train_eval"

For a single-source SDK call, omitting image or passing an empty string selects python:3.11-slim. It does not request the native runtime available when leaving the console image field blank. For GPU workloads, pass a compatible CUDA image with the dependencies your code needs.

Use an explicit image and command. Omitting the command is accepted by this SDK, but is not a portable way to invoke an image entrypoint: deployment bootstrap controls execution. It is unsuitable for a first workload.

Inside a with nodus.Client() as client: block:

Python
workload = client.run(
    image="pytorch/pytorch:2.8.0-cuda12.8-cudnn9-runtime",
    command=["python", "-c", "print('ready')"],
    budget=5,
)

A string command uses shlex.split. It does not invoke a shell. Prefer an argv list. Pipes, redirects, variable expansion, and && need an explicit shell, such as command=["sh", "-c", "python preprocess.py && python train.py"].

Images must contain a bootstrap fetch tool (curl, wget, or python3), plus your program dependencies. Upload source files explicitly with client.assets.upload(). framework is passed through to the control plane. It does not install a framework or replace the need to prepare runnable code. The current compiler supports train_eval: it runs the same command in prepare, train, and eval stages. Code must branch on NODUS_STAGE_ID and honor the declared handoffs. Prefer explicit stages when each command differs. Do not combine framework with stages, because framework expansion takes precedence.

When stages is nonempty, its stage sources replace the top-level source. Combining it with nonempty image, command, or source_asset_id raises TypeError.

Input and output files

Argument Purpose
source_asset_id Uploaded/imported code asset extracted into the working directory
inputs Named asset inputs such as [{"name": "training", "asset_id": "ASSET_ID"}]
outputs Declared files such as {"model": "model.bin"} relative to the working directory

outputs creates a single stage named main. Do not combine it with stages or framework. Put source.asset_id on each explicit stage instead of using source_asset_id. Top-level asset inputs can also supply staged workloads. See code and datasets for asset creation and input paths, and logs and results for downloads.

File declaration constraints

Use asset IDs returned by upload or import, not paths or URLs. Their format is asset_ followed by 1 to 64 letters, digits, or hyphens. Omitted source_asset_id attaches no code asset. Omitted inputs attaches no named assets.

inputs accepts at most eight dictionaries, each containing name and asset_id, with an optional boolean cache flag. Names must be unique, start with a letter, and contain at most 64 letters, digits, or underscores. For example, training_data is valid and training-data is not. The input directory is exposed as NODUS_INPUT_training_data.

Set cache: True to allow reuse of verified input content within your team and execution region. Cache storage uses workspace size and count limits. The first workload that fills a cache remains its storage billing owner, including after termination, under its existing spending cap. Storage billing stays disabled until a storage rate is configured. An unavailable cache falls back to the ordinary input. This flag does not stream external bucket data.

Output names use only letters, digits, dots, underscores, or hyphens. They must be distinct without regard to case, cannot be . or .., and cannot end in a dot. Reserved file names CON, PRN, AUX, NUL, COM1 through COM9, and LPT1 through LPT9 are rejected without regard to case, including names with extensions such as CON.txt. Stage IDs with declared outputs follow these same portability rules in addition to the stage ID rules.

Output paths identify files inside the workload working directory. Use / for subdirectories, such as results/model.bin. Absolute paths, backslashes, colons, control characters, empty path components, and . or .. components are rejected. When a stage has no declared outputs, non-empty outputs/ and results/ folders are automatically preserved as outputs.tar and results.tar. Explicit output mappings replace this default. Save complete model bundles in a default folder, or declare files elsewhere. See logs and results for collection exclusions and downloads.

Stream a bucket object

A bucket input supplies a sequential file path through NODUS_INPUT_<name>. The runner reads directly from the declared regional S3 or Google Cloud Storage endpoint while your command consumes the file. It does not import the corpus into Nodus storage. Read through EOF to verify the declared byte count and SHA-256 digest. Seeking and reopening the stream are not supported. The example descriptor below represents an object containing the three bytes abc. Replace its location, byte count and digest with your own object metadata.

Python
job = client.run(
    command=["python", "train.py"],
    budget=2,
    data_regions=["us-east-1"],
    inputs=[{
        "name": "corpus",
        "bucket": {
            "uri": "s3://training-bucket/corpus.jsonl",
            "region": "us-east-1",
            "bytes": 3,
            "sha256": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
            "credential_source": "team_webhook",
        },
    }],
)

Use gs://bucket/object and the exact Google Cloud region for GCS. The execution region must exactly match the input region. Do not put signed URLs, access keys, or tokens in the workload definition. Bucket inputs do not accept cache. Imported assets and OCI image layers use the separate optional digest cache.

A team administrator must configure the existing team webhook to handle a synchronous input.credentials.request. Nodus signs this request using the webhook timestamp and HMAC headers. The request identifies the workload, stage, generation, input name and object descriptor. Return HTTP 200 with the same object and a credentials object containing expires_at and either S3 access_key_id, secret_access_key, session_token, or GCS access_token. Scope the temporary credential to reading the declared object and set its expiry within one hour. Never log the response body.

Nodus keeps the credential only in memory and transfers it to the authenticated runner over TLS. A failed, expired, unread or corrupt stream prevents successful completion. Recovery requests a fresh credential and starts the stream from the beginning. Your program remains responsible for loading its own saved progress and skipping data already processed. Data received before EOF is not yet fully verified against the declared digest.

Database result sinks

An output value can be a path string or a dictionary containing path and sink, where sink contains connection and table. String paths retain their existing behavior. Database sinks support CSV, JSONL and flat Parquet files. See database result loading for types, limits, generation replacement and reload.