Summary
When configuring Azure OpenAI (e.g., GPT-5.4) as a custom provider, OpenClaw does not add the required api-version query parameter to API requests, resulting in HTTP 404 errors.
Environment
- OpenClaw version: 2026.3.x
- Azure OpenAI endpoint:
https://*.cognitiveservices.azure.com
- Model: gpt-5.4
Steps to Reproduce
- Configure Azure OpenAI provider in
openclaw.json:
{
"models": {
"providers": {
"azure-openai": {
"baseUrl": "https://my-resource.cognitiveservices.azure.com/openai/deployments/gpt-5.4",
"apiKey": "...",
"api": "openai-completions",
"models": [
{ "id": "gpt-5.4", "name": "GPT-5.4 (Azure)" }
]
}
}
}
}
- Set model:
/model azure-openai/gpt-5.4
- Send any message
Expected Behavior
OpenClaw should call:
POST https://my-resource.cognitiveservices.azure.com/openai/deployments/gpt-5.4/chat/completions?api-version=2024-12-01-preview
Actual Behavior
OpenClaw calls (without api-version):
POST https://my-resource.cognitiveservices.azure.com/openai/deployments/gpt-5.4/chat/completions
Result: HTTP 404: Resource not found
Evidence
Direct curl with api-version works:
curl -X POST "https://my-resource.cognitiveservices.azure.com/openai/deployments/gpt-5.4/chat/completions?api-version=2024-12-01-preview" \
-H "api-key: ..." \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"hi"}],"max_completion_tokens":100}'
# Returns: {"choices":[{"message":{"content":"Hi! How can I help?"}}]}
Current Workaround
Using nginx as a local proxy to add api-version:
server {
listen 8080;
location /openai/ {
proxy_pass https://my-resource.cognitiveservices.azure.com/openai/;
proxy_set_header Host my-resource.cognitiveservices.azure.com;
proxy_set_header api-key $http_api_key;
proxy_ssl_server_name on;
set $args "${args}&api-version=2024-12-01-preview";
if ($args ~ "^&") {
set $args "api-version=2024-12-01-preview";
}
}
}
Then configure openclaw to use http://localhost:8080/openai/deployments/gpt-5.4.
Proposed Solution
- Add
apiVersion config option for providers:
{
"azure-openai": {
"baseUrl": "...",
"apiVersion": "2024-12-01-preview"
}
}
- Or auto-detect Azure endpoints (*.cognitiveservices.azure.com, *.openai.azure.com) and add default api-version.
Note: The onboard-custom.ts already has Azure detection logic that adds api-version for verification probes, but this doesn't apply to runtime API calls.
Related Code
src/commands/onboard-custom.ts:289 - adds api-version only during onboarding
src/agents/tools/web-search.ts:1258 - appends /chat/completions without query params
Additional Notes
GPT-5.4 also requires max_completion_tokens instead of max_tokens, which can be configured via compat.maxTokensField, but this is a separate issue.
Summary
When configuring Azure OpenAI (e.g., GPT-5.4) as a custom provider, OpenClaw does not add the required
api-versionquery parameter to API requests, resulting in HTTP 404 errors.Environment
https://*.cognitiveservices.azure.comSteps to Reproduce
openclaw.json:{ "models": { "providers": { "azure-openai": { "baseUrl": "https://my-resource.cognitiveservices.azure.com/openai/deployments/gpt-5.4", "apiKey": "...", "api": "openai-completions", "models": [ { "id": "gpt-5.4", "name": "GPT-5.4 (Azure)" } ] } } } }/model azure-openai/gpt-5.4Expected Behavior
OpenClaw should call:
Actual Behavior
OpenClaw calls (without api-version):
Result:
HTTP 404: Resource not foundEvidence
Direct curl with api-version works:
Current Workaround
Using nginx as a local proxy to add api-version:
Then configure openclaw to use
http://localhost:8080/openai/deployments/gpt-5.4.Proposed Solution
apiVersionconfig option for providers:{ "azure-openai": { "baseUrl": "...", "apiVersion": "2024-12-01-preview" } }Note: The
onboard-custom.tsalready has Azure detection logic that adds api-version for verification probes, but this doesn't apply to runtime API calls.Related Code
src/commands/onboard-custom.ts:289- adds api-version only during onboardingsrc/agents/tools/web-search.ts:1258- appends/chat/completionswithout query paramsAdditional Notes
GPT-5.4 also requires
max_completion_tokensinstead ofmax_tokens, which can be configured viacompat.maxTokensField, but this is a separate issue.