Skip to content

fix(rebuild): keep the fresh agent model routing on config restore (#7011) - #7066

Closed
yanyunl1991 wants to merge 1 commit into
mainfrom
fix/7011-agents-routing-fresh-on-rebuild
Closed

fix(rebuild): keep the fresh agent model routing on config restore (#7011)#7066
yanyunl1991 wants to merge 1 commit into
mainfrom
fix/7011-agents-routing-fresh-on-rebuild

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

After switching the inference provider/model (e.g. nemoclaw onboard → NVIDIA Endpoints), the host route and nemoclaw inference get show the new model, but the OpenClaw agent inside the sandbox keeps routing to the previous model — and a rebuild does not fix it.

Root cause: the rebuild config-restore merge (mergeOpenClawRestoredConfig) treats the whole agents section as durable (restored from the pre-rebuild backup). So agents.defaults.model.primary — the ref the agent/TUI routes on — is reverted to the backed-up (pre-switch) model, overriding the fresh rebuild's new routing. This is inconsistent with the models section, where the fresh rebuild already owns the routing identity while the backup restores user tuning (#5202).

Fix

Add mergeOpenClawAgents: the backup still restores durable agent config (per-agent settings, thinkingDefault / timeoutSeconds / compaction, …), but the fresh rebuild owns the model routingagents.defaults.model and each agent-list entry's model ref.

Reproduced and fixed end-to-end (DGX Spark, build provider, super→ultra)

The bug is provider/model-agnostic (any switch + rebuild reverts), so it does not require the reporter's DGX Station / DeepSeek setup.

Stage Host inference get Sandbox openclaw.json primary
onboard-switch super→ultra ultra super (reverted)
rebuild --yes (before fix) ultra super (persists)
rebuild --yes (with this fix) ultra ultra

Durable agent tuning (thinkingDefault=off) is preserved across the rebuild. Also verified at the merge level directly.

Unit test covers the fresh-routing / durable-tuning split; the existing #5202 restore tests still pass.

Fixes #7011.

Signed-off-by: Yanyun Liao yanyunl@nvidia.com

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Restored configuration now preserves the current agent model and provider routing.
    • Durable agent settings, such as thinking defaults and timeouts, continue to be restored from backups.
    • Prevented stale per-agent model references from returning during configuration restore.
    • Preserved unrelated MCP server settings during restoration.

…7011)

After switching the inference provider/model (e.g. via `nemoclaw onboard`), the
host route and `inference get` show the new model, but the OpenClaw agent inside
the sandbox kept routing to the previous one, and a rebuild did not fix it.

The rebuild config-restore merge treats the whole `agents` section as durable
(restored from the pre-rebuild backup), so `agents.defaults.model.primary` -- the
ref the agent/TUI routes on -- reverted to the backed-up (pre-switch) model. This
is inconsistent with the `models` section, where the fresh rebuild already owns
the routing identity while the backup restores user tuning.

Add `mergeOpenClawAgents`: the backup still restores durable agent config
(per-agent settings, thinkingDefault / timeoutSeconds / compaction, etc.), but
the fresh rebuild owns the model routing -- `agents.defaults.model` and each
agent-list entry's `model` ref.

Reproduced and fixed end-to-end on a DGX Spark (build provider, super->ultra):
before, `inference get` showed ultra while the sandbox openclaw.json primary
stayed super across a rebuild; after, the rebuild keeps primary=ultra and the
durable agent tuning is preserved. The bug is provider/model-agnostic (any
switch + rebuild reverts), so it does not require the reporter's DGX Station /
DeepSeek setup. Unit test covers the fresh-routing / durable-tuning split;
existing #5202 restore tests still pass.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@github-code-quality

github-code-quality Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the fix/7011-agents-rout... branch remains at 80%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 94b5e46 fix/7011-agents-rout... 13237ad +/-
src/lib/state/o...config-merge.ts 96% 97% +1%
src/lib/inference/local.ts 80% 82% +2%
src/lib/inferen...er-lifecycle.ts 65% 71% +6%
src/lib/inferen...lama/process.ts 50% 100% +50%

Updated July 17, 2026 02:43 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Selective restore now keeps fresh agent model routing while restoring durable agent tuning and unrelated MCP settings. Per-agent model references are reconciled by agent ID, preventing stale backup routing from returning.

Changes

Agent routing restore

Layer / File(s) Summary
Agent merge ownership
src/lib/state/openclaw-config-merge.ts
Documents routing ownership and merges agent settings while retaining fresh default and per-agent model references.
Restore integration and validation
src/lib/state/openclaw-config-merge.ts, src/lib/state/openclaw-config-merge.test.ts
Wires agent reconciliation into selective restore and tests durable tuning, routing ownership, stale-reference removal, and MCP preservation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BackupConfig
  participant CurrentConfig
  participant mergeOpenClawAgents
  participant RestoredConfig
  BackupConfig->>mergeOpenClawAgents: durable agent settings
  CurrentConfig->>mergeOpenClawAgents: fresh model routing
  mergeOpenClawAgents->>RestoredConfig: reconciled agents configuration
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#7063: Updates the same restore merge path to preserve fresh agent model routing after provider changes.

Suggested labels: feature, integration: dcode

Suggested reviewers: apurvvkumaria

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving fresh agent model routing during config restore.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/7011-agents-routing-fresh-on-rebuild

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with 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.

Inline comments:
In `@src/lib/state/openclaw-config-merge.ts`:
- Around line 395-427: Update mergeOpenClawAgents in
src/lib/state/openclaw-config-merge.ts (lines 395-427) so agents.list is
reconciled as an ID-based union that retains fresh-only agents, and make fresh
omission of defaults.model authoritative by removing any backup value. Add
coverage in src/lib/state/openclaw-config-merge.test.ts (lines 246-294) for a
fresh-only agent and a fresh configuration that omits defaults.model.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d8ae7023-ea71-4a5d-b25d-a6224613a41d

📥 Commits

Reviewing files that changed from the base of the PR and between 94b5e46 and 13237ad.

📒 Files selected for processing (2)
  • src/lib/state/openclaw-config-merge.test.ts
  • src/lib/state/openclaw-config-merge.ts

Comment on lines +395 to +427
function mergeOpenClawAgents(backupAgents: unknown, currentAgents: unknown): unknown {
if (!isPlainObject(currentAgents)) return cloneJson(backupAgents ?? currentAgents);
const backup = isPlainObject(backupAgents) ? backupAgents : {};
const merged = mergeJsonObjects(currentAgents, backup);

// Fresh rebuild owns agents.defaults.model (the routing block).
if (isPlainObject(currentAgents.defaults) && "model" in currentAgents.defaults) {
const mergedDefaults = isPlainObject(merged.defaults)
? merged.defaults
: ((merged.defaults = {}) as Record<string, unknown>);
mergedDefaults.model = cloneJson(currentAgents.defaults.model);
}

// Fresh rebuild owns each agent-list entry's `model` routing ref (by id). An
// agent that the fresh config routes via defaults (no `model` key) must not
// resurrect a stale per-agent ref from the backup.
if (Array.isArray(merged.list) && Array.isArray(currentAgents.list)) {
const freshById = new Map<string, Record<string, unknown>>();
for (const entry of currentAgents.list) {
const id = agentEntryId(entry);
if (id && isPlainObject(entry) && !freshById.has(id)) freshById.set(id, entry);
}
merged.list = merged.list.map((entry) => {
if (!isPlainObject(entry)) return entry;
const id = agentEntryId(entry);
const fresh = id ? freshById.get(id) : undefined;
if (!fresh) return entry;
const next: Record<string, unknown> = { ...entry };
if ("model" in fresh) next.model = cloneJson(fresh.model);
else delete next.model;
return next;
});
}

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Complete fresh ownership of the agent configuration.

The backup overlay replaces the fresh list wholesale and only preserves defaults.model when fresh explicitly provides it. This can drop newly rebuilt agents or resurrect stale default routing.

  • src/lib/state/openclaw-config-merge.ts#L395-L427: reconcile agents.list as an ID-based union and make fresh absence of defaults.model authoritative.
  • src/lib/state/openclaw-config-merge.test.ts#L246-L294: cover a fresh-only agent and a fresh config that intentionally omits defaults.model.
📍 Affects 2 files
  • src/lib/state/openclaw-config-merge.ts#L395-L427 (this comment)
  • src/lib/state/openclaw-config-merge.test.ts#L246-L294
🤖 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 `@src/lib/state/openclaw-config-merge.ts` around lines 395 - 427, Update
mergeOpenClawAgents in src/lib/state/openclaw-config-merge.ts (lines 395-427) so
agents.list is reconciled as an ID-based union that retains fresh-only agents,
and make fresh omission of defaults.model authoritative by removing any backup
value. Add coverage in src/lib/state/openclaw-config-merge.test.ts (lines
246-294) for a fresh-only agent and a fresh configuration that omits
defaults.model.

Source: Path instructions

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / high confidence
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions
Status: Canonical ledger: 0 blocker(s), 1 warning(s), 0 suggestion(s).

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 fewer warning, the same number of suggestions.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: onboard-repair, onboard-resume

2 optional E2E recommendations
  • openclaw-inference-switch
  • rebuild-openclaw
1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Cover explicit fresh per-agent model routing

  • Location: src/lib/state/openclaw-config-merge.ts:422
  • Category: tests
  • Problem: The new test covers only the branch that deletes a stale backup `model` when the fresh matching agent has no model key. It does not exercise the adjacent branch that assigns an explicit fresh per-agent `model`, so a regression that lets the stale backup model win for agents with an explicit fresh route would not be detected.
  • Impact: A provider/model switch that generates an explicit per-agent model reference could silently retain the old backup route, reproducing the routing-integrity failure this change is intended to prevent.
  • Recommendation: Add a merge test with matching agent IDs, distinct backup and fresh explicit per-agent model values, and a separate durable per-agent setting; assert the fresh model wins and the durable setting remains restored.
  • Verification: Inspect `mergeOpenClawAgents` at lines 420-423 and the new test at `openclaw-config-merge.test.ts:246-295`: only the `else delete next.model` path is exercised.
  • Test coverage: A Vitest fixture where backup and fresh `agents.list` entries share an ID but specify different explicit `model` values; assert the merged entry uses the fresh value while retaining a backup-owned per-agent tuning field.
  • Evidence: `mergeOpenClawAgents` assigns `next.model = cloneJson(fresh.model)` when a matched fresh entry explicitly has `model` (`src/lib/state/openclaw-config-merge.ts:422`). The added test makes the fresh `main` entry omit `model` and asserts only that the stale field is absent (`src/lib/state/openclaw-config-merge.test.ts:266-289`).

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@yanyunl1991

Copy link
Copy Markdown
Contributor Author

Closing in favor of #7063 (same diagnosis, tighter scoping that re-owns exactly the switch-set routing refs). Added the real-hardware E2E reproduction there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DGX Station][Inference] OpenClaw agent routes to previous model after switching provider from vllm-local to NVIDIA Endpoints

1 participant