Bug type
Behavior bug (incorrect output/state without crash)
Summary
The image tool throws Unknown model: <custom-provider>/<model-id> when imageModel is configured with a custom provider defined in models.json, because the tool internally uses @mariozechner/pi-coding-agent's ModelRegistry.find() which does not properly load custom providers from models.json.
Steps to reproduce
- Configure a custom OpenAI-compatible proxy provider in
openclaw.json under models.providers with baseUrl, apiKey, api, and models array.
- Set
agents.defaults.imageModel to custom-provider/model-id (where custom-provider is not a built-in pi-ai provider).
- Send an image to the agent (e.g., via Feishu or other channel).
- The
image tool is invoked and fails with Unknown model: custom-provider/model-id.
Expected behavior
The image tool should resolve custom providers from models.json the same way the main runner does, allowing imageModel to point to models on custom providers.
Observed behavior
The image tool fails with Unknown model error. Two specific root causes identified:
Root Cause 1: Validation failure in models.json blocks all custom model loading
If ANY provider in models.json has a models array but no apiKey (e.g., a provider auto-generated by ensureOpenClawModelsJson that uses OAuth-only auth), ModelRegistry.validateConfig throws, causing loadCustomModels to return an error result. This makes the ENTIRE custom models + overrides loading fail — including provider-level baseUrl overrides for OTHER built-in providers.
// ModelRegistry.validateConfig throws:
// "Provider xxx: apiKey is required when defining custom models."
// → loadCustomModels returns emptyCustomModelsResult({ error })
// → overrides Map is empty
// → loadBuiltInModels doesn't apply baseUrl overrides from models.json
Root Cause 2: Custom providers not in built-in catalog are invisible to image tool
Even without the validation error, providers that don't exist in pi-ai's built-in MODELS catalog are not found by registry.find(). The mergeCustomModels method does add them to this.models, but only when loadCustomModels succeeds without error. The main runner resolves models through a different path that handles custom providers correctly.
OpenClaw version
2026.4.11
Operating system
Linux (Ubuntu, kernel 6.8.0-65-generic, x64)
Model
custom-proxy/zai-org/glm-5.1 (primary, works in main chat)
custom-proxy/zai-org/glm-5v-turbo (imageModel, fails in image tool)
Provider / routing chain
openclaw -> custom OpenAI-compatible proxy -> upstream model provider
Additional provider/model setup details
Custom provider is configured in openclaw.json under models.providers with baseUrl, apiKey: "...", api: "openai-completions", and a models array containing the vision model with input: ["text", "image"]. The same custom provider works correctly for the primary text model in main chat. Only the image tool fails because it uses PiCodingAgent.ModelRegistry.find() which has limited custom provider support.
Logs, screenshots, and evidence
Error: Unknown model: custom-proxy/zai-org/glm-5v-turbo
Source: image-CDit-npy.js line 24:
const model = modelRegistry.find(resolvedRef.provider, resolvedRef.model);
if (!model) throw new Error(`Unknown model: ${resolvedRef.provider}/${resolvedRef.model}`);
When attempting to use a built-in provider name (e.g., zai/glm-5v-turbo) as imageModel with a baseUrl override in models.json for the zai provider, the override is not applied because loadCustomModels fails due to an unrelated validation error in another provider (see Root Cause 1). The model resolves with the built-in baseUrl instead of the override, resulting in a 401 error.
Impact and severity
- Affected: Users with custom proxy providers (OpenAI-compatible) who want to use a vision model via the
image tool
- Severity: Medium (blocks image tool for custom providers, workaround exists)
- Frequency: Always (deterministic, every image tool invocation fails)
- Consequence: Images cannot be analyzed using dedicated vision models; must fall back to primary model via
read tool, which may have inferior vision capabilities
Additional information
Workaround: Images can be analyzed by using the read tool to send the image content to the primary text model, which resolves custom providers through its own model resolution path. The image tool specifically cannot use custom providers.
Suggested fixes:
- Make
loadCustomModels more resilient — a validation error for one provider should not prevent loading other providers and overrides.
- Ensure
ensureOpenClawModelsJson does not generate providers with models arrays but no apiKey when the provider uses OAuth.
- Consider having the
image tool use the same model resolution path as the main runner, which correctly handles custom providers.
Bug type
Behavior bug (incorrect output/state without crash)
Summary
The
imagetool throwsUnknown model: <custom-provider>/<model-id>whenimageModelis configured with a custom provider defined inmodels.json, because the tool internally uses@mariozechner/pi-coding-agent'sModelRegistry.find()which does not properly load custom providers frommodels.json.Steps to reproduce
openclaw.jsonundermodels.providerswithbaseUrl,apiKey,api, andmodelsarray.agents.defaults.imageModeltocustom-provider/model-id(wherecustom-provideris not a built-in pi-ai provider).imagetool is invoked and fails withUnknown model: custom-provider/model-id.Expected behavior
The
imagetool should resolve custom providers frommodels.jsonthe same way the main runner does, allowingimageModelto point to models on custom providers.Observed behavior
The
imagetool fails withUnknown modelerror. Two specific root causes identified:Root Cause 1: Validation failure in models.json blocks all custom model loading
If ANY provider in
models.jsonhas amodelsarray but noapiKey(e.g., a provider auto-generated byensureOpenClawModelsJsonthat uses OAuth-only auth),ModelRegistry.validateConfigthrows, causingloadCustomModelsto return an error result. This makes the ENTIRE custom models + overrides loading fail — including provider-levelbaseUrloverrides for OTHER built-in providers.Root Cause 2: Custom providers not in built-in catalog are invisible to image tool
Even without the validation error, providers that don't exist in pi-ai's built-in
MODELScatalog are not found byregistry.find(). ThemergeCustomModelsmethod does add them tothis.models, but only whenloadCustomModelssucceeds without error. The main runner resolves models through a different path that handles custom providers correctly.OpenClaw version
2026.4.11
Operating system
Linux (Ubuntu, kernel 6.8.0-65-generic, x64)
Model
custom-proxy/zai-org/glm-5.1 (primary, works in main chat)
custom-proxy/zai-org/glm-5v-turbo (imageModel, fails in image tool)
Provider / routing chain
openclaw -> custom OpenAI-compatible proxy -> upstream model provider
Additional provider/model setup details
Custom provider is configured in
openclaw.jsonundermodels.providerswithbaseUrl,apiKey: "...",api: "openai-completions", and amodelsarray containing the vision model withinput: ["text", "image"]. The same custom provider works correctly for the primary text model in main chat. Only theimagetool fails because it usesPiCodingAgent.ModelRegistry.find()which has limited custom provider support.Logs, screenshots, and evidence
Source:
image-CDit-npy.jsline 24:When attempting to use a built-in provider name (e.g.,
zai/glm-5v-turbo) asimageModelwith abaseUrloverride inmodels.jsonfor thezaiprovider, the override is not applied becauseloadCustomModelsfails due to an unrelated validation error in another provider (see Root Cause 1). The model resolves with the built-inbaseUrlinstead of the override, resulting in a 401 error.Impact and severity
imagetoolreadtool, which may have inferior vision capabilitiesAdditional information
Workaround: Images can be analyzed by using the
readtool to send the image content to the primary text model, which resolves custom providers through its own model resolution path. Theimagetool specifically cannot use custom providers.Suggested fixes:
loadCustomModelsmore resilient — a validation error for one provider should not prevent loading other providers and overrides.ensureOpenClawModelsJsondoes not generate providers withmodelsarrays but noapiKeywhen the provider uses OAuth.imagetool use the same model resolution path as the main runner, which correctly handles custom providers.