Skip to content

Azure AI Foundry Responses API: type: "message" missing from input items causes 400 error #84109

@alfredpennyworthtc-netizen

Description

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

  1. 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 }]
  }
}
  1. Assign an agent to use this model: model: { "primary": "azure-openai-primary/gpt-5.3-codex" }

  2. 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:

  1. The AzureOpenAI SDK automatically appends ?api-version=v1 to requests
  2. Foundry project endpoints (with /v1 already in the path) reject this: 400 api-version query parameter is not allowed when using /v1 path
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions