Skip to content

Commit 49f3163

Browse files
authored
feat(cli): add Deep Agents aliases (#5881)
<!-- markdownlint-disable MD041 --> ## Summary Adds a `nemo-deepagents` host CLI alias for the LangChain Deep Agents Code runtime and teaches onboarding to accept common user-facing agent aliases. This lets users run `nemo-deepagents onboard` or shorter forms such as `nemoclaw onboard --agent dcode`, `--agent deepagents`, and `--agent langchain` instead of remembering `langchain-deepagents-code`. ## Changes - Registered `nemo-deepagents` as an npm bin that reuses the existing `bin/nemoclaw.js` launcher and selects Deep Agents Code when invoked through that symlink. - Added canonical agent alias resolution for `--agent` and `NEMOCLAW_AGENT`, including `nemohermes`, `dcode`, `deepagents`, `deepagents-code`, `langchain`, and related variants. - Updated CLI branding, installer/update branding, onboard `--agent` help, and unknown-agent diagnostics for the alias set. - Updated Deep Agents quickstart, command reference, and platform support docs; adjusted platform-doc validation to allow documented aliases. - Added/updated tests for CLI alias behavior, onboarding arg parsing/help, agent definition alias resolution, update copy, oclif help, and platform-doc validation. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [x] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check all that apply. For any "covered by existing tests", "not applicable", or waiver entry, add a brief justification on the same line or in the Changes section. --> - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [x] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: self-review; changes are limited to agent selector canonicalization, launcher branding, installer alias selection, docs, and tests, with no credential handling or network-policy enforcement changes. - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification <!-- Check each item you ran and confirmed. Leave unchecked items you skipped. Doc-only changes do not require npm test unless you ran it. --> - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Git hooks passed during commit and push, or `npx prek run --from-ref main --to-ref HEAD` passes - [x] Targeted tests pass for changed behavior - [ ] Full `npm test` passes (broad runtime changes only) - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Verification commands run: - `npm run build:cli` - `npx vitest run test/nemohermes-alias.test.ts test/nemo-deepagents-alias.test.ts test/update.test.ts test/cli-oclif-compatibility.test.ts src/lib/cli/branding.test.ts src/lib/actions/update.test.ts src/lib/agent/defs.test.ts src/lib/onboard/legacy-command.test.ts src/lib/onboard/agent-flag-help.test.ts src/lib/onboard/command-support.test.ts test/cli/dispatch-basics.test.ts test/generate-platform-docs.test.ts --reporter=dot` - `NEMOCLAW_RUN_INSTALLER_TESTS=1 npx vitest run --project installer-integration test/install-preflight.test.ts --reporter=dot` - `npm run typecheck:cli` - `npm run validate:configs` - `python3 scripts/generate-platform-docs.py --check` - `npm run docs` (passed; Fern reported two hidden warnings) - Commit hooks passed; latest push hooks passed. --- <!-- DCO sign-off is required in this PR description, and every commit must appear as Verified in GitHub. Run: git config user.name && git config user.email --> Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a `nemo-deepagents` CLI alias for Deep Agents with matching branding, help, onboarding, uninstall, and update flows. * **Documentation** * Updated quickstart and command/reference docs to use the Deep Agents CLI wrapper and clarified `--agent` alias vs canonical name behavior. * Refreshed platform support/onboarding matrix entries for the new alias. * **Bug Fixes** * Improved agent selector alias resolution and enhanced “unknown agent” guidance with supported alias mappings. * Sanitized Deep Agents update environment variables during installs. * **Tests** * Added/expanded coverage for Deep Agents alias behavior and alias canonicalization. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 9c8ee86 commit 49f3163

27 files changed

Lines changed: 645 additions & 66 deletions

bin/nemoclaw.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,10 @@
33
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
44
// SPDX-License-Identifier: Apache-2.0
55

6+
const invokedAs = require("node:path").basename(process.argv[1] || "");
7+
if (invokedAs === "nemo-deepagents") {
8+
process.env.NEMOCLAW_AGENT = "langchain-deepagents-code";
9+
process.env.NEMOCLAW_INVOKED_AS = "nemo-deepagents";
10+
}
11+
612
require("../dist/nemoclaw");

ci/platform-matrix.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
"name": "LangChain Deep Agents Code",
163163
"status": "experimental",
164164
"default": false,
165-
"notes": "Terminal-oriented coding harness (no in-sandbox gateway, no dashboard) built on the Deep Agents SDK; manifest at `agents/langchain-deepagents-code/manifest.yaml` with binary `dcode`. Onboard with `$$nemoclaw onboard --agent langchain-deepagents-code` and follow [the quickstart](../get-started/quickstart-langchain-deepagents-code). NemoClaw runs it as a managed harness: unmanaged sandbox/MCP/shell overrides are rejected and credential-bearing proxy URLs are dropped from persisted shell env. Inference routes through OpenShell's `inference.local` endpoint via Deep Agents Code's OpenAI-compatible provider. Live runtime acceptance, broader launch material, and terminal-agent diagnostics are tracked at open issue #4861."
165+
"notes": "Terminal-oriented coding harness (no in-sandbox gateway, no dashboard) built on the Deep Agents SDK; manifest at `agents/langchain-deepagents-code/manifest.yaml` with binary `dcode`. Onboard with `$$nemo-deepagents onboard` or `$$nemoclaw onboard --agent langchain-deepagents-code`, and follow [the quickstart](../get-started/quickstart-langchain-deepagents-code). NemoClaw runs it as a managed harness: unmanaged sandbox/MCP/shell overrides are rejected and credential-bearing proxy URLs are dropped from persisted shell env. Inference routes through OpenShell's `inference.local` endpoint via Deep Agents Code's OpenAI-compatible provider. Live runtime acceptance, broader launch material, and terminal-agent diagnostics are tracked at open issue #4861."
166166
}
167167
],
168168

docs/get-started/quickstart-langchain-deepagents-code.mdx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ Use this guide to build an OpenShell sandbox with the `dcode` terminal coding ag
1919

2020
## Onboard
2121

22-
Run onboarding with the canonical agent ID.
22+
Run onboarding with the Deep Agents alias, or use `nemoclaw --agent` with either the canonical agent ID or a short alias.
2323

2424
```bash
25+
nemo-deepagents onboard
26+
# Equivalent:
2527
nemoclaw onboard --agent langchain-deepagents-code
28+
# Also accepted:
29+
nemoclaw onboard --agent dcode
30+
nemoclaw onboard --agent deepagents
31+
nemoclaw onboard --agent langchain
2632
```
2733

2834
The image installs a hash-locked, pinned Deep Agents Code release with NVIDIA provider support.
@@ -71,9 +77,9 @@ To enable Tavily, apply the maintained `tavily` policy preset so the sandbox may
7177

7278
```bash
7379
# Preview the endpoints the preset opens:
74-
nemoclaw <sandbox-name> policy-add tavily --dry-run
80+
nemo-deepagents <sandbox-name> policy-add tavily --dry-run
7581
# Apply it:
76-
nemoclaw <sandbox-name> policy-add tavily --yes
82+
nemo-deepagents <sandbox-name> policy-add tavily --yes
7783
```
7884

7985
The `tavily` preset only opens egress to `api.tavily.com:443`.
@@ -83,7 +89,7 @@ Because OpenShell attributes the harness's calls to the sandbox `python3` interp
8389
Remove the access again when it is no longer needed.
8490

8591
```bash
86-
nemoclaw <sandbox-name> policy-remove tavily --yes
92+
nemo-deepagents <sandbox-name> policy-remove tavily --yes
8793
```
8894

8995
### Optional Tracing (LangSmith)
@@ -95,13 +101,13 @@ Treat it as unsupported until NemoClaw ships a maintained `langsmith` preset.
95101

96102
## Troubleshooting
97103

98-
Use normal sandbox lifecycle commands.
104+
Use normal sandbox lifecycle commands through either `nemo-deepagents` or `nemoclaw`:
99105

100106
```bash
101-
nemoclaw <sandbox-name> status
102-
nemoclaw <sandbox-name> logs --follow
103-
nemoclaw <sandbox-name> rebuild
104-
nemoclaw <sandbox-name> snapshot create --name before-change
107+
nemo-deepagents <sandbox-name> status
108+
nemo-deepagents <sandbox-name> logs --follow
109+
nemo-deepagents <sandbox-name> rebuild
110+
nemo-deepagents <sandbox-name> snapshot create --name before-change
105111
```
106112

107113
`status` reports the selected harness as a terminal runtime and prints the interactive/headless command shape.

docs/reference/commands-nemohermes.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ nemohermes onboard [options]
103103
nemoclaw onboard --agent hermes [options]
104104
```
105105

106+
`--agent` accepts the canonical manifest names from `nemohermes agents list` plus common aliases.
107+
For example, `nemohermes` resolves to `hermes`, while `dcode`, `deepagents`, `deepagents-code`, and `langchain` resolve to `langchain-deepagents-code`.
108+
106109
#### `--resume` and `--fresh`
107110

108111
NemoClaw records onboarding progress so interrupted runs can continue.

docs/reference/commands.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ nemoclaw onboard --agent hermes [options]
144144

145145
</AgentOnly>
146146

147+
`--agent` accepts the canonical manifest names from `$$nemoclaw agents list` plus common aliases.
148+
For example, `nemohermes` resolves to `hermes`, while `dcode`, `deepagents`, `deepagents-code`, and `langchain` resolve to `langchain-deepagents-code`.
149+
147150
#### `--resume` and `--fresh`
148151

149152
NemoClaw records onboarding progress so interrupted runs can continue.

docs/reference/platform-support.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Pick the matching onboarding entry point for each agent.
6565
|-------|--------|---------|-------|
6666
| OpenClaw | Tested | Yes | Default agent runtime. Onboard with `$$nemoclaw onboard` (no `--agent` flag required). |
6767
| Hermes | Tested with limitations | No | First-class agent with dedicated CLI (`$$nemohermes`), Dockerfile, manifest, docs, and nightly E2E job coverage (`hermes-e2e` job in `.github/workflows/nightly-e2e.yaml` plus the `hermes-*-vitest` jobs in `e2e-vitest-scenarios.yaml`). Onboard with `$$nemohermes onboard` or pass `--agent hermes` to `$$nemoclaw onboard`. Unlocks the Hermes Provider inference route. Known structural gaps: model-provider compatibility registry is empty (backfilled after failures, see `nemoclaw-blueprint/model-specific-setup/hermes/README.md`); no Hermes-specific unit tests in `nemoclaw/src/`; macOS and WSL CI suites do not differentiate agents. Suitable for evaluation and the documented onboarding paths; production parity with OpenClaw is not yet asserted. |
68-
| LangChain Deep Agents Code | Experimental | No | Terminal-oriented coding harness (no in-sandbox gateway, no dashboard) built on the Deep Agents SDK; manifest at `agents/langchain-deepagents-code/manifest.yaml` with binary `dcode`. Onboard with `$$nemoclaw onboard --agent langchain-deepagents-code` and follow [the quickstart](../get-started/quickstart-langchain-deepagents-code). NemoClaw runs it as a managed harness: unmanaged sandbox/MCP/shell overrides are rejected and credential-bearing proxy URLs are dropped from persisted shell env. Inference routes through OpenShell's `inference.local` endpoint via Deep Agents Code's OpenAI-compatible provider. Live runtime acceptance, broader launch material, and terminal-agent diagnostics are tracked at open issue #4861. |
68+
| LangChain Deep Agents Code | Experimental | No | Terminal-oriented coding harness (no in-sandbox gateway, no dashboard) built on the Deep Agents SDK; manifest at `agents/langchain-deepagents-code/manifest.yaml` with binary `dcode`. Onboard with `$$nemo-deepagents onboard` or `$$nemoclaw onboard --agent langchain-deepagents-code`, and follow [the quickstart](../get-started/quickstart-langchain-deepagents-code). NemoClaw runs it as a managed harness: unmanaged sandbox/MCP/shell overrides are rejected and credential-bearing proxy URLs are dropped from persisted shell env. Inference routes through OpenShell's `inference.local` endpoint via Deep Agents Code's OpenAI-compatible provider. Live runtime acceptance, broader launch material, and terminal-agent diagnostics are tracked at open issue #4861. |
6969
{/* agent-status:end */}
7070

7171
## Platforms

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"license": "Apache-2.0",
77
"bin": {
88
"nemoclaw": "./bin/nemoclaw.js",
9-
"nemohermes": "./bin/nemohermes.js"
9+
"nemohermes": "./bin/nemohermes.js",
10+
"nemo-deepagents": "./bin/nemoclaw.js"
1011
},
1112
"oclif": {
1213
"bin": "nemoclaw",

scripts/install.sh

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ installer_version_for_display() {
107107
agent_display_name() {
108108
case "${1:-}" in
109109
hermes) printf "Hermes" ;;
110+
langchain-deepagents-code) printf "LangChain Deep Agents Code" ;;
110111
openclaw | "") printf "OpenClaw" ;;
111112
*)
112113
local first rest
@@ -117,6 +118,25 @@ agent_display_name() {
117118
esac
118119
}
119120

121+
canonical_agent_name() {
122+
local raw="${1:-}" normalized
123+
normalized="$(printf "%s" "$raw" | tr '[:upper:]_ ' '[:lower:]--' | sed -E 's/-+/-/g; s/^-//; s/-$//')"
124+
case "$normalized" in
125+
nemoclaw | nemo-claw | openclaw)
126+
printf "openclaw"
127+
;;
128+
nemohermes | nemo-hermes | hermes)
129+
printf "hermes"
130+
;;
131+
nemo-deepagents | nemo-deepagent | nemodeepagents | nemodeepagent | dcode | deepagent | deepagents | deep-agent | deep-agents | deepagentcode | deepagentscode | deepagent-code | deepagents-code | deep-agent-code | deep-agents-code | langchain | langchain-code | langchaindeepagent | langchaindeepagents | langchain-deepagent | langchain-deepagents | langchaindeepagentcode | langchaindeepagentscode | langchain-deepagent-code | langchain-deepagents-code | langchain-deep-agent | langchain-deep-agents | langchain-deep-agent-code | langchain-deep-agents-code)
132+
printf "langchain-deepagents-code"
133+
;;
134+
*)
135+
printf "%s" "$raw"
136+
;;
137+
esac
138+
}
139+
120140
# Resolve which Git ref to install from.
121141
# Priority: NEMOCLAW_INSTALL_TAG env var > lkg tag.
122142
resolve_release_tag() {
@@ -269,9 +289,14 @@ resolve_default_sandbox_name() {
269289
fi
270290

271291
local fallback="my-assistant"
272-
if [[ "${NEMOCLAW_AGENT:-}" == "hermes" ]]; then
273-
fallback="hermes"
274-
fi
292+
case "${NEMOCLAW_AGENT:-}" in
293+
hermes)
294+
fallback="hermes"
295+
;;
296+
langchain-deepagents-code)
297+
fallback="deepagents-code"
298+
;;
299+
esac
275300
printf "%s" "${sandbox_name:-$fallback}"
276301
}
277302

@@ -846,12 +871,21 @@ MIN_NODE_VERSION="22.16.0"
846871
MIN_NPM_MAJOR=10
847872

848873
# ── Agent branding — adapt user-visible names to the active agent ──
874+
if [[ -n "${NEMOCLAW_AGENT:-}" ]]; then
875+
NEMOCLAW_AGENT="$(canonical_agent_name "$NEMOCLAW_AGENT")"
876+
export NEMOCLAW_AGENT
877+
fi
849878
case "${NEMOCLAW_AGENT:-openclaw}" in
850879
hermes)
851880
_CLI_DISPLAY="NemoHermes"
852881
_AGENT_PRODUCT="Hermes"
853882
_CLI_BIN="nemohermes"
854883
;;
884+
langchain-deepagents-code)
885+
_CLI_DISPLAY="NemoDeepAgents"
886+
_AGENT_PRODUCT="LangChain Deep Agents Code"
887+
_CLI_BIN="nemo-deepagents"
888+
;;
855889
*)
856890
_CLI_DISPLAY="NemoClaw"
857891
_AGENT_PRODUCT="OpenClaw"
@@ -1536,8 +1570,8 @@ is_real_nemoclaw_cli() {
15361570
local expected_name="${2:-$_CLI_BIN}"
15371571
local version_output
15381572
version_output="$("$bin_path" --version 2>/dev/null)" || return 1
1539-
# Real CLI outputs: "nemoclaw v0.1.0" or "nemohermes v0.1.0"
1540-
# (or any semver, with optional pre-release/build metadata).
1573+
# Real CLI outputs: "nemoclaw v0.1.0", "nemohermes v0.1.0", or
1574+
# "nemo-deepagents v0.1.0" (or any semver, with optional pre-release/build metadata).
15411575
[[ "$version_output" =~ ^${expected_name}[[:space:]]+v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?([+][0-9A-Za-z.-]+)?$ ]]
15421576
}
15431577

src/lib/actions/update.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,32 @@ describe("runUpdateAction", () => {
6666
);
6767
});
6868

69+
it("--check renders NemoDeepAgents branding and installer guidance when the Deep Agents alias is active", async () => {
70+
const log = vi.fn();
71+
72+
const result = await runUpdateAction(
73+
{ check: true },
74+
{
75+
currentVersion: () => "0.1.0",
76+
env: { ...process.env, NEMOCLAW_AGENT: "dcode" },
77+
getLatestVersion: () => "0.2.0",
78+
isSourceCheckout: () => false,
79+
log,
80+
spawnSyncImpl: vi.fn(),
81+
},
82+
);
83+
84+
expect(result.status).toBe(0);
85+
expect(log).toHaveBeenCalledWith(
86+
expect.stringContaining("Current NemoDeepAgents version: 0.1.0"),
87+
);
88+
expect(log).toHaveBeenCalledWith(
89+
expect.stringContaining(
90+
"curl -fsSL https://www.nvidia.com/nemoclaw.sh | NEMOCLAW_AGENT=langchain-deepagents-code bash",
91+
),
92+
);
93+
});
94+
6995
it("does not run the installer for developer source checkouts", async () => {
7096
const error = vi.fn();
7197
const spawnSyncImpl = vi.fn();
@@ -226,6 +252,46 @@ describe("runUpdateAction", () => {
226252
expect(options?.env?.NEMOCLAW_INSTALL_TAG).toBeUndefined();
227253
});
228254

255+
it("preserves the canonical Deep Agents agent selection while sanitizing installer env", async () => {
256+
const spawnSyncImpl = vi.fn(
257+
() => ({ status: 0, stdout: "", stderr: "", signal: null }) as never,
258+
);
259+
const log = vi.fn();
260+
261+
await runUpdateAction(
262+
{ yes: true },
263+
{
264+
currentVersion: () => "0.1.0",
265+
env: {
266+
...process.env,
267+
BASH_ENV: "/tmp/review-bash-env",
268+
NEMOCLAW_AGENT: "langchain-deepagents-code",
269+
NEMOCLAW_INSTALL_REF: "refs/heads/not-maintained",
270+
},
271+
getLatestVersion: () => "0.2.0",
272+
isSourceCheckout: () => false,
273+
log,
274+
spawnSyncImpl,
275+
},
276+
);
277+
278+
const calls = spawnSyncImpl.mock.calls as unknown as Array<
279+
[string, readonly string[], { env?: NodeJS.ProcessEnv }]
280+
>;
281+
const options = calls[0]?.[2];
282+
expect(options?.env?.NEMOCLAW_AGENT).toBe("langchain-deepagents-code");
283+
expect(options?.env?.BASH_ENV).toBeUndefined();
284+
expect(options?.env?.NEMOCLAW_INSTALL_REF).toBeUndefined();
285+
expect(log).toHaveBeenCalledWith(
286+
expect.stringContaining("Running maintained NemoDeepAgents installer"),
287+
);
288+
expect(log).toHaveBeenCalledWith(
289+
expect.stringContaining(
290+
"Installer completed. Run `nemo-deepagents upgrade-sandboxes --check`",
291+
),
292+
);
293+
});
294+
229295
it("preserves the Hermes agent selection while sanitizing installer env", async () => {
230296
const spawnSyncImpl = vi.fn(
231297
() => ({ status: 0, stdout: "", stderr: "", signal: null }) as never,

0 commit comments

Comments
 (0)