Skip to content
Merged
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
53 changes: 52 additions & 1 deletion .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,23 @@ reviews:
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=cloud-e2e,sandbox-operations-e2e,rebuild-openclaw-e2e,messaging-compatible-endpoint-e2e,hermes-discord-e2e,hermes-slack-e2e,openshell-gateway-upgrade-e2e
```

- path: "src/lib/actions/inference-set.ts"
instructions: |
This file switches the OpenShell inference route and patches the
selected running agent config. Changes here affect OpenClaw and
Hermes model switching without a sandbox rebuild.

**E2E test recommendation:**
- `openclaw-inference-switch-e2e` — OpenClaw route + config patch
+ live OpenClaw request after switch
- `hermes-inference-switch-e2e` — Hermes route + config.yaml patch
+ live Hermes request after switch

To run selectively:
```
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=openclaw-inference-switch-e2e,hermes-inference-switch-e2e
```

- path: "src/nemoclaw.ts"
instructions: |
This file contains CLI dispatch, status, recovery, and connect
Expand Down Expand Up @@ -274,6 +291,8 @@ reviews:

**E2E test recommendation:**
- `hermes-e2e` — Hermes onboard + health probe + live inference
- `hermes-inference-switch-e2e` — Hermes route + config.yaml patch
+ live Hermes request after switch
- `hermes-discord-e2e` — Hermes Discord config schema + placeholder
isolation
- `hermes-slack-e2e` — Hermes Slack policy + Python placeholder egress
Expand All @@ -282,7 +301,7 @@ reviews:

To run selectively:
```
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=hermes-e2e,hermes-discord-e2e,hermes-slack-e2e,rebuild-hermes-e2e,rebuild-hermes-stale-base-e2e
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=hermes-e2e,hermes-inference-switch-e2e,hermes-discord-e2e,hermes-slack-e2e,rebuild-hermes-e2e,rebuild-hermes-stale-base-e2e
```

- path: "test/e2e/test-hermes-slack-e2e.sh"
Expand Down Expand Up @@ -357,6 +376,38 @@ reviews:
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=cloud-inference-e2e
```

- path: "test/e2e/test-openclaw-inference-switch.sh"
instructions: |
This script validates OpenClaw model/provider switching with
`nemoclaw inference set`, including OpenShell route state,
/sandbox/.openclaw/openclaw.json, config hash recomputation, and
live requests after the switch.

**E2E test recommendation:**
- `openclaw-inference-switch-e2e` — OpenClaw route + config patch
+ live OpenClaw request after switch

To run selectively:
```
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=openclaw-inference-switch-e2e
```

- path: "test/e2e/test-hermes-inference-switch.sh"
instructions: |
This script validates Hermes model/provider switching with
`nemohermes inference set`, including OpenShell route state,
/sandbox/.hermes/config.yaml, config hash recomputation, .env
preservation, and live requests after the switch.

**E2E test recommendation:**
- `hermes-inference-switch-e2e` — Hermes route + config.yaml patch
+ live Hermes request after switch

To run selectively:
```
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=hermes-inference-switch-e2e
```

- path: "test/e2e/test-skill-agent-e2e.sh"
instructions: &e2e-skill-agent |
This script tests skill injection into the sandbox and verifies
Expand Down
85 changes: 84 additions & 1 deletion .github/workflows/nightly-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@
# processes are restarted after an OpenShell upgrade.
# hermes-e2e Hermes Agent E2E — install → onboard --agent hermes → health
# probe → live inference. Validates the multi-agent architecture.
# hermes-inference-switch-e2e
# Switches a running Hermes sandbox with `nemohermes inference set`
# and verifies route, config.yaml, hashes, and live requests.
# hermes-discord-e2e Hermes Discord onboarding — validates the top-level Hermes
# Discord schema plus OpenShell placeholder/token isolation.
# hermes-slack-e2e Hermes Slack onboarding — validates the Hermes Slack policy,
# Slack providers, and Python placeholder egress path.
# openclaw-inference-switch-e2e
# Switches a running OpenClaw sandbox with `nemoclaw inference set`
# and verifies route, openclaw.json, hashes, and live requests.
# credential-migration-e2e Validates legacy ~/.nemoclaw/credentials.json migration to the
# OpenShell gateway, secure zero-fill on unlink, allowlist filter
# on non-credential env keys, and symlink-safe deletion.
Expand Down Expand Up @@ -62,8 +68,10 @@ on:
kimi-inference-compat-e2e,
token-rotation-e2e, sandbox-survival-e2e,
openshell-gateway-upgrade-e2e,
issue-2478-crash-loop-recovery-e2e, hermes-e2e, hermes-discord-e2e,
issue-2478-crash-loop-recovery-e2e, hermes-e2e,
hermes-inference-switch-e2e, hermes-discord-e2e,
hermes-slack-e2e, sandbox-operations-e2e, inference-routing-e2e,
openclaw-inference-switch-e2e,
network-policy-e2e, deployment-services-e2e, diagnostics-e2e,
credential-migration-e2e,
snapshot-commands-e2e, shields-config-e2e, rebuild-openclaw-e2e,
Expand Down Expand Up @@ -511,6 +519,41 @@ jobs:
path: /tmp/nemoclaw-e2e-hermes-install.log
if-no-files-found: ignore

# ── Hermes inference switch E2E ─────────────────────────────────
# Validates `nemohermes inference set` against a running Hermes sandbox:
# OpenShell route, config.yaml patch, config hashes, no automatic restart,
# and live requests after the switch.
hermes-inference-switch-e2e:
if: >-
github.repository == 'NVIDIA/NemoClaw' &&
(github.event_name != 'workflow_dispatch' ||
inputs.jobs == '' ||
contains(format(',{0},', inputs.jobs), ',hermes-inference-switch-e2e,'))
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Run Hermes inference switch E2E test
env:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
NEMOCLAW_NON_INTERACTIVE: "1"
NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1"
NEMOCLAW_SANDBOX_NAME: "e2e-hermes-inference-switch"
NEMOCLAW_RECREATE_SANDBOX: "1"
NEMOCLAW_AGENT: "hermes"
GITHUB_TOKEN: ${{ github.token }}
run: bash test/e2e/test-hermes-inference-switch.sh

- name: Upload install log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: hermes-inference-switch-install-log
path: /tmp/nemoclaw-e2e-hermes-inference-switch-install.log
if-no-files-found: ignore

# ── Hermes Discord E2E ───────────────────────────────────────
# Validates Hermes onboarding with Discord enabled. Proves the Hermes
# sandbox gets top-level discord: config, never platforms.discord, and only
Expand Down Expand Up @@ -867,6 +910,40 @@ jobs:
path: test-inference-routing-*.log
if-no-files-found: ignore

# ── OpenClaw inference switch E2E ───────────────────────────────
# Validates `nemoclaw inference set` against a running OpenClaw sandbox:
# OpenShell route, openclaw.json patch, config hash, no automatic restart,
# and live requests after the switch.
openclaw-inference-switch-e2e:
if: >-
github.repository == 'NVIDIA/NemoClaw' &&
(github.event_name != 'workflow_dispatch' ||
inputs.jobs == '' ||
contains(format(',{0},', inputs.jobs), ',openclaw-inference-switch-e2e,'))
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Run OpenClaw inference switch E2E test
env:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
NEMOCLAW_NON_INTERACTIVE: "1"
NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE: "1"
NEMOCLAW_SANDBOX_NAME: "e2e-openclaw-inference-switch"
NEMOCLAW_RECREATE_SANDBOX: "1"
GITHUB_TOKEN: ${{ github.token }}
run: bash test/e2e/test-openclaw-inference-switch.sh

- name: Upload install log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: openclaw-inference-switch-install-log
path: /tmp/nemoclaw-e2e-openclaw-inference-switch-install.log
if-no-files-found: ignore

# ── Network policy E2E ───────────────────────────────────────
# TC-NET-01..07, TC-NET-09: deny-by-default, whitelist, live policy-add,
# dry-run, hot-reload, inference exemption, permissive mode, SSRF validation.
Expand Down Expand Up @@ -1724,10 +1801,12 @@ jobs:
sandbox-survival-e2e,
issue-2478-crash-loop-recovery-e2e,
hermes-e2e,
hermes-inference-switch-e2e,
hermes-discord-e2e,
hermes-slack-e2e,
sandbox-operations-e2e,
inference-routing-e2e,
openclaw-inference-switch-e2e,
network-policy-e2e,
deployment-services-e2e,
diagnostics-e2e,
Expand Down Expand Up @@ -1812,10 +1891,12 @@ jobs:
sandbox-survival-e2e,
issue-2478-crash-loop-recovery-e2e,
hermes-e2e,
hermes-inference-switch-e2e,
hermes-discord-e2e,
hermes-slack-e2e,
sandbox-operations-e2e,
inference-routing-e2e,
openclaw-inference-switch-e2e,
network-policy-e2e,
deployment-services-e2e,
diagnostics-e2e,
Expand Down Expand Up @@ -1948,10 +2029,12 @@ jobs:
sandbox-survival-e2e,
issue-2478-crash-loop-recovery-e2e,
hermes-e2e,
hermes-inference-switch-e2e,
hermes-discord-e2e,
hermes-slack-e2e,
sandbox-operations-e2e,
inference-routing-e2e,
openclaw-inference-switch-e2e,
network-policy-e2e,
deployment-services-e2e,
diagnostics-e2e,
Expand Down
6 changes: 6 additions & 0 deletions ci/platform-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@
"endpoint_type": "OpenAI-compatible",
"notes": "Uses Google's OpenAI-compatible endpoint"
},
{
"name": "Hermes Provider",
"status": "hermes only",
"endpoint_type": "OpenAI-compatible route",
"notes": "Available when onboarding Hermes Agent through `nemohermes`"
},
{
"name": "Local Ollama",
"status": "caveated",
Expand Down
5 changes: 3 additions & 2 deletions docs/get-started/quickstart-hermes.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,11 @@ $ nemohermes my-hermes snapshot create --name before-change
$ nemohermes my-hermes rebuild
```

To change the active model or provider without rebuilding the sandbox, use the OpenShell inference route.
To change the active model or provider without rebuilding the sandbox, use `nemohermes inference set`.
It updates the OpenShell inference route and patches `/sandbox/.hermes/config.yaml` without restarting Hermes.

```console
$ openshell inference set -g nemoclaw --model <model> --provider <provider>
$ nemohermes inference set --model <model> --provider <provider>
```

To remove the sandbox when you are done, destroy it explicitly.
Expand Down
2 changes: 2 additions & 0 deletions docs/inference/inference-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ NemoClaw uses provider-specific local tokens for those routes, and rebuilds of l
| Anthropic | Tested | Native Anthropic | Uses anthropic-messages |
| Other Anthropic-compatible endpoint | Tested | Custom Anthropic-compatible | For Claude proxies and compatible gateways |
| Google Gemini | Tested | OpenAI-compatible | Uses Google's OpenAI-compatible endpoint |
| Hermes Provider | Hermes only | OpenAI-compatible route | Available when onboarding Hermes Agent through `nemohermes` |
| Local Ollama | Caveated | Local Ollama API | Available when Ollama is installed or running on the host |
| Local NVIDIA NIM | Experimental | Local OpenAI-compatible | Requires `NEMOCLAW_EXPERIMENTAL=1` and a NIM-capable GPU |
| Local vLLM | Experimental | Local OpenAI-compatible | Requires `NEMOCLAW_EXPERIMENTAL=1` and a server already running on `localhost:8000` |
Expand All @@ -68,6 +69,7 @@ Experimental local vLLM appears when you opt in and NemoClaw detects either a ru
| Anthropic | Routes to the Anthropic Messages API. Set `ANTHROPIC_API_KEY`. | `claude-sonnet-4-6`, `claude-haiku-4-5`, `claude-opus-4-6` |
| Other Anthropic-compatible endpoint | Routes to any server that implements the Anthropic Messages API (`/v1/messages`). The wizard prompts for a base URL and model name. Set `COMPATIBLE_ANTHROPIC_API_KEY`. | You provide the model name. |
| Google Gemini | Routes to Google's OpenAI-compatible endpoint. NemoClaw prefers `/responses` only when the endpoint proves it can handle tool calling in a way OpenClaw uses; otherwise it falls back to `/chat/completions`. Set `GEMINI_API_KEY`. | `gemini-3.1-pro-preview`, `gemini-3.1-flash-lite-preview`, `gemini-3-flash-preview`, `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite` |
| Hermes Provider | Routes Hermes Agent through the host OpenShell provider registered by NemoClaw when onboarding Hermes Agent. | Curated Hermes Provider models such as `moonshotai/kimi-k2.6`, `openai/gpt-5.4-mini`, and `z-ai/glm-5.1`. |
| Local Ollama | Routes to a local Ollama instance on `localhost:11434`. NemoClaw detects installed models, offers starter models if none are present, pulls and warms the selected model, and validates it. | Selected during onboarding. For more information, refer to [Use a Local Inference Server](use-local-inference.md). |
| Model Router | Starts a host-side router on port `4000`, registers it as an OpenAI-compatible provider, and keeps the sandbox pointed at `inference.local`. Set `NEMOCLAW_PROVIDER=routed` for non-interactive setup. | The router pool defines the model names. |

Expand Down
15 changes: 13 additions & 2 deletions docs/inference/switch-inference-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ No restart is required.
## Switch to a Different Model

Use `nemoclaw inference set` with the provider and model that match the upstream you want to use.
The command updates the OpenShell inference route and synchronizes the running OpenClaw config so `agents.defaults.model.primary` continues to match the routed model.
The command updates the OpenShell inference route and synchronizes the running agent config.
For OpenClaw, it updates `agents.defaults.model.primary` and the matching provider namespace.
For Hermes, it updates `/sandbox/.hermes/config.yaml` (`model.default`, `model.base_url`, and `model.provider: custom`) without rebuilding or restarting Hermes.

Pass `--sandbox <name>` when you do not want to use the default registered sandbox.
Under `nemohermes`, pass `--sandbox <name>` when more than one Hermes sandbox is registered.

### NVIDIA Endpoints

Expand Down Expand Up @@ -75,6 +78,14 @@ $ nemoclaw inference set --provider compatible-endpoint --model <model-name>
$ nemoclaw inference set --provider compatible-anthropic-endpoint --model <model-name>
```

### Hermes Provider

For a NemoClaw-managed Hermes sandbox, use the Hermes alias with the registered Hermes Provider route:

```console
$ nemohermes inference set --provider hermes-provider --model openai/gpt-5.4-mini
```

#### Switching from Responses API to Chat Completions

If onboarding selected `/v1/responses` but the agent fails at runtime (for
Expand Down Expand Up @@ -188,7 +199,7 @@ The output includes the active provider, model, and endpoint.

- The host keeps provider credentials.
- The sandbox continues to use `inference.local`.
- `nemoclaw inference set` patches the selected running OpenClaw sandbox config and recomputes its config hash.
- `nemoclaw inference set` patches the selected running OpenClaw or Hermes sandbox config and recomputes its config hash.
- Use `nemoclaw onboard --resume --recreate-sandbox` for build-time settings such as context window, max tokens, reasoning mode, heartbeat cadence, or image contents.
- Local Ollama and local vLLM routes use local provider tokens rather than `OPENAI_API_KEY`. Rebuilds of older local-inference sandboxes clear the stale OpenAI credential requirement automatically.

Expand Down
10 changes: 8 additions & 2 deletions docs/reference/cli-selection-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,19 @@ Approved endpoints are session-scoped unless you also add them to the policy thr

### Change Models or Providers

Use the NemoClaw command for model or provider switches so the OpenShell route and the running OpenClaw config stay consistent:
Use the NemoClaw command for model or provider switches so the OpenShell route and the running agent config stay consistent:

```console
$ nemoclaw inference set --provider nvidia-prod --model nvidia/nemotron-3-super-120b-a12b
```

For a build-time OpenClaw setting change, rerun onboarding so the sandbox configuration is recreated consistently:
For Hermes sandboxes, use the alias; it updates the route and `/sandbox/.hermes/config.yaml` without a rebuild or restart:

```console
$ nemohermes inference set --provider hermes-provider --model openai/gpt-5.4-mini
```

For a build-time agent setting change, rerun onboarding so the sandbox configuration is recreated consistently:

```console
$ nemoclaw onboard --resume --recreate-sandbox
Expand Down
9 changes: 5 additions & 4 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -869,17 +869,18 @@ $ nemoclaw status --json

### `nemoclaw inference set`

Switch the active inference provider or model for a NemoClaw-managed OpenClaw sandbox.
The command updates the OpenShell gateway route, patches the selected running OpenClaw config so the agent's primary model identity matches the route, recomputes the config hash, and updates the NemoClaw registry.
Switch the active inference provider or model for a NemoClaw-managed OpenClaw or Hermes sandbox.
The command updates the OpenShell gateway route, patches the selected running agent config so it matches the route, recomputes the config hash, and updates the NemoClaw registry.
For Hermes, the patch updates `/sandbox/.hermes/config.yaml` (`model.default`, `model.base_url`, and `model.provider: custom`) and does not rebuild or restart the gateway.

By default, the command syncs the default registered sandbox.
Pass `--sandbox <name>` to target a different OpenClaw sandbox.
Under the `nemohermes` alias, it uses the registered Hermes sandbox when exactly one exists; otherwise pass `--sandbox <name>` to target one explicitly.

```console
$ nemoclaw inference set --provider <provider> --model <model> [--sandbox <name>] [--no-verify]
```

Supported provider names are `nvidia-prod`, `nvidia-nim`, `nvidia-router`, `openai-api`, `anthropic-prod`, `compatible-anthropic-endpoint`, `gemini-api`, `compatible-endpoint`, `ollama-local`, and `vllm-local`.
Supported provider names are `nvidia-prod`, `nvidia-nim`, `nvidia-router`, `openai-api`, `anthropic-prod`, `compatible-anthropic-endpoint`, `gemini-api`, `compatible-endpoint`, `hermes-provider`, `ollama-local`, and `vllm-local`.
Use `--no-verify` only when OpenShell cannot verify the provider at switch time but you have already confirmed the provider and credential.

### `nemoclaw setup`
Expand Down
2 changes: 1 addition & 1 deletion src/commands/inference/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { withCommandDisplay } from "../../lib/cli/command-display";
export default withCommandDisplay(Command, [
{
usage: "nemoclaw inference set",
description: "Switch inference and sync OpenClaw model identity",
description: "Switch inference and sync the running agent config",
flags: "--provider <provider> --model <model> [--sandbox <name>] [--no-verify]",
group: "Services",
scope: "global",
Expand Down
Loading
Loading