Skip to main content
The NIKA Python SDK lets you mark a Python function as cloud-runnable, keep the normal local call path for debugging, and explicitly submit the same function to NIKA-managed compute when you need isolated execution.
For now, code cloud delegation is designed to run from NIKA cloud notebooks. Local terminals and external notebooks can still import the SDK for development, but remote submission is not a supported workflow outside NIKA notebooks yet.

Prerequisites

  • A cloud NIKA notebook with a running machine
  • Access to the workspace or project where the delegated run should execute
  • Python code that can be serialized or imported by the remote worker
  • Any third-party packages declared in requirements
  • Inputs and outputs passed as serializable values, workspace file paths, dataset IDs, or other managed references
The SDK package is named nika_py and exposes the Python module nika_py. The public SDK surface uses run and run-configuration APIs.

Available SDK Functions

Use these entrypoints from nika_py:

Step 1: Decorate a Function

Use @run to define the compute target, timeouts, and dependency requirements for the remote invocation. Calling the function normally still runs it in the current notebook kernel.
Use direct execution first when you are still checking the logic:
build_buffer_summary(...) and build_buffer_summary.local(...) both run in the notebook kernel. Nothing is submitted to cloud delegation until you call .submit(...).

Step 2: Submit to Cloud Compute

Call .submit(...) to serialize the invocation and send it to the NIKA cloud runner available from the notebook.
You can also choose to fan out multiple runs with custom names.
The returned RunHandle is a lightweight reference to the remote run. It can poll status, fetch logs, wait for a result, or request cancellation.
If you call run.result() while the run is still pending, initializing, running, or cancelling, the SDK raises RunNotCompleteError. Use run.wait(...) when the notebook should block until the result is ready. The timeout argument on run.wait(...) is in seconds and only controls how long the notebook blocks — it never affects the run itself. The run_timeout_hours and queue_timeout_hours options on @run(...) are in hours and bound the run.

Step 3: Choose Compute and Runtime Options

The decorator currently accepts these options: The remote platform may reject compute types that are not enabled for your workspace. Start with the smallest machine that matches the memory or GPU profile of the task, then scale up only when the logs or runtime behavior show that the run needs it. Per-run configuration is passed to .submit(...) with RunConfig: Run names are optional, can be up to 63 characters, and must match ^[a-zA-Z0-9]([-a-zA-Z0-9_.]*[a-zA-Z0-9])?$. Use them for stable labels such as site-buffer-summary, nightly-index, or experiment-1. Because .submit(..., config=RunConfig(...)) reserves the config keyword for SDK configuration, a function decorated with @run cannot define a parameter named config.

Step 4: Reconnect to Existing Runs

Use load_run(...) when you already have a run ID from a previous cell, browser refresh, or shared notebook note.
If you are working from the decorated function object, use .load(...) to reuse the same client configuration:
Use list_runs(...) to retrieve one page of runs visible from the notebook. The returned RunPage contains runs and next_cursor.
Allowed status filters are pending, initializing, running, cancelling, succeeded, failed, and cancelled. The name filter is an exact match on the run name, limit must be between 1 and 200, and cursor should only be set from a previous page’s next_cursor. You can also filter child runs client-side with parent_run_id:

Step 5: Track Child Runs

When code inside a delegated run submits more work, the SDK can link the nested submission back to the run that started it. Notebook submissions do not set a parent and remain root runs. Every returned RunHandle exposes parent_run_id, which is None for root runs. Handles returned from load_run(...) and list_runs(...) also carry snapshot metadata when the gateway provides it, including name, machine_type, run_timeout_hours, queue_timeout_hours, last_status, created_at, started_at, and finished_at. list_runs(parent_run_id=...) retrieves one page of recent runs and filters that page locally. You can use handle helpers when you are navigating a run tree:

Step 6: Cancel a Running Run

If a delegated run is no longer needed, call cancel() on its handle.
Cancellation is asynchronous. Calling run.cancel() sends the cancellation request immediately and returns a RunCancellation object. The object exposes last_status and done; when awaited, it polls until the backend reports cancelled. If the run reaches succeeded or failed before cancellation completes, awaiting the cancellation raises RemoteRunError.

How Delegation Works

When you call .submit(...), the SDK builds an invocation envelope and submits it to NIKA cloud compute:
  1. The decorated function is converted into a function bundle.
  2. Positional and keyword arguments are serialized with cloudpickle.
  3. Runtime options are attached as compute and run_timeout_hours (always sent, 1 when you don’t set it), plus optional queue_timeout_hours, optional requirements, and optional per-run name from RunConfig.
  4. If the submitting process is already inside a delegated run, the SDK includes parent-run metadata.
  5. NIKA returns run_id, and the remote runner starts an isolated worker, executes the function, stores logs, and makes the result available to the handle. New runs use the nr--... run ID format, while older nr-<32 hex> IDs remain valid for loading, status checks, logs, results, cancellation, and parent-run metadata.
The status lifecycle is pendinginitializingrunning, then one of succeeded, failed, or cancelled. A short-lived cancelling status appears after run.cancel() while the operator tears down the worker. Unknown future statuses are treated defensively as running by the SDK. When a result is ready, the runner can return either an inline pickled result payload or a result_url. For large or stored results, the SDK fetches the signed result_url, decodes the cloudpickle bytes, and returns the Python object from run.result() or run.wait(...). The SDK uses two bundling strategies: Most cloud notebook usage will use cloudpickle because functions are usually defined in notebook cells. Keep those functions focused: pass large datasets by path or ID, not by capturing a large dataframe in a closure.

Serialization Guidelines

Delegated functions should have clear boundaries. The SDK can serialize ordinary Python values, but remote execution is more reliable when the function receives references to data instead of live objects from the notebook session. Prefer:
  • Strings, numbers, booleans, lists, dictionaries, and dataclasses
  • Workspace file paths such as /workspace/data/input.geojson
  • Dataset IDs, table names, object storage URLs, or other managed references
  • Return values that are small enough to serialize comfortably
  • Output files written to explicit workspace paths
Avoid capturing:
  • Open file handles
  • Database connections
  • Sockets or clients with active network state
  • GPU tensors or model objects already loaded in notebook memory
  • Large pandas or GeoPandas dataframes in closure variables
  • Secrets embedded in source code or closures
If a result is large, write it to a workspace file and return metadata:

Troubleshooting

AuthenticationError or ConfigurationError

The SDK cannot use the notebook’s cloud delegation context. Make sure the code is running inside a cloud NIKA notebook. Local Python processes are not a supported delegation environment at the moment.

RunNotCompleteError

The run has not reached a terminal state yet. Check run.status() and run.logs(tail=200), or use:

Remote Dependency Errors

Add the missing package to requirements and pin versions when reproducibility matters.

Cloudpickle Runtime Mismatch

Notebook-defined functions are serialized as Python code objects. If the worker uses a different Python minor version than the notebook kernel, unpickling can fail. Use the cloud notebook runtime selected by NIKA, keep functions simple, or move production code into an importable module so the SDK can use module_ref.

Best Practices

  • Test the function locally in the notebook with .local(...) before submitting.
  • Keep delegated functions deterministic: pass every input explicitly and write outputs to known paths.
  • Pin critical dependencies in requirements.
  • Use logs(tail=...) for progress reporting instead of returning large debug payloads.
  • Return compact metadata and store large outputs as files.
  • Use load_run(...) to reconnect instead of re-submitting the same expensive run.
  • Treat notebook cloudpickle delegation as an exploratory workflow; move stable production routines into importable modules when they need stronger reproducibility.
  • Do not place credentials, private endpoints, or long-lived secrets in function closures. Pass secret references or managed paths instead.

Next Steps

Now that you can delegate Python functions to cloud compute:
  1. Learn how to run code in NIKA notebooks
  2. Review supported Python libraries
  3. Use custom geoprocess deployment when you need a versioned worker available from GIS tools