Skip to content

fix(models-config): let config baseUrl/apiKey override agent models.json in merge mode#37331

Closed
maweibin wants to merge 2 commits intoopenclaw:mainfrom
maweibin:fix/37309-models-json-config-baseurl-wins
Closed

fix(models-config): let config baseUrl/apiKey override agent models.json in merge mode#37331
maweibin wants to merge 2 commits intoopenclaw:mainfrom
maweibin:fix/37309-models-json-config-baseurl-wins

Conversation

@maweibin
Copy link
Copy Markdown
Contributor

@maweibin maweibin commented Mar 6, 2026

Fixes #37309

Problem

In models.mode: "merge", updating baseUrl (or apiKey) in openclaw.json and restarting the gateway had no effect: the agent kept using the values stored in .openclaw/agent/.../models.json. Users had to manually edit the hidden models.json to correct a wrong URL.

Cause

mergeWithExistingProviderSecrets always preserved non-empty apiKey/baseUrl from the existing agent models.json, overwriting the values coming from config, so config was never able to override once agent state existed.

Solution

In merge mode, only preserve agent apiKey/baseUrl when config does not provide a non-empty value. When config provides a non-empty baseUrl or apiKey, config wins. Thus:

  • Correcting openclaw.json and restarting takes effect.
  • When config omits or leaves these fields empty, existing agent values are still preserved.

Changes

  • src/agents/models-config.ts: In mergeWithExistingProviderSecrets, preserve existing apiKey/baseUrl only when the corresponding value from config is missing or empty.
  • src/agents/models-config.fills-missing-provider-apikey-from-env-var.test.ts: Renamed and updated the test that had expected agent-to-win; added a test that agent values are preserved when config provides empty strings.
  • src/config/schema.help.ts: Updated models.mode help text to describe the new merge behavior.

Testing

  • pnpm test -- src/agents/models-config --run (71 tests) passes.

@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Mar 6, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR correctly fixes issue #37309 by inverting the precedence in merge mode so that config values take priority when non-empty.

The fix:

  • mergeWithExistingProviderSecrets now checks whether the incoming config provides non-empty apiKey/baseUrl before deciding whether to preserve the agent state value
  • Config values win when explicitly set to non-empty strings, enabling config changes to take effect on restart
  • Agent values are only preserved when config omits the field or provides an empty string, maintaining backward compatibility

Testing:

Documentation:

  • Help text updated to clearly explain the new merge behavior and the precedence rules

The change is minimal, surgical, and safe to merge.

Confidence Score: 5/5

  • This PR is safe to merge; it's a targeted behavioral fix with no risk of regressions to unrelated code paths.
  • The change is minimal and surgical — two additional boolean guards in a single private function. Both the bug-fix case (config wins) and the backward-compatibility case (agent preserved when config empty) are covered by explicit tests. The logic cleanly captures "config provides a non-empty value" and the merge mode behavior is properly documented. All 71 tests pass.
  • No files require special attention.

Last reviewed commit: 25bbfcc

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25bbfcc801

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +164 to +168
const configHasApiKey =
typeof (newEntry as { apiKey?: string }).apiKey === "string" &&
(newEntry as { apiKey?: string }).apiKey !== "";
const configHasBaseUrl =
typeof (newEntry as { baseUrl?: string }).baseUrl === "string" &&
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Distinguish implicit providers from config overrides

In merge mode this check treats any non-empty newEntry.apiKey/baseUrl as a config override, but newEntry is built from both explicit config and implicitly discovered providers (resolveProvidersForModelsJson merges them first). That means providers discovered from env/profile now overwrite existing models.json secrets/endpoints even when the user omitted that provider in openclaw.json, which regresses the documented "config omits => preserve existing" behavior and can reset persisted custom endpoints/tokens on restart.

Useful? React with 👍 / 👎.

@maweibin
Copy link
Copy Markdown
Contributor Author

maweibin commented Mar 6, 2026

@gumadeiras can help me review this pr,thanks

@maweibin maweibin changed the title Fix/37309 models json config baseurl wins fix(models-config): let config baseUrl/apiKey override agent models.json in merge mode Mar 6, 2026
@openclaw-barnacle
Copy link
Copy Markdown

Closing this PR because the author has more than 10 active PRs in this repo. Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.

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

Labels

agents Agent runtime and tooling r: too-many-prs size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Cannot update vLLM base URL; agent caches old config in hidden models.json

2 participants