Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/build-nemo-platform-wheel/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ inputs:
required: false
default: "19700101000000"
python-version:
description: Python version for setup-uv.
description: Python version for setup-uv. Must be within the wheel's supported range.
required: false
default: "3.11"
default: "3.12"
source-root:
description: >
Path to the checked-out repository. release-bundle.yaml uses `source`;
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ Quick install from PyPI:
```bash
curl -LsSf https://astral.sh/uv/0.9.30/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv venv --python 3.13
source .venv/bin/activate
uv pip install nemo-platform
uv tool install "nemo-platform[all]"

nemo setup
```

`uv tool install` gives you a global `nemo` command in its own isolated environment, with nothing to activate. The `all` extra adds the platform services, so `nemo services run` works; without it you get the SDK and CLI only. To import the SDK from your own code, `pip install "nemo-platform[all]"` into a virtual environment instead.

Source checkout for development:

```bash
Expand Down
4 changes: 3 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ is unavailable, start Docker and retry—do not proceed to `rm -rf`.

## Bootstrap and start

The README documents the streamlined path. Prefer this over the manual steps below whenever the task fits — it covers prerequisites install, service startup, provider registration, default/fast model selection, and demo agent deployment in one shot:
This section is the **source checkout** path: use it to work on NeMo Platform itself, on a local plugin, or on Studio assets. To only *use* the platform, install the published wheel instead — `uv tool install "nemo-platform[all]"` needs no checkout and no toolchain, then continue at `nemo setup`.

The steps below cover prerequisites install, service startup, provider registration, default/fast model selection, and demo agent deployment in one shot. Prefer them over the manual sections further down whenever the task fits:

Before running `make bootstrap`, install Flox from the [Flox installation guide](https://flox.dev/docs/install-flox/install). Flox is the recommended source-development toolchain and does not need to be activated first. Contributors using a preinstalled host toolchain instead need uv `>=0.9.14`, Node.js `22.23.2`, pnpm `10.34.5`, and a C compiler; they must use `make TOOLCHAIN=system bootstrap`.

Expand Down
26 changes: 17 additions & 9 deletions docs/cli/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,33 @@ If you previously installed the `nemo-microservices` package, uninstall it first
pip uninstall nemo-microservices
```

### Install in a Virtual Environment
### Install

Install the PyPI `nemo-platform` wrapper package in a Python 3.12-3.13 virtual environment. If you are working from a source checkout, run `make bootstrap` from the repository root instead; the generated SDK package under `sdk/python/nemo-platform/pyproject.toml` does not define the wrapper extras.
Install the PyPI `nemo-platform` wrapper package. From a source checkout, run `make bootstrap` from the repository root instead; the generated SDK package under `sdk/python/nemo-platform/pyproject.toml` does not define the wrapper extras.

<Tabs>

<Tab title="uv tool (recommended)">

One command, `nemo` available everywhere, nothing to activate.

```bash
pip install "nemo-platform[all]"
uv tool install "nemo-platform[all]"
```

Or with uv:
</Tab>

<Tab title="Virtual environment">

Use when you also import the SDK from your own code. `nemo` works only while the environment is active.

```bash
uv pip install "nemo-platform[all]"
pip install "nemo-platform[all]"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we just prefer the uv way, tool or not?

```

<Warning>

When installed in a virtual environment, the `nemo` command is only available when the environment is activated.
</Tab>

</Warning>
</Tabs>

### Verify Installation

Expand Down
19 changes: 19 additions & 0 deletions docs/cli/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ Activate the virtual environment where you installed the package:
source /path/to/venv/bin/activate
```

## Installation Issues

### Install Fails Building a Dependency

**Symptoms:**
- `uv tool install "nemo-platform[all]"` fails while building a dependency, often on a missing C header such as `omp.h`

**Cause:**

NeMo Platform supports Python 3.12 and 3.13, but uv [picks the interpreter itself](https://docs.astral.sh/uv/concepts/tools/#python-versions), so an install can land on Python 3.14.

**Solution:**

Name a supported interpreter. uv downloads one if you do not have it:

```bash
uv tool install --python 3.13 "nemo-platform[all]"
```

## Connection Issues

### Unable to Connect to Server
Expand Down
28 changes: 21 additions & 7 deletions docs/get-started/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Install NeMo Platform and start working with AI agents.
- Python 3.12-3.13
- An API key from one of: [NVIDIA Build](https://build.nvidia.com), [OpenAI](https://platform.openai.com/api-keys), [Anthropic](https://console.anthropic.com/settings/keys), [Google Gemini](https://aistudio.google.com/apikey), or a local [Ollama](https://ollama.com) instance (no key needed)
- 16 GB available disk space and 8 GB RAM
- For the PyPI install: `pip` in a Python environment
- For the PyPI install: [uv](https://docs.astral.sh/uv/) `>=0.9.14`, or `pip` in a Python environment
- For the source checkout install: [Git](https://git-scm.com/), GNU Make, [uv](https://docs.astral.sh/uv/) `>=0.9.14`, [Node.js (≥22.23.2, \<23)](https://nodejs.org/en/download) satisfying `web/package.json`, and [pnpm](https://pnpm.io/installation)

## Install
Expand All @@ -21,21 +21,35 @@ Choose the install path that matches what you want to do.

### Install from PyPI

Use the [PyPI package](https://pypi.org/project/nemo-platform/) for the quickest local install. The `all` extra includes the SDK, CLI, platform services, and default first-party plugins:
Use the [PyPI package](https://pypi.org/project/nemo-platform/) for the quickest local install. The `all` extra includes the SDK, CLI, platform services, and default first-party plugins; drop it for the SDK and CLI alone.

<Tabs>

<Tab title="uv tool (recommended)">

One command, `nemo` available everywhere, nothing to activate.

```bash
uv tool install "nemo-platform[all]"
```
Comment on lines +33 to +34

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- docs/get-started/setup.mdx ---'
cat -n docs/get-started/setup.mdx | sed -n '1,80p'
printf '%s\n' '--- packages/nemo_platform/README.md ---'
cat -n packages/nemo_platform/README.md | sed -n '1,60p'
printf '%s\n' '--- uv tool references ---'
rg -n -i 'uv tool|PATH|shell reload|nemo-platform\[all\]' docs packages/nemo_platform README.md 2>/dev/null || true

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 50384


🏁 Script executed:

#!/bin/bash
set -u
printf '%s\n' '--- cited documentation ranges ---'
sed -n '25,42p' docs/get-started/setup.mdx
printf '%s\n' '--- cited README range ---'
sed -n '20,36p' packages/nemo_platform/README.md
printf '%s\n' '--- uv availability and relevant help ---'
if command -v uv >/dev/null 2>&1; then
  uv --version
  uv tool --help | sed -n '1,160p'
  printf '%s\n' '--- uv tool dir --bin ---'
  uv tool dir --bin
else
  printf '%s\n' 'uv is not installed in the sandbox'
fi

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 1358


🌐 Web query:

site:docs.astral.sh/uv uv tool install PATH shell restart executable directory

💡 Result:

When you install a tool using uv tool install, the tool's executables are placed in a specific executable directory (bin directory) [1][2][3]. For these tools to be accessible directly from your shell, this directory must be included in your system's PATH environment variable [1][4]. If the directory is not already in your PATH, uv will display a warning upon installation [1][2]. To resolve this, you can run the following command to automatically add the executable directory to your shell's configuration files: uv tool update-shell [1][5] After running this command, you will typically need to restart your shell session (or source your configuration file, e.g., source ~/.bashrc or source ~/.zshrc) for the changes to take effect and for the new PATH to be recognized [1][4]. You can locate the tool executable directory on your system by running: uv tool dir --bin [3] This ensures that the symlinks or copies of the tool's executables are correctly referenced by your shell [1][4].

Citations:


Document uv PATH setup

If the uv tool executable directory is not on PATH, nemo is not immediately available. In both files, replace “available everywhere” with guidance to run uv tool update-shell, then restart the shell or source its configuration.

📍 Affects 2 files
  • docs/get-started/setup.mdx#L33-L34 (this comment)
  • packages/nemo_platform/README.md#L26-L30
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/get-started/setup.mdx` around lines 33 - 34, Update the installation
guidance following the uv tool installation in docs/get-started/setup.mdx (lines
33-34) and packages/nemo_platform/README.md (lines 26-30): replace “available
everywhere” with instructions to run uv tool update-shell, then restart the
shell or source its configuration so nemo is available on PATH.

Source: MCP tools


🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- referenced documentation ---'
for f in docs/get-started/setup.mdx packages/nemo_platform/README.md; do
  if [ -f "$f" ]; then
    printf '\n### %s\n' "$f"
    nl -ba "$f" | sed -n '20,55p'
  else
    printf 'MISSING %s\n' "$f"
  fi
done

printf '%s\n' '--- package metadata and all extra ---'
rg -n -S --glob '!*node_modules*' \
  'nemo-platform|optional-dependencies|extras_require|\[all\]|all\s*=|dependency|conflict|next release' \
  pyproject.toml setup.py setup.cfg packages docs .github 2>/dev/null | sed -n '1,240p'

printf '%s\n' '--- repository files near package metadata ---'
git ls-files | rg '(^|/)(pyproject\.toml|setup\.py|setup\.cfg|requirements[^/]*|CHANGELOG|.*release.*|.*manifest.*)$' | sed -n '1,160p'

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 33075


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- setup instructions ---'
for f in docs/get-started/setup.mdx packages/nemo_platform/README.md; do
  printf '\n### %s\n' "$f"
  sed -n '20,55p' "$f"
done

printf '%s\n' '--- package metadata ---'
sed -n '1,220p' packages/nemo_platform/pyproject.toml

printf '%s\n' '--- relevant repository changes ---'
git diff --stat
git diff -- docs/get-started/setup.mdx packages/nemo_platform/README.md packages/nemo_platform/pyproject.toml | sed -n '1,260p'

printf '%s\n' '--- all references to the published install commands ---'
rg -n -F \
  -e 'uv tool install "nemo-platform[all]"' \
  -e 'pip install "nemo-platform[all]"' \
  -e 'nemo-platform[all]' \
  docs packages README.md 2>/dev/null | sed -n '1,220p'

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 37354


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- wrapper extra definitions ---'
rg -n -A12 -B4 \
  '^\[project\.optional-dependencies\]|^all\s*=|^services\s*=|^core-service\s*=|^service' \
  packages/nemo_platform/pyproject.toml | sed -n '1,260p'

printf '%s\n' '--- bundling documentation ---'
sed -n '1,155p' packages/nemo_platform/BUNDLING.md

printf '%s\n' '--- package version and release references ---'
rg -n -S \
  '^\[tool\.hatch|version|release|0\.[0-9]+\.[0-9]+|next release|unresolved|conflict' \
  packages/nemo_platform/pyproject.toml packages/nemo_platform/BUNDLING.md \
  docs/about/release-notes/current-release.mdx .github/release* .github/workflows/release.yaml \
  2>/dev/null | sed -n '1,240p'

printf '%s\n' '--- repository state ---'
git status --short
git log -5 --oneline -- packages/nemo_platform/pyproject.toml docs/get-started/setup.mdx packages/nemo_platform/README.md

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 32952


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- recent dependency-related commits ---'
for c in 1c5a6b0e0 89868b26e 548ac20d8 76d1643aa; do
  printf '\n### %s\n' "$c"
  git show --stat --oneline "$c"
  git show --format=fuller --no-ext-diff "$c" -- \
    packages/nemo_platform/pyproject.toml \
    docs/get-started/setup.mdx \
    packages/nemo_platform/README.md \
    plugins/nemo-agents/pyproject.toml \
    uv.lock | sed -n '1,280p'
done

printf '%s\n' '--- resolver tooling availability ---'
command -v uv || true
command -v pip || true
command -v python3 || true

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 50383


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import subprocess
import tomllib
from pathlib import Path

metadata = tomllib.loads(
    Path("packages/nemo_platform/pyproject.toml").read_text(encoding="utf-8")
)
extras = metadata["project"]["optional-dependencies"]

assert extras["all"] == ["nemo-platform[services]"]
assert any(dep == "nemo-platform[plugins]" for dep in extras["services"])
assert any("nvidia-nat-core>=1.8.0,<1.9" == dep for dep in extras["nemo-agents-plugin"])

for path in (
    Path("docs/get-started/setup.mdx"),
    Path("packages/nemo_platform/README.md"),
):
    text = path.read_text(encoding="utf-8")
    assert text.count('uv tool install "nemo-platform[all]"') == 1
    assert text.count('pip install "nemo-platform[all]"') == 1
    print(f"{path}: both published commands are unpinned")

message = subprocess.check_output(
    ["git", "show", "-s", "--format=%B", "1c5a6b0e0"],
    text=True,
)
required = (
    "Published 0.3.0 still installs",
    "this affects the next release",
    "nemo-platform[all] resolves without the repo's override-dependencies",
)
for phrase in required:
    assert phrase in message
print("1c5a6b0e0: records that 0.3.0 installs but the next release remains unresolved")
print("all -> services:", extras["all"])
print("NAT constraint:", next(
    dep for dep in extras["nemo-agents-plugin"]
    if dep.startswith("nvidia-nat-core")
))
PY

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 283


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import subprocess
from pathlib import Path

pyproject = Path("packages/nemo_platform/pyproject.toml").read_text(encoding="utf-8")
for expected in (
    'all = ["nemo-platform[services]"]',
    '"nemo-platform[plugins]"',
    '"nvidia-nat-core>=1.8.0,<1.9"',
):
    assert expected in pyproject, expected

for path in (
    Path("docs/get-started/setup.mdx"),
    Path("packages/nemo_platform/README.md"),
):
    text = path.read_text(encoding="utf-8")
    assert text.count('uv tool install "nemo-platform[all]"') == 1
    assert text.count('pip install "nemo-platform[all]"') == 1
    print(f"{path}: both published commands are unpinned")

message = subprocess.check_output(
    ["git", "show", "-s", "--format=%B", "1c5a6b0e0"],
    text=True,
)
for phrase in (
    "Published 0.3.0 still installs",
    "this affects the next release",
    "nemo-platform[all] resolves without the repo's override-dependencies",
):
    assert phrase in message, phrase

print("1c5a6b0e0: records that 0.3.0 installs but the next release remains unresolved")
print("all -> services and NAT remains constrained to the 1.8 line")
PY

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 458


Pin or gate the [all] install commands. NAT 1.8 caps cryptography below the version required by data-designer==0.8.0. Use nemo-platform[all]==0.3.0 until the dependency conflict is resolved, or defer all four commands in docs/get-started/setup.mdx and packages/nemo_platform/README.md.

📍 Affects 2 files
  • docs/get-started/setup.mdx#L33-L34 (this comment)
  • docs/get-started/setup.mdx#L45-L46
  • packages/nemo_platform/README.md#L29-L30
  • packages/nemo_platform/README.md#L35-L36
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/get-started/setup.mdx` around lines 33 - 34, Pin every [all] install
command to nemo-platform[all]==0.3.0 to avoid the current dependency conflict:
update both commands in docs/get-started/setup.mdx at lines 33-34 and 45-46, and
both commands in packages/nemo_platform/README.md at lines 29-30 and 35-36.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- relevant files ---'
git ls-files 'docs/get-started/setup.mdx' 'packages/nemo_platform/README.md' \
  | while IFS= read -r f; do
    printf '\n--- %s ---\n' "$f"
    wc -l "$f"
    rg -n -C 5 'uv|python|requires-python|requires_python|Python|version' "$f" || true
  done

printf '\n--- package and project metadata candidates ---\n'
git ls-files | rg '(^|/)(pyproject\.toml|setup\.py|setup\.cfg|.*requirements.*|.*uv.*|README\.md)$' \
  | head -200

printf '\n--- Python requirement declarations ---\n'
rg -n -C 3 'requires-python|requires_python|python_requires|Programming Language :: Python|Python :: 3\.(12|13)|uv' \
  --glob 'pyproject.toml' --glob 'setup.py' --glob 'setup.cfg' --glob '*.md' --glob '*.mdx' . \
  | head -300

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 35084


🏁 Script executed:

#!/bin/bash
set -eu

for f in packages/nemo_platform/pyproject.toml pyproject.toml .cursor/rules/uv.mdc README.md; do
  if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
    printf '\n--- %s ---\n' "$f"
    wc -l "$f"
    rg -n -C 6 'requires-python|requires_python|python|tool\.uv|uv|index|resolution|conflict|nemo-platform' "$f" | head -240
  fi
done

printf '\n--- all nemo-platform Python requirements ---\n'
rg -n -C 4 'requires-python|requires_python|python_requires' \
  packages/nemo_platform/pyproject.toml sdk/python/nemo-platform/pyproject.toml \
  pyproject.toml 2>/dev/null || true

printf '\n--- install command occurrences ---\n'
rg -n -C 2 'uv tool install "nemo-platform\[all\]"|uv tool install' \
  docs/get-started/setup.mdx packages/nemo_platform/README.md README.md

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 27416


🌐 Web query:

Astral uv official documentation uv tool install --python interpreter selection default behavior requires-python

💡 Result:

When using uv tool install, the default Python interpreter selection and the handling of requires-python constraints behave according to the following logic: Python Interpreter Selection By default, uv attempts to select an appropriate Python interpreter for the tool environment [1]. It uses standard Python discovery logic [1], which searches for interpreters in the PATH, virtual environments, and managed installations (via uv python install) [2][3][4]. If no specific interpreter is requested via the --python flag, uv follows a preference hierarchy [5][4]: 1. The python-preference setting (defaulting to managed) determines whether uv prioritizes its own managed installations or system-installed interpreters [5][4]. 2. If multiple candidates exist, uv prioritizes newer versions among managed installations, while for system interpreters, it typically selects the first compatible version found [5][4]. 3. If no suitable Python version is found, uv may automatically download and install a required managed Python version [3][4]. Requires-Python Handling Historically, uv tool install did not automatically infer Python requirements from a package's metadata, which often led to resolution failures if the default discovered interpreter was incompatible [6][7]. However, recent updates have introduced mechanisms to improve this [8]: - Inference: uv can now inspect the requires-python metadata (e.g., from pyproject.toml or wheel distribution metadata) to refine the Python version request [8]. - Resolution and Refinement: If initial resolution fails due to an incompatible interpreter, uv can automatically attempt to refine the choice—including downloading a compliant managed Python version—to satisfy the tool's requirements [9]. For precise control, you can always explicitly specify the required Python version or range using the --python flag [1], for example: uv tool install --python ">=3.10" This approach overrides default discovery and ensures the tool is installed in an environment using a compatible interpreter [1][7].

Citations:


🌐 Web query:

site:docs.astral.sh/uv OR site:github.com/astral-sh/uv uv 0.9.14 tool install requires-python compatible interpreter release

💡 Result:

In uv version 0.9.14, the uv tool install command is designed to be aware of the requires-python metadata of the package being installed [1][2]. When you run uv tool install, uv performs the following steps: 1. Initial Interpreter Selection: It initially identifies a Python interpreter based on your environment and system defaults [2]. 2. Resolution and Compatibility Check: It attempts to resolve the package's dependencies. If the initially selected interpreter does not satisfy the package's Requires-Python constraint, the resolution will fail [3][1]. 3. Automated Refinement: If resolution fails due to an incompatible Python version, uv attempts to automatically refine the interpreter [3][1]. It will search for a compatible Python version—including downloading a managed Python interpreter if necessary—that satisfies the package's requires-python requirements [3][1]. It is important to note that uv tool ignores local project-specific configuration files such as .python-version or pyproject.toml files found in the current working directory [4]. Additionally, while uv respects the lower bounds of requires-python constraints during dependency resolution, it intentionally ignores upper bounds [5]. You can always override the automatic discovery by explicitly specifying the desired interpreter using the --python flag, for example: uv tool install --python 3.12 <package_name> [4][6].

Citations:


🌐 Web query:

site:github.com/astral-sh/uv/pull/19577 uv tool install requires-python version

💡 Result:

When using uv tool install, the command generally ignores non-global Python version requests, including requires-python values found in a pyproject.toml file [1][2]. Instead, it uses standard Python version discovery logic to create an isolated virtual environment for the tool [1][2]. If you need to use a specific Python version for a tool, you should use the --python flag during the installation command [1][2]. Note: Recent developments in the uv repository (as of mid-2026) have introduced experimental efforts to infer Python version requirements from source trees (e.g., peeking at pyproject.toml when installing tools from a local directory) to improve compatibility and reduce installation failures [3]. However, the stable documentation maintains that uv tool install generally ignores requires-python metadata to maintain consistent, isolated environments [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

if command -v uv >/dev/null 2>&1; then
  printf '%s\n' '--- installed uv version ---'
  uv --version
  printf '%s\n' '--- uv tool install options ---'
  uv tool install --help | rg -n -C 2 -- '--python|requires-python|version|managed'
else
  printf '%s\n' 'uv is not installed in the sandbox\n'
fi

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 200


🌐 Web query:

site:docs.astral.sh/uv/concepts/tools/ "requires-python" "uv tool install"

💡 Result:

When using the uv tool install command, uv ignores the requires-python constraint specified in a pyproject.toml file [1][2]. While uv uses standard Python version discovery logic to create an isolated virtual environment for the tool, it explicitly excludes non-global Python version requests, including.python-version files and requires-python metadata [1][2]. If you need to install a tool with a specific Python version requirement, you must explicitly provide the --python option during the installation command [1][2]. For example: uv tool install --python If the Python version selected for the tool is later uninstalled, the tool environment will be broken and the tool may become unusable [1][2].

Citations:


🌐 Web query:

site:docs.astral.sh/uv/concepts/tools/ "The Python version" "--python" tool install

💡 Result:

To specify a Python version when installing a tool with the uv package manager, you can use the --python option [1][2]. For example, to install a package with a specific Python version using uv, you would use the following syntax [1][2]: uv tool install --python Each tool installed via uv is linked to a specific Python version [1][2]. When using the --python option, uv uses its standard Python version discovery logic to locate the requested version, while ignoring local configuration files like.python-version or pyproject.toml requirements [1][2]. If the specified Python version is later uninstalled from your system, the tool environment will become broken and the tool may no longer function [1][2].

Citations:


🌐 Web query:

site:docs.astral.sh/uv/guides/tools/ "python" "tool install"

💡 Result:

To install Python tools for personal use, the current recommended approach is to use tools like uv or pipx, which create isolated environments for each application to prevent dependency conflicts. Using uv, you can install a tool into a persistent environment where its executables are added to your PATH, allowing you to run them directly [1][2]. To install a tool using uv, use the following command: uv tool install For example, to install ruff: uv tool install ruff When installed this way, uv places the tool's executables in a bin directory [1][2]. If the directory is not already in your PATH, you can update your shell configuration using: uv tool update-shell If you want to specify a particular Python version for the tool, you can provide it during installation [1][2]: uv tool install --python 3.10 ruff Unlike installing packages with standard pip into your global environment, using these dedicated tool managers ensures that each application's dependencies remain isolated [1][2].

Citations:


🌐 Web query:

site:docs.astral.sh/uv/concepts/tools/ "Requires-Python" package metadata tool environment

💡 Result:

The Requires-Python metadata field is a specification used in Python packaging to declare the range of Python versions that a package or project supports [1][2][3]. This field is typically defined in a projects configuration file, such as pyproject.toml. When working with packaging tools and environments, the Requires-Python value serves as a constraint for installation. For instance, if a user attempts to install a package into an environment running a Python version outside the range specified in Requires-Python, the packaging tool should identify this incompatibility and prevent the installation. However, usage can vary by tool context. For example, some modern tooling like uv, when managing isolated tool environments, may ignore the Requires-Python value from a projects pyproject.toml in favor of specific version discovery logic or explicit user-provided version requirements [1][3]. In these specific tool environments, the tool links the environment to a designated Python version rather than strictly adhering to the metadata constraint defined within the project itself [1][2].

Citations:


Pin the tool environment to Python 3.13. uv tool install does not use local Python constraints during interpreter discovery, while nemo-platform requires Python 3.12–3.13. Apply --python 3.13 to both commands. Add uv >=0.9.14 to the package README prerequisites.

📍 Affects 2 files
  • docs/get-started/setup.mdx#L33-L34 (this comment)
  • packages/nemo_platform/README.md#L29-L30
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/get-started/setup.mdx` around lines 33 - 34, Pin both uv tool
installation commands in docs/get-started/setup.mdx (lines 33-34) to Python 3.13
by adding the --python 3.13 option. Update packages/nemo_platform/README.md
(lines 29-30) to list uv >=0.9.14 in the prerequisites.

Source: MCP tools


</Tab>

<Tab title="Virtual environment">

Use when you also import the SDK from your own code. `nemo` works only while the environment is active.

```bash
python -m venv .venv
source .venv/bin/activate
pip install "nemo-platform[all]"
```

For SDK and CLI usage only, install the base package:
</Tab>

```bash
pip install nemo-platform
```
</Tabs>

After installing `nemo-platform[all]` from PyPI, continue with `nemo setup`.
Continue with `nemo setup`.

### Install from source

Expand Down
12 changes: 8 additions & 4 deletions packages/nemo_platform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ NeMo Platform brings NVIDIA NeMo libraries together under one CLI, Python SDK, a

**Prerequisites:** Python 3.12–3.13 and an API key for an inference provider (NVIDIA Build, OpenAI, Anthropic, Google Gemini, or a local Ollama instance).

The `nemo-platform` distribution is a convenience wrapper that bundles the SDK, shared runtime packages, default first-party plugins, and platform services into a single wheel. Install just the SDK and CLI, or install everything needed to run the platform locally:
The `nemo-platform` distribution is a convenience wrapper that bundles the SDK, shared runtime packages, default first-party plugins, and platform services into a single wheel. The `all` extra adds the platform services; drop it for the SDK and CLI alone.

Recommended — one command, `nemo` available everywhere, nothing to activate:

```bash
# SDK + CLI only
pip install nemo-platform
uv tool install "nemo-platform[all]"
```

# SDK + CLI + all platform services and default plugins (recommended)
Use a virtual environment instead when you also import the SDK from your own code. `nemo` then works only while the environment is active:

```bash
pip install "nemo-platform[all]"
```
Comment on lines +32 to 36

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,90p' packages/nemo_platform/README.md
printf '\n--- related setup references ---\n'
rg -n -i 'virtual environment|python -m venv|nemo-platform\[all\]|pip install|uv sync|NeMoPlatform' packages/nemo_platform docs README.md 2>/dev/null | head -200

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 28297


🏁 Script executed:

cat -n packages/nemo_platform/README.md | sed -n '1,90p'
printf '\n--- related setup references ---\n'
rg -n -i 'virtual environment|python -m venv|nemo-platform\[all\]|pip install|uv sync|NeMoPlatform' packages/nemo_platform docs README.md 2>/dev/null | head -200

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 27070


🏁 Script executed:

sed -n '25,60p' docs/get-started/setup.mdx
printf '\n--- CLI installation tabs ---\n'
sed -n '32,60p' docs/cli/index.mdx
printf '\n--- interpreter behavior probe ---\n'
python3 - <<'PY'
import os
import sys
print("current interpreter:", sys.executable)
print("virtual environment active:", sys.prefix != sys.base_prefix)
print("pip target for `python -m pip`:", sys.prefix)
print("PATH pip candidates:")
for directory in os.environ.get("PATH", "").split(os.pathsep):
    candidate = os.path.join(directory, "pip")
    if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
        print(candidate)
PY

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 1738


Create and activate the virtual environment before installing.

This command can install into the current system interpreter. Add the setup sequence or link to docs/get-started/setup.mdx.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_platform/README.md` around lines 32 - 36, Update the
installation instructions in the README to include creating and activating a
virtual environment before running the nemo-platform installation command, or
link to the existing setup guidance in docs/get-started/setup.mdx.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import typer
from nemo_platform_ext.cli.core.help_formatter import create_typer_app
from nemo_platform_ext.cli.docker_preflight import require_docker_for_default_local
from nemo_platform_ext.local.install import services_extra_install_command
from nemo_platform_ext.local.process import (
ForegroundInstanceError,
InstanceAlreadyRunningError,
Expand Down Expand Up @@ -75,10 +76,7 @@ def _require_services_extra() -> None:
"Running local platform services needs extra components that aren't installed yet.\n"
"\n"
"Install them with:\n"
" pip install 'nemo-platform[all]'\n"
"\n"
"On Python 3.14, use:\n"
" PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 pip install 'nemo-platform[all]'\n",
f" {services_extra_install_command()}\n",
err=True,
)
raise typer.Exit(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from pydantic import SecretStr
from rich import box
from rich.console import Console
from rich.markup import escape
from rich.panel import Panel

from nemo_platform_ext.cli.commands.skills import registry as skills_registry
Expand All @@ -49,6 +50,7 @@
from nemo_platform_ext.client.tls import client_verify_from_env
from nemo_platform_ext.config.config import Config
from nemo_platform_ext.config.models import DEFAULT_BASE_URL, ConfigFile, ConfigParams, LocalServicesConfig, NoAuthUser
from nemo_platform_ext.local.install import services_extra_install_command
from nemo_platform_ext.local.process import (
PortConflict,
check_port_available_for_start,
Expand Down Expand Up @@ -1154,9 +1156,7 @@ def _maybe_start_services(
if importlib.util.find_spec("pyleak") is None:
console.print(f"{CROSS} Local services require extra dependencies that aren't installed.")
console.print(" Install them with:")
console.print(" [cyan]pip install 'nemo-platform\\[all]'[/cyan]")
console.print(" On Python 3.14, use:")
console.print(" [cyan]PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 pip install 'nemo-platform\\[all]'[/cyan]")
console.print(f" [cyan]{escape(services_extra_install_command())}[/cyan]")
raise typer.Exit(1)

# Fail before stop/spawn when default local needs Docker (NVBug 6537617).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""How this NeMo Platform install was created."""

from __future__ import annotations

import sys
from pathlib import Path


def services_extra_install_command() -> str:
"""Return the command that adds the packaged service dependencies here.

``uv tool install`` environments are managed by uv and are not meant to be
edited with pip; re-running the tool install with the extra upgrades them
in place. uv marks such an environment with a ``uv-receipt.toml`` at its
root, which is what distinguishes it from an ordinary virtual environment.
"""
if (Path(sys.prefix) / "uv-receipt.toml").is_file():
return "uv tool install 'nemo-platform[all]'"
return "pip install 'nemo-platform[all]'"
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from nemo_platform import AsyncNeMoPlatform, NeMoPlatform
from nemo_platform_ext.local import process
from nemo_platform_ext.local.install import services_extra_install_command
from nemo_platform_ext.local.transport import (
EMBEDDED_BASE_URL,
UDS_BASE_URL,
Expand Down Expand Up @@ -407,7 +408,7 @@ async def stop_async(self, *, timeout: float = 30.0, force: bool = False) -> pro
def require_services_extra() -> None:
if importlib.util.find_spec("pyleak") is not None:
return
raise ServicesExtraRequiredError("Install service dependencies with `pip install 'nemo-platform[all]'`.")
raise ServicesExtraRequiredError(f"Install service dependencies with `{services_extra_install_command()}`.")


def _validate_socket_path_length(socket_path: Path) -> None:
Expand Down
27 changes: 27 additions & 0 deletions packages/nemo_platform_ext/tests/local/test_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

import sys
from pathlib import Path

import pytest
from nemo_platform_ext.local.install import services_extra_install_command


@pytest.mark.parametrize(
("uv_tool_env", "expected"),
[
(False, "pip install 'nemo-platform[all]'"),
(True, "uv tool install 'nemo-platform[all]'"),
],
)
def test_services_extra_install_command_matches_install_method(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, uv_tool_env: bool, expected: str
) -> None:
if uv_tool_env:
(tmp_path / "uv-receipt.toml").write_text("[tool]\n")
monkeypatch.setattr(sys, "prefix", str(tmp_path))

assert services_extra_install_command() == expected
4 changes: 2 additions & 2 deletions script/compile-wheel-constraints.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ emit_constraints() {
local wheel="$1" spec="$2" label="$3" out="$4" venv meta
venv="$(mktemp -d)"
meta="$(mktemp -d)"
uv venv "${venv}" --python 3.11 --quiet
uv venv "${venv}" --python 3.12 --quiet
# Resolve+install once with the cap so we snapshot consistent, py3.14-safe versions.
printf '%s\n' "${LITELLM_CAP%% *}" >"${meta}/cap.txt"
uv pip install --python "${venv}/bin/python" --constraint "${meta}/cap.txt" "${spec}" >/dev/null
Expand All @@ -61,7 +61,7 @@ PY
printf '# Regenerate with: script/compile-wheel-constraints.sh <dir-with-built-wheels>\n#\n'
while read -r name; do
[[ -n "${name}" ]] || continue
ver="$("${venv}/bin/python" -c "import importlib.metadata as m; print(m.version('${name}'))" 2>/dev/null || true)
ver="$("${venv}/bin/python" -c "import importlib.metadata as m; print(m.version('${name}'))" 2>/dev/null || true)"
[[ -n "${ver}" ]] && printf '%s==%s\n' "${name}" "${ver}"
done <"${meta}/names.txt" | sort
printf '%s\n' "${LITELLM_CAP}"
Expand Down
15 changes: 14 additions & 1 deletion script/test-nemo-cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,20 @@ done

echo "----- nemo on PATH -----"
command -v nemo
nemo --version
version_output="$(nemo --version)"
echo "${version_output}"
# A bare `0.0.0` is the CLI's fallback when its importlib.metadata lookup
# misses the distribution it was installed from, which is invisible unless the
# output is asserted. Match it exactly: nightly wheels are stamped with a
# sentinel `0.0.0.dev<timestamp>` that is a legitimate version string. The
# pattern is the subset of PEP 440 this project stamps — release, optional
# pre-release, any number of .post/.dev segments, optional local version.
version="${version_output#nemo version }"
if [[ "${version}" == "0.0.0" ]] ||
[[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?(\.(post|dev)[0-9]+)*(\+[0-9a-z.]+)?$ ]]; then
echo "::error::nemo --version did not report an installed version: ${version_output}" >&2
exit 1
fi

# Import-time checks for commands that ship in the bundled wrapper. We don't
# call `nemo services --help` here because `nemo services run` below is a
Expand Down
3 changes: 1 addition & 2 deletions sdk/python/nemo-platform/pyproject.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion sdk/python/nemo-platform/src/nemo_platform/_version.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading