Skip to content

[Bug]: Agent-level models.json apiKey not overriding main config #27243

@songchenghao

Description

@songchenghao

Summary

Bug Report: Agent-level models.json apiKey not overriding main config

Environment

  • OpenClaw Version: (installed globally via npm)
  • Node Version: v24.13.0
  • Platform: Linux (deployed on server 10.10.164.9)

Description

When using agent-level models.json files to customize provider configurations (specifically apiKey and baseUrl), the values are not being applied correctly. The model name is correctly overridden, but the apiKey and baseUrl from the main openclaw.json configuration take precedence instead of the agent-specific values.

Steps to Reproduce

  1. Create an agent-specific models.json file at:

    ~/.openclaw/agents/{agentId}/agent/models.json
    

    With content:

    {
      "providers": {
        "user-custom": {
          "baseUrl": "https://custom-api.example.com/",
          "apiKey": "agent_specific_key_12345",
          "models": [
            {
              "id": "claude-4-sonnet",
              "name": "Claude 4 Sonnet"
            }
          ]
        }
      }
    }
  2. In main ~/.openclaw/openclaw.json, configure the agent:

    {
      "agents": {
        "list": [
          {
            "id": "test-agent",
            "model": "user-custom/claude-4-sonnet"
          }
        ]
      },
      "models": {
        "providers": {
          "user-custom": {
            "baseUrl": "https://main-api.example.com/",
            "apiKey": "main_config_key_67890",
            "models": []
          }
        }
      }
    }
  3. Start a new session with the agent and observe which API key is used

Expected Behavior

The agent should use:

  • ✅ Model name: user-custom/claude-4-sonnet (from agent models.json)
  • ✅ API Key: agent_specific_key_12345 (from agent models.json)
  • ✅ Base URL: https://custom-api.example.com/ (from agent models.json)

Actual Behavior

The agent uses:

  • ✅ Model name: user-custom/claude-4-sonnet (correctly from agent models.json)
  • ❌ API Key: main_config_key_67890 (incorrectly from main config)
  • ❌ Base URL: https://main-api.example.com/ (incorrectly from main config)

Root Cause Analysis

After examining the source code in dist/image-D9rvznlL.js, the issue is in the mergeProviderModels function (lines 17-42):

function mergeProviderModels(implicit, explicit) {
    const implicitModels = Array.isArray(implicit.models) ? implicit.models : [];
    const explicitModels = Array.isArray(explicit.models) ? explicit.models : [];

    if (implicitModels.length === 0) return {
        ...implicit,
        ...explicit
    };

    // ... model merging logic ...

    return {
        ...implicit,    // agent models.json
        ...explicit,    // main config - THIS OVERWRITES implicit!
        models: mergedModels
    };
}

Problem: The spread operator order {...implicit, ...explicit} causes the explicit (main config) properties to overwrite the implicit (agent models.json) properties, including apiKey and baseUrl.

Expected behavior: Agent-level configuration should have higher priority than main config for per-agent customization.

Suggested Fix

Change the spread operator order in the return statement:

return {
    ...explicit,    // main config as defaults
    ...implicit,    // agent config overrides
    models: mergedModels
};

Or, to be more explicit and avoid unintended overwrites:

return {
    baseUrl: implicit.baseUrl ?? explicit.baseUrl,
    apiKey: implicit.apiKey ?? explicit.apiKey,
    // ... other properties with explicit precedence
    models: mergedModels
};

Workaround

Currently, the only workaround is to define separate providers for each agent directly in the main openclaw.json:

{
  "models": {
    "providers": {
      "user-agent1": {
        "apiKey": "key_for_agent1",
        "models": [...]
      },
      "user-agent2": {
        "apiKey": "key_for_agent2",
        "models": [...]
      }
    }
  }
}

However, this defeats the purpose of agent-level models.json files and makes multi-agent configuration management difficult.

Impact

This bug affects:

  • Multi-agent setups where different agents need different API keys
  • Per-agent customization of baseUrl (e.g., using different API gateways)
  • Any scenario requiring agent-specific provider configuration

Additional Context

  • The models array merging works correctly (models are properly combined)
  • Only provider properties like apiKey, baseUrl, etc. are affected
  • The agent-level models.json file is being loaded (evidenced by model names working)
  • The configuration merging logic appears to have the precedence backwards

Steps to reproduce

above

Expected behavior

above

Actual behavior

above

OpenClaw version

2026.2.9

Operating system

linux

Install method

npm global

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions