Skip to content

Commit 865e3f9

Browse files
fix(dcode): apply the compatible-endpoint reasoning effort at runtime (#7971)
<!-- markdownlint-disable MD041 --> ## Summary A NemoClaw-managed Deep Agents Code sandbox recorded a compatible-endpoint reasoning effort in registry state but sent every model request without it, so the endpoint default applied instead. The managed image now bakes the recorded effort into a root-owned file, and the managed provider resolver supplies it as an `extra_body.reasoning_effort` request parameter. ## Related Issue Fixes #7938 ## Changes - `agents/langchain-deepagents-code/Dockerfile` declares `ARG NEMOCLAW_REASONING_EFFORT`, validates it as empty, `low`, `medium`, or `high` at build time, and writes it to root-owned `0444` `/usr/local/share/nemoclaw/dcode-reasoning-effort`. The staged-Dockerfile patcher already rewrote this ARG name for OpenClaw; with no matching declaration here the rewrite was a silent no-op. - `agents/langchain-deepagents-code/managed-dcode-runtime.py` adds `managed_reasoning_effort()`. It repeats the fail-closed shape of `managed_auto_approval_mode()` because both read image state that runtime must not trust: ownership, mode, exact size, `O_NOFOLLOW`, and a read-race check. An unsafe or unrecognized file returns `None`, which keeps the endpoint default. Direct-module cases in `test/langchain-deepagents-code-reasoning-effort.test.ts` pin the rejected shapes. - `agents/langchain-deepagents-code/patch-managed-deepagents-code.py` sets `extra_body.reasoning_effort` on the managed OpenAI adapter. The hardened resolver never consumes the mutable `config.toml` params table, so a generator-only change cannot reach the request. The same file adds the new function to the stale-helper guard, which now covers every managed capability rather than auto-approval alone. - `agents/langchain-deepagents-code/generate-config.ts` records the effort in the generated per-model params table. `extra_body` now merges the Ultra template argument and the reasoning effort into one table; an unset effort produces byte-identical output to before. - `scripts/check-dcode-profile-import-gate.sh` allows the new ARG name. The gate refuses any unlisted ARG, so the build fails without this entry. - Docs record the build-time behavior for Deep Agents Code and correct the model-capabilities page, which previously implied `inference set` could change the effort on a Deep Agents Code sandbox. ## 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 one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [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) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review <!-- Required for code and documentation changes after the changes and applicable validation are complete. Keep one review checkbox and one instance of each visible or hidden field. For Evidence, list changed documentation paths. For documentation-only changes, also state that the writing rules and documentation style were reviewed. For other results, explain why no documentation change is needed or why the review is blocked. For Agent, use a consistent product and surface name, such as Codex Desktop, Codex CLI, Claude Code, or Cursor. After committing all review changes, put `git rev-parse --short HEAD` and `git rev-parse --short HEAD:AGENTS.md` in the hidden metadata below. Rerun the review and refresh that metadata after any new commit. This receipt is advisory during the data-collection pilot. --> - [ ] Documentation writer subagent reviewed the completed changes - Result: `blocked` - Evidence: `docs/get-started/quickstart-langchain-deepagents-code.mdx`, `docs/inference/configure-model-capabilities.mdx`. The authoring host ran with subagents disabled, so no documentation writer subagent reviewed the change. `npm run docs` reports 0 errors, including the route check that rejected an earlier cross-variant link. - Agent: Claude Code <!-- docs-review-head-sha: 2a09f90 --> <!-- docs-review-agents-blob-sha: c052d60 --> ## DGX Station Hardware Evidence <!-- Required only when scripts/prepare-dgx-station-host.sh changes. Maintainers must review the linked evidence before approving or merging. This is human-reviewed evidence, not authenticated hardware provenance. Exceptional bypasses use existing repository governance and must be documented on the PR. --> - [ ] Tested on DGX Station - Tested commit: - Station profile/scenario: - Result: - Supporting evidence: ## Verification <!-- Check each applicable item only when supported by the requested evidence. Run targeted tests once per relevant change set and rerun after later edits or hook autofixes that can affect the tested behavior. Do not rerun hook-covered checks. --> - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: `npx vitest run --project integration test/langchain-deepagents-code-config.test.ts test/langchain-deepagents-code-reasoning-effort.test.ts test/langchain-deepagents-code-direct-module-patch.test.ts test/langchain-deepagents-code-nemotron-profile-plugin.test.ts test/langchain-deepagents-code-image.test.ts test/langchain-deepagents-code-auto-approval-image.test.ts test/langchain-deepagents-code-profile-build-gate.test.ts` — 7 files, 150 tests passed. `npm run typecheck:cli` reports 0 errors. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [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) --- <!-- 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: Tinson Lai <tinsonl@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added configurable reasoning-effort levels—low, medium, or high—for supported Deep Agents Code inference endpoints. * Leaving the setting unset preserves the endpoint default; invalid or unsafe values are safely ignored. * Changes require fresh onboarding with sandbox recreation. * **Documentation** * Clarified supported workflows and configuration behavior. * **Tests** * Added coverage for valid, unset, invalid, unsafe, and provider-specific settings. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Tinson Lai <tinsonl@nvidia.com> Co-authored-by: J. Yaunches <jyaunches@nvidia.com>
1 parent 0d5c876 commit 865e3f9

17 files changed

Lines changed: 397 additions & 33 deletions

agents/langchain-deepagents-code/Dockerfile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ ARG NEMOCLAW_UPSTREAM_PROVIDER=nvidia
117117
ARG NEMOCLAW_UPSTREAM_ENDPOINT_URL=
118118
ARG NEMOCLAW_INFERENCE_BASE_URL=https://inference.local/v1
119119
ARG NEMOCLAW_INFERENCE_API=openai-completions
120+
ARG NEMOCLAW_REASONING_EFFORT=
120121
ARG NEMOCLAW_TOOL_DISCLOSURE=progressive
121122
ARG NEMOCLAW_DCODE_AUTO_APPROVAL=disabled
122123
ARG NEMOCLAW_BUILD_ID=default
@@ -131,6 +132,10 @@ RUN case "$NEMOCLAW_TOOL_DISCLOSURE" in \
131132
&& case "$NEMOCLAW_DCODE_AUTO_APPROVAL" in \
132133
disabled|thread-opt-in) ;; \
133134
*) echo "ERROR: NEMOCLAW_DCODE_AUTO_APPROVAL must be disabled or thread-opt-in" >&2; exit 1 ;; \
135+
esac \
136+
&& case "$NEMOCLAW_REASONING_EFFORT" in \
137+
""|low|medium|high) ;; \
138+
*) echo "ERROR: NEMOCLAW_REASONING_EFFORT must be empty, low, medium, or high" >&2; exit 1 ;; \
134139
esac
135140

136141
# The launcher and startup script read these root-owned files instead of
@@ -143,8 +148,9 @@ RUN install -d -m 0755 /usr/local/share/nemoclaw \
143148
&& printf '%s\n' "$NEMOCLAW_PROXY_PORT" > /usr/local/share/nemoclaw/dcode-proxy-port \
144149
&& printf '%s\n' "$NEMOCLAW_INFERENCE_BASE_URL" > /usr/local/share/nemoclaw/dcode-inference-base-url \
145150
&& printf '%s\n' "$NEMOCLAW_DCODE_AUTO_APPROVAL" > /usr/local/share/nemoclaw/dcode-auto-approval \
146-
&& chown root:root /usr/local/share/nemoclaw/dcode-proxy-host /usr/local/share/nemoclaw/dcode-proxy-port /usr/local/share/nemoclaw/dcode-inference-base-url /usr/local/share/nemoclaw/dcode-auto-approval \
147-
&& chmod 0444 /usr/local/share/nemoclaw/dcode-proxy-host /usr/local/share/nemoclaw/dcode-proxy-port /usr/local/share/nemoclaw/dcode-inference-base-url /usr/local/share/nemoclaw/dcode-auto-approval \
151+
&& printf '%s\n' "$NEMOCLAW_REASONING_EFFORT" > /usr/local/share/nemoclaw/dcode-reasoning-effort \
152+
&& chown root:root /usr/local/share/nemoclaw/dcode-proxy-host /usr/local/share/nemoclaw/dcode-proxy-port /usr/local/share/nemoclaw/dcode-inference-base-url /usr/local/share/nemoclaw/dcode-auto-approval /usr/local/share/nemoclaw/dcode-reasoning-effort \
153+
&& chmod 0444 /usr/local/share/nemoclaw/dcode-proxy-host /usr/local/share/nemoclaw/dcode-proxy-port /usr/local/share/nemoclaw/dcode-inference-base-url /usr/local/share/nemoclaw/dcode-auto-approval /usr/local/share/nemoclaw/dcode-reasoning-effort \
148154
&& unset OTEL_EXPORTER_OTLP_TRACES_ENDPOINT \
149155
&& empty_prompt_log="$(mktemp)" \
150156
&& if timeout 10 /usr/local/bin/dcode -n "" >"$empty_prompt_log" 2>&1; then empty_prompt_status=0; else empty_prompt_status=$?; fi \
@@ -165,6 +171,7 @@ ENV HOME=/sandbox \
165171
NEMOCLAW_UPSTREAM_ENDPOINT_URL=${NEMOCLAW_UPSTREAM_ENDPOINT_URL} \
166172
NEMOCLAW_INFERENCE_BASE_URL=${NEMOCLAW_INFERENCE_BASE_URL} \
167173
NEMOCLAW_INFERENCE_API=${NEMOCLAW_INFERENCE_API} \
174+
NEMOCLAW_REASONING_EFFORT=${NEMOCLAW_REASONING_EFFORT} \
168175
NEMOCLAW_TOOL_DISCLOSURE=${NEMOCLAW_TOOL_DISCLOSURE} \
169176
NEMOCLAW_BUILD_ID=${NEMOCLAW_BUILD_ID} \
170177
DEEPAGENTS_CODE_NO_UPDATE_CHECK=1 \

agents/langchain-deepagents-code/generate-config.ts

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
1010
import { homedir } from "node:os";
1111
import { join } from "node:path";
1212

13+
type ReasoningEffort = "low" | "medium" | "high";
14+
1315
type Settings = {
1416
model: string;
1517
baseUrl: string;
1618
providerKey: string;
1719
upstreamProvider: string;
1820
upstreamEndpointUrl: string | null;
1921
inferenceApi: string;
22+
reasoningEffort: ReasoningEffort | null;
2023
};
2124

2225
type ManagedDeepAgentsProvider = "openai" | "openrouter";
@@ -63,9 +66,19 @@ function readSettings(env: NodeJS.ProcessEnv): Settings {
6366
env.NEMOCLAW_INFERENCE_API || "openai-completions",
6467
"NEMOCLAW_INFERENCE_API",
6568
),
69+
reasoningEffort: normalizeReasoningEffort(env.NEMOCLAW_REASONING_EFFORT),
6670
};
6771
}
6872

73+
function normalizeReasoningEffort(value: string | undefined): ReasoningEffort | null {
74+
if (value === undefined || value.trim() === "") return null;
75+
const text = value.trim();
76+
if (text !== "low" && text !== "medium" && text !== "high") {
77+
throw new Error("NEMOCLAW_REASONING_EFFORT must be low, medium, or high.");
78+
}
79+
return text;
80+
}
81+
6982
function readRequiredEnv(env: NodeJS.ProcessEnv, name: string): string {
7083
const value = env[name];
7184
if (!value) throw new Error(`${name} is required`);
@@ -165,26 +178,38 @@ function modelNameForManagedProvider(model: string): string {
165178
return trimmed;
166179
}
167180

168-
function openAiModelRequestParamLines(model: string): string[] {
181+
function openAiModelRequestParamLines(
182+
model: string,
183+
reasoningEffort: ReasoningEffort | null,
184+
): string[] {
169185
// Source boundary: NVIDIA's Ultra serving template owns the empty assistant
170186
// content behavior; this generator owns only the managed per-model request
171187
// parameters. Keep the exact invalid state, regression proof, and separate
172188
// removal conditions for this option and the dispatch guard in
173189
// dependency-review.md under "Managed Ultra compatibility workarounds."
174-
return NEMOTRON_ULTRA_MODEL_IDS.has(model)
175-
? [
176-
"",
177-
`[models.providers.openai.params.${tomlString(model)}]`,
178-
"# Nemotron Ultra coding-agent requests need nonempty content when tool calls and reasoning are combined.",
179-
"extra_body = { chat_template_kwargs = { force_nonempty_content = true } }",
180-
]
181-
: [];
190+
const isUltra = NEMOTRON_ULTRA_MODEL_IDS.has(model);
191+
const extraBodyEntries = [
192+
...(isUltra ? ["chat_template_kwargs = { force_nonempty_content = true }"] : []),
193+
...(reasoningEffort ? [`reasoning_effort = ${tomlString(reasoningEffort)}`] : []),
194+
];
195+
if (extraBodyEntries.length === 0) return [];
196+
return [
197+
"",
198+
`[models.providers.openai.params.${tomlString(model)}]`,
199+
...(isUltra
200+
? [
201+
"# Nemotron Ultra coding-agent requests need nonempty content when tool calls and reasoning are combined.",
202+
]
203+
: []),
204+
`extra_body = { ${extraBodyEntries.join(", ")} }`,
205+
];
182206
}
183207

184208
function providerConfigLines(
185209
provider: ManagedDeepAgentsProvider,
186210
model: string,
187211
baseUrl: string,
212+
reasoningEffort: ReasoningEffort | null,
188213
): string[] {
189214
return [
190215
`[models.providers.${provider}]`,
@@ -199,7 +224,7 @@ function providerConfigLines(
199224
"# NemoClaw-managed inference.local currently exposes Chat Completions.",
200225
"# Remove this override when that route supports OpenAI Responses API.",
201226
"use_responses_api = false",
202-
...openAiModelRequestParamLines(model),
227+
...openAiModelRequestParamLines(model, reasoningEffort),
203228
]
204229
: []),
205230
];
@@ -216,7 +241,7 @@ function buildConfig(settings: Settings): ManagedDeepAgentsConfig {
216241
"[models]",
217242
`default = ${tomlString(defaultModel)}`,
218243
"",
219-
...providerConfigLines(provider, model, settings.baseUrl),
244+
...providerConfigLines(provider, model, settings.baseUrl, settings.reasoningEffort),
220245
"",
221246
"[update]",
222247
"check = false",

agents/langchain-deepagents-code/managed-dcode-runtime.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@
4141
b"disabled\n": _AUTO_APPROVAL_DISABLED,
4242
b"thread-opt-in\n": _AUTO_APPROVAL_THREAD_OPT_IN,
4343
}
44+
_REASONING_EFFORT_FILE = Path(
45+
"/usr/local/share/nemoclaw/dcode-reasoning-effort"
46+
)
47+
_REASONING_EFFORT_CONTENTS: dict[bytes, str | None] = {
48+
b"\n": None,
49+
b"low\n": "low",
50+
b"medium\n": "medium",
51+
b"high\n": "high",
52+
}
4453
_MANAGED_FILE_OWNER_UID = 0
4554
_CREDENTIAL_NAME = re.compile(
4655
r"(?:^|[_-])(?:API_KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|PASS|CREDENTIAL)$",
@@ -1309,6 +1318,64 @@ def managed_auto_approval_enabled() -> bool:
13091318
return managed_auto_approval_mode() == _AUTO_APPROVAL_THREAD_OPT_IN
13101319

13111320

1321+
def _unset_reasoning_effort(reason: str) -> None:
1322+
if os.environ.get("NEMOCLAW_DEBUG") == "1":
1323+
print(
1324+
f"NemoClaw managed reasoning effort unset: {reason}",
1325+
file=sys.stderr,
1326+
)
1327+
return None
1328+
1329+
1330+
def managed_reasoning_effort() -> str | None:
1331+
"""Return the reasoning effort baked into the image, or None for the endpoint default."""
1332+
path = _REASONING_EFFORT_FILE
1333+
try:
1334+
if path.is_symlink():
1335+
return _unset_reasoning_effort("capability path is a symlink")
1336+
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0)
1337+
flags |= getattr(os, "O_NOFOLLOW", 0)
1338+
descriptor = os.open(path, flags)
1339+
except OSError:
1340+
return _unset_reasoning_effort("capability file is missing or unreadable")
1341+
1342+
try:
1343+
metadata = os.fstat(descriptor)
1344+
if (
1345+
not stat.S_ISREG(metadata.st_mode)
1346+
or metadata.st_uid != _MANAGED_FILE_OWNER_UID
1347+
or stat.S_IMODE(metadata.st_mode) != 0o444
1348+
or metadata.st_size not in {
1349+
len(content) for content in _REASONING_EFFORT_CONTENTS
1350+
}
1351+
):
1352+
return _unset_reasoning_effort("capability metadata is unsafe")
1353+
1354+
chunks: list[bytes] = []
1355+
remaining = metadata.st_size
1356+
while remaining:
1357+
chunk = os.read(descriptor, remaining)
1358+
if not chunk:
1359+
return _unset_reasoning_effort("capability file was truncated")
1360+
chunks.append(chunk)
1361+
remaining -= len(chunk)
1362+
if os.read(descriptor, 1):
1363+
return _unset_reasoning_effort("capability file changed while reading")
1364+
except OSError:
1365+
return _unset_reasoning_effort("capability file read failed")
1366+
finally:
1367+
try:
1368+
os.close(descriptor)
1369+
except OSError:
1370+
# Cleanup cannot weaken the endpoint-default capability result.
1371+
pass
1372+
1373+
raw = b"".join(chunks)
1374+
if raw not in _REASONING_EFFORT_CONTENTS:
1375+
return _unset_reasoning_effort("capability contents are invalid")
1376+
return _REASONING_EFFORT_CONTENTS[raw]
1377+
1378+
13121379
def managed_display_provider(adapter_provider: object) -> str:
13131380
"""Return the provider label to show for the managed inference adapter.
13141381

agents/langchain-deepagents-code/patch-managed-deepagents-code.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,10 @@ def _get_provider_kwargs(provider: str, *, model_name: str | None = None) -> dic
511511
"""Return only the NemoClaw-managed inference constructor contract."""
512512
del model_name
513513
from deepagents_code.model_config import ModelConfig, ModelConfigError
514-
from deepagents_code._nemoclaw_managed import managed_inference_base_url
514+
from deepagents_code._nemoclaw_managed import (
515+
managed_inference_base_url,
516+
managed_reasoning_effort,
517+
)
515518
516519
if provider not in {"openai", "openrouter"}:
517520
raise ModelConfigError(
@@ -527,6 +530,9 @@ def _get_provider_kwargs(provider: str, *, model_name: str | None = None) -> dic
527530
}
528531
if provider == "openai":
529532
kwargs["use_responses_api"] = False
533+
reasoning_effort = managed_reasoning_effort()
534+
if reasoning_effort is not None:
535+
kwargs["extra_body"] = {"reasoning_effort": reasoning_effort}
530536
return kwargs
531537
'''
532538

@@ -1735,9 +1741,10 @@ def main() -> None:
17351741
else ""
17361742
)
17371743
analytics_guard = 'os.environ["LANGGRAPH_CLI_NO_ANALYTICS"] = "1"'
1738-
auto_approval_guards = (
1744+
capability_guards = (
17391745
"def managed_auto_approval_mode() -> str:",
17401746
"def managed_auto_approval_enabled() -> bool:",
1747+
"def managed_reasoning_effort() -> str | None:",
17411748
)
17421749
if (
17431750
PATCH_MARKER not in helper_source
@@ -1752,7 +1759,7 @@ def main() -> None:
17521759
for line in helper_source.splitlines()
17531760
)
17541761
!= 1
1755-
for guard in auto_approval_guards
1762+
for guard in capability_guards
17561763
)
17571764
):
17581765
raise RuntimeError(

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ After the terminal smoke checks, onboarding runs `dcode --version` and compares
121121
Fresh and resumed onboarding exit nonzero instead of reporting the runtime ready when the installed version is too old, uses an incompatible version scheme, or cannot be verified.
122122
If the version check fails, review the reported version error and run `nemo-deepagents <sandbox-name> rebuild` before resuming onboarding.
123123
NemoClaw writes `/sandbox/.deepagents/config.toml` with an OpenAI-compatible provider pointed at `https://inference.local/v1`, uses a scoped placeholder API key for that managed route, and sets `use_responses_api = false` for Chat Completions compatibility.
124+
When onboarding records a reasoning effort on a `compatible-endpoint` route that uses `openai-completions`, the managed image bakes that value into a root-owned file and Deep Agents Code model requests carry it as an `extra_body.reasoning_effort` request parameter.
125+
Leave `NEMOCLAW_REASONING_EFFORT` unset to keep the endpoint's own default.
126+
Deep Agents Code has no runtime `inference set` path, so re-onboard the sandbox with `nemo-deepagents onboard --fresh --name <sandbox-name> --recreate-sandbox` to change the recorded effort.
124127
When you use NVIDIA Endpoints without selecting another model, new Deep Agents Code sandboxes default to `nvidia/nemotron-3-ultra-550b-a55b`.
125128
For this model, the managed image maps the OpenAI-compatible route to Deep Agents `0.7.0a6`'s native Nemotron 3 Ultra harness profile, including model-specific tool-calling, filesystem, retry, context, and final-answer safeguards.
126129
Rebuild existing Deep Agents Code sandboxes after upgrading to NemoClaw v0.0.76 or later so their image includes this profile.

docs/inference/configure-model-capabilities.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ Onboarding records the reasoning flag and the reasoning effort in the sandbox's
8686
A resumed onboard and `nemoclaw <sandbox-name> rebuild` both replay those recorded values, so exporting `NEMOCLAW_REASONING` or `NEMOCLAW_REASONING_EFFORT` before either command does not change them.
8787
When a resumed onboard on the `compatible-endpoint` provider sees an explicit `NEMOCLAW_REASONING` or `NEMOCLAW_REASONING_EFFORT` that disagrees with the recorded value, it reports the recorded value and the recreate command instead of applying the variable.
8888

89-
To change the reasoning effort on a running sandbox without a recreate, pass `--reasoning-effort` to `inference set`.
89+
Deep Agents Code applies the recorded reasoning effort from the sandbox image instead, and has no `inference set` path.
90+
Refer to [Quickstart with Deep Agents](/user-guide/deepagents/get-started/quickstart) for that agent's behavior.
91+
92+
To change the reasoning effort on a running OpenClaw sandbox without a recreate, pass `--reasoning-effort` to `inference set`.
9093

9194
```bash
9295
nemoclaw <sandbox-name> inference set --provider compatible-endpoint --model <model> --endpoint-url <recorded-url> --reasoning-effort high

scripts/check-dcode-profile-import-gate.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ for dockerfile in \
3939
agents/langchain-deepagents-code/Dockerfile; do
4040
while IFS= read -r arg_name; do
4141
case "${arg_name}" in
42-
BASE_IMAGE | NEMOCLAW_CORPORATE_CA_B64 | NEMOCLAW_MODEL | NEMOCLAW_INFERENCE_PROVIDER_ID | NEMOCLAW_PROVIDER_KEY | NEMOCLAW_UPSTREAM_PROVIDER | NEMOCLAW_UPSTREAM_ENDPOINT_URL | NEMOCLAW_INFERENCE_BASE_URL | NEMOCLAW_INFERENCE_API | NEMOCLAW_TOOL_DISCLOSURE | NEMOCLAW_DCODE_AUTO_APPROVAL | NEMOCLAW_BUILD_ID | NEMOCLAW_DARWIN_VM_COMPAT | NEMOCLAW_PROXY_HOST | NEMOCLAW_PROXY_PORT | PERL_VERSION | PERL_SHA256 | PERL_PACKAGE_REVISION) ;;
42+
BASE_IMAGE | NEMOCLAW_CORPORATE_CA_B64 | NEMOCLAW_MODEL | NEMOCLAW_INFERENCE_PROVIDER_ID | NEMOCLAW_PROVIDER_KEY | NEMOCLAW_UPSTREAM_PROVIDER | NEMOCLAW_UPSTREAM_ENDPOINT_URL | NEMOCLAW_INFERENCE_BASE_URL | NEMOCLAW_INFERENCE_API | NEMOCLAW_REASONING_EFFORT | NEMOCLAW_TOOL_DISCLOSURE | NEMOCLAW_DCODE_AUTO_APPROVAL | NEMOCLAW_BUILD_ID | NEMOCLAW_DARWIN_VM_COMPAT | NEMOCLAW_PROXY_HOST | NEMOCLAW_PROXY_PORT | PERL_VERSION | PERL_SHA256 | PERL_PACKAGE_REVISION) ;;
4343
*)
4444
echo "ERROR: plain-progress build refuses unreviewed ARG ${arg_name} in ${dockerfile}" >&2
4545
exit 1

src/lib/onboard/managed-startup-agent-environment.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ function dcodeProfile(): ManagedStartupProfile {
219219
contextWindow: null,
220220
maxTokens: null,
221221
reasoning: null,
222-
reasoningEffort: null,
222+
reasoningEffort: "high",
223223
},
224224
corporateCa: { bundleSha256: CA_SHA256 },
225225
};
@@ -526,6 +526,7 @@ describe("managed startup agent environment", () => {
526526
NEMOCLAW_INFERENCE_BASE_URL: "https://inference.local/v1",
527527
NEMOCLAW_INFERENCE_PROVIDER_ID: "inference",
528528
NEMOCLAW_MODEL: "openai/gpt-5.4",
529+
NEMOCLAW_REASONING_EFFORT: "high",
529530
NEMOCLAW_TOOL_DISCLOSURE: "progressive",
530531
NEMOCLAW_UPSTREAM_ENDPOINT_URL: "https://openrouter.ai/api/v1",
531532
NEMOCLAW_UPSTREAM_PROVIDER: "openrouter",
@@ -536,6 +537,7 @@ describe("managed startup agent environment", () => {
536537
});
537538
const expectedDcodeRuntime = { ...result.configurationEnvironment };
538539
delete expectedDcodeRuntime.NEMOCLAW_INFERENCE_BASE_URL;
540+
delete expectedDcodeRuntime.NEMOCLAW_REASONING_EFFORT;
539541
for (const name of [
540542
"HTTP_PROXY",
541543
"HTTPS_PROXY",
@@ -563,6 +565,7 @@ describe("managed startup agent environment", () => {
563565
expect(result.runtimeEnvironment).not.toHaveProperty("HTTP_PROXY");
564566
expect(result.runtimeEnvironment).not.toHaveProperty("HTTPS_PROXY");
565567
expect(result.runtimeEnvironment).not.toHaveProperty("NEMOCLAW_INFERENCE_BASE_URL");
568+
expect(result.runtimeEnvironment).not.toHaveProperty("NEMOCLAW_REASONING_EFFORT");
566569

567570
expect(result.materials).toEqual([
568571
{
@@ -606,6 +609,15 @@ describe("managed startup agent environment", () => {
606609
group: "root",
607610
mode: 0o444,
608611
},
612+
{
613+
kind: "root-owned-file",
614+
legacyInput: "NEMOCLAW_REASONING_EFFORT",
615+
path: "/usr/local/share/nemoclaw/dcode-reasoning-effort",
616+
contents: "high\n",
617+
owner: "root",
618+
group: "root",
619+
mode: 0o444,
620+
},
609621
]);
610622
expect(result.actions).toEqual([
611623
{

src/lib/onboard/managed-startup-onboard-profile.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ describe("buildManagedStartupOnboardProfile", () => {
295295
contextWindow: null,
296296
maxTokens: null,
297297
reasoning: null,
298-
reasoningEffort: null,
298+
reasoningEffort: "default",
299299
},
300300
});
301301
});

src/lib/onboard/managed-startup-profile-builder.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ describe("buildManagedStartupProfile", () => {
398398
NEMOCLAW_PROXY_HOST: "10.200.0.1",
399399
NEMOCLAW_PROXY_PORT: "3128",
400400
NEMOCLAW_OBSERVABILITY: "1",
401+
NEMOCLAW_REASONING_EFFORT: "high",
401402
},
402403
}),
403404
);
@@ -434,7 +435,7 @@ describe("buildManagedStartupProfile", () => {
434435
contextWindow: null,
435436
maxTokens: null,
436437
reasoning: null,
437-
reasoningEffort: null,
438+
reasoningEffort: "high",
438439
},
439440
});
440441
expect(decodeManagedStartupProfile(built.encodedProfile)).toEqual(built.profile);

0 commit comments

Comments
 (0)