Summary
OpenClaw's openai-responses and azure-openai-responses transports both fail against Azure AI Foundry project endpoints. The root cause is that convertResponsesMessages() does not include type: "message" on user/developer input items, which Azure AI Foundry's Responses API requires. OpenAI's direct API infers the type when absent; Azure does not.
A secondary issue prevents using api: "azure-openai-responses" as a workaround: the AzureOpenAI SDK injects an api-version query parameter that Foundry project endpoints reject.
Context
Azure AI Foundry project endpoints use a different URL structure than traditional Azure OpenAI resources:
- Traditional:
https://<resource>.openai.azure.com/openai/v1
- Foundry project:
https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1
These Foundry endpoints expose only the Responses API (/responses) — the Chat Completions API (/chat/completions) returns "unsupported operation". They also require an explicit type field on every input item in the input array, which OpenAI's direct API does not.
This is increasingly common: Azure AI Foundry is Microsoft's recommended deployment path for new models (GPT-5.x, Codex, etc.), meaning more users will hit this as they migrate from traditional Azure OpenAI resources.
Steps to Reproduce
- Configure a provider targeting an Azure AI Foundry project endpoint:
{
"azure-openai-primary": {
"baseUrl": "https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1",
"apiKey": "***",
"api": "openai-responses",
"authHeader": false,
"headers": { "api-key": "***" },
"models": [{ "id": "gpt-5.3-codex", "reasoning": true }]
}
}
-
Assign an agent to use this model: model: { "primary": "azure-openai-primary/gpt-5.3-codex" }
-
Send any message. The request fails immediately with:
400 Invalid value: ''. Supported values are: 'apply_patch_call', ..., 'message', 'reasoning', ...
param: input[1]
code: invalid_value
Root Cause Analysis
Issue 1: Missing type field on input items
In openai-responses-shared.js, convertResponsesMessages() outputs user and developer messages without a type field:
// Current output:
{ role: "developer", content: "..." }
{ role: "user", content: [{ type: "input_text", text: "..." }] }
Azure AI Foundry requires:
// Expected:
{ type: "message", role: "developer", content: [{ type: "input_text", text: "..." }] }
{ type: "message", role: "user", content: [{ type: "input_text", text: "..." }] }
Note: developer messages also need their content wrapped as an array with type: "input_text" — a bare string works on OpenAI direct but fails on Azure.
Issue 2: azure-openai-responses transport incompatible with Foundry endpoints
Switching to api: "azure-openai-responses" does not help because:
- The
AzureOpenAI SDK automatically appends ?api-version=v1 to requests
- Foundry project endpoints (with
/v1 already in the path) reject this: 400 api-version query parameter is not allowed when using /v1 path
- Even if the SDK issue were resolved,
convertResponsesMessages() still omits type: "message" — the same input formatting problem applies
Issue 3: prompt_cache_retention and store not supported
The openai-responses transport sends prompt_cache_retention and store: false in the request body. Foundry endpoints may reject these fields (unconfirmed but likely).
Verified Workaround
Using the generic OpenAI client (not AzureOpenAI) with type: "message" explicitly added to every input item works correctly — including streaming, tools, and multi-turn conversation history with function calls. Confirmed via standalone Node.js testing against the live Foundry endpoint.
Suggested Solutions
I would appreciate guidance on which approach you would prefer. Some options:
Option A: Add type: "message" unconditionally
In convertResponsesMessages(), add type: "message" to all user/developer/system message objects. This is harmless for OpenAI's direct API (which accepts it) and required by Azure. This is the simplest fix.
Option B: Add a provider-level compat flag
Introduce something like compat.explicitInputTypes: true on the provider/model config. When set, convertResponsesMessages() includes type: "message" on input items. This is more targeted but requires config changes.
Option C: Dedicated azure-foundry-responses transport
A new API type that uses the generic OpenAI client (no api-version injection), always includes type: "message", and strips unsupported fields like store and prompt_cache_retention. This would be the most robust long-term solution.
Option D: Fix azure-openai-responses to handle Foundry endpoints
Detect Foundry project URLs (contain /api/projects/) and either suppress the api-version parameter or switch to the generic OpenAI client for those endpoints. Combined with Option A or B for the type field.
Happy to submit a PR if you point me at the preferred approach.
Summary
OpenClaw's
openai-responsesandazure-openai-responsestransports both fail against Azure AI Foundry project endpoints. The root cause is thatconvertResponsesMessages()does not includetype: "message"on user/developer input items, which Azure AI Foundry's Responses API requires. OpenAI's direct API infers the type when absent; Azure does not.A secondary issue prevents using
api: "azure-openai-responses"as a workaround: theAzureOpenAISDK injects anapi-versionquery parameter that Foundry project endpoints reject.Context
Azure AI Foundry project endpoints use a different URL structure than traditional Azure OpenAI resources:
https://<resource>.openai.azure.com/openai/v1https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1These Foundry endpoints expose only the Responses API (
/responses) — the Chat Completions API (/chat/completions) returns "unsupported operation". They also require an explicittypefield on every input item in theinputarray, which OpenAI's direct API does not.This is increasingly common: Azure AI Foundry is Microsoft's recommended deployment path for new models (GPT-5.x, Codex, etc.), meaning more users will hit this as they migrate from traditional Azure OpenAI resources.
Steps to Reproduce
{ "azure-openai-primary": { "baseUrl": "https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1", "apiKey": "***", "api": "openai-responses", "authHeader": false, "headers": { "api-key": "***" }, "models": [{ "id": "gpt-5.3-codex", "reasoning": true }] } }Assign an agent to use this model:
model: { "primary": "azure-openai-primary/gpt-5.3-codex" }Send any message. The request fails immediately with:
Root Cause Analysis
Issue 1: Missing
typefield on input itemsIn
openai-responses-shared.js,convertResponsesMessages()outputs user and developer messages without atypefield:Azure AI Foundry requires:
Note: developer messages also need their content wrapped as an array with
type: "input_text"— a bare string works on OpenAI direct but fails on Azure.Issue 2:
azure-openai-responsestransport incompatible with Foundry endpointsSwitching to
api: "azure-openai-responses"does not help because:AzureOpenAISDK automatically appends?api-version=v1to requests/v1already in the path) reject this:400 api-version query parameter is not allowed when using /v1 pathconvertResponsesMessages()still omitstype: "message"— the same input formatting problem appliesIssue 3:
prompt_cache_retentionandstorenot supportedThe
openai-responsestransport sendsprompt_cache_retentionandstore: falsein the request body. Foundry endpoints may reject these fields (unconfirmed but likely).Verified Workaround
Using the generic
OpenAIclient (notAzureOpenAI) withtype: "message"explicitly added to every input item works correctly — including streaming, tools, and multi-turn conversation history with function calls. Confirmed via standalone Node.js testing against the live Foundry endpoint.Suggested Solutions
I would appreciate guidance on which approach you would prefer. Some options:
Option A: Add
type: "message"unconditionallyIn
convertResponsesMessages(), addtype: "message"to all user/developer/system message objects. This is harmless for OpenAI's direct API (which accepts it) and required by Azure. This is the simplest fix.Option B: Add a provider-level compat flag
Introduce something like
compat.explicitInputTypes: trueon the provider/model config. When set,convertResponsesMessages()includestype: "message"on input items. This is more targeted but requires config changes.Option C: Dedicated
azure-foundry-responsestransportA new API type that uses the generic
OpenAIclient (noapi-versioninjection), always includestype: "message", and strips unsupported fields likestoreandprompt_cache_retention. This would be the most robust long-term solution.Option D: Fix
azure-openai-responsesto handle Foundry endpointsDetect Foundry project URLs (contain
/api/projects/) and either suppress theapi-versionparameter or switch to the genericOpenAIclient for those endpoints. Combined with Option A or B for the type field.Happy to submit a PR if you point me at the preferred approach.