Skip to content

Azure AI Foundry models (/openai/v1/responses) fail with 400 Invalid value and 400 schema mismatch across all GPT-5.x deployments #90570

Description

@Osshaikh

Azure AI Foundry models (/openai/v1/responses) fail with 400 Invalid value and 400 The provided data does not match the expected schema across all GPT-5.x deployments

Summary

OpenClaw v2026.6.1 (and v2026.5.x) cannot successfully complete a single round-trip with Azure AI Foundry-hosted OpenAI models (GPT-5.2, GPT-5.4, GPT-5.4-pro, GPT-5.5) when using api: "openai-responses". Every call fails with a 400 schema validation error from Azure. This makes OpenClaw effectively unusable with the standard Microsoft Foundry deployment of OpenAI models.

The same Azure endpoints accept hand-crafted curl requests successfully — so this is a payload serialization bug inside OpenClaw's openai-responses transport when talking to Azure Foundry's /openai/v1/responses endpoint.

I also see two flavours of the error depending on the request:

  • 400 Invalid value: ''. Supported values are: 'apply_patch_call', 'apply_patch_call_output', 'code_interpreter_call', 'compaction', 'computer_call', 'computer_call_output', 'custom_tool_call', 'custom_tool_call_output', 'file_search_call', 'function_call', 'function_call_output', 'image_generation_call', 'item_reference', 'local_shell_call', 'local_shell_call_output', 'mcp_approval_request', 'mcp_approval_response', 'mcp_call', 'mcp_list_tools', 'message', 'reasoning', 'shell_call', 'shell_call_output', 'tool_search_call', 'tool_search_output', and 'web_search_call'.
    → Strongly suggests OpenClaw is emitting an item with type: "" (empty string) somewhere in the input[] array.
  • 400 The provided data does not match the expected schema [Request ID: ...]
    → Different request body, same provider, also rejected.

Switching to api: "openai-completions" against /openai/v1/chat/completions on the same Azure Foundry resource succeeds with curl for both GPT-5.2 and GPT-5.5, but OpenClaw still fails (different code path also broken — see Run 6).


Environment

  • OpenClaw version: tested on 2026.5.2, 2026.5.12, 2026.5.28, 2026.6.1 (current)
  • Node.js: v22.22.3
  • OS: Windows 11 (native install via npm install -g openclaw)
  • Channels enabled: Telegram (allowlist), WhatsApp
  • Active model provider: custom openai-responses provider pointed at Azure AI Foundry
  • Auth: api-key header

Azure resources tested (all fail)

Resource Region Type Deployments tested
<RESOURCE_A>.services.ai.azure.com (project: <PROJECT>) eastus2 AIServices (Foundry project endpoint) gpt-5.2, gpt-5.4-pro, gpt-5.5
<RESOURCE_B>.cognitiveservices.azure.com eastus AIServices gpt-5.2, gpt-5.4, gpt-5.5
<RESOURCE_C>.cognitiveservices.azure.com eastus2 AIServices gpt-5.3-codex
<RESOURCE_D>.cognitiveservices.azure.com AIServices gpt-5.2

All four fail in identical ways when OpenClaw is the client. Only differences are the deployment IDs.


Provider config (representative)

~/.openclaw/openclaw.json — only relevant blocks shown:

{
  "models": {
    "providers": {
      "azure-foundry": {
        "baseUrl": "https://<RESOURCE>.services.ai.azure.com/openai/v1",
        "apiKey": "${AZURE_FOUNDRY_API_KEY}",
        "api": "openai-responses",
        "headers": {
          "api-key": "${AZURE_FOUNDRY_API_KEY}"
        },
        "models": [
          { "id": "gpt-5.5",     "name": "GPT 5.5 (foundry)",     "reasoning": true, "input": ["text","image"], "contextWindow": 200000, "maxTokens": 65536 },
          { "id": "gpt-5.2",     "name": "GPT 5.2 (foundry)",     "reasoning": true, "input": ["text","image"], "contextWindow": 200000, "maxTokens": 16384 },
          { "id": "gpt-5.4-pro", "name": "GPT 5.4 Pro (foundry)", "reasoning": true, "input": ["text","image"], "contextWindow": 200000, "maxTokens": 32768 }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "azure-foundry/gpt-5.5",
        "fallbacks": ["azure-foundry/gpt-5.2"]
      },
      "thinkingDefault": "off"
    }
  }
}

The same shape was tested with "api": "azure-openai-responses" (also fails with 400 Missing required query parameter: api-version because the Foundry /v1 path explicitly disallows the api-version query param) and with "api": "openai-completions" against /chat/completions (also fails — see Run 6 below).

Additional combinations tried:

  • baseUrl with and without /v1
  • baseUrl with /openai/deployments/<model> (legacy Azure path) — returns 404 on Foundry
  • baseUrl with the project-scoped path /api/projects/<project>/openai/v1 — same 400
  • Auth via api-key header AND via Authorization: Bearer ... (both accepted by Azure, both rejected by OpenClaw's payload)
  • headers.api-key set explicitly in the provider block
  • Removing and re-adding auth-profiles.json entries
  • Wiping ~/.openclaw/agents/main/sessions/* between every test
  • Hard restart of the gateway process (not just hot reload)
  • Scoping api-version injection via a custom NODE_OPTIONS --require patch (works for azure-openai-responses URL form, doesn't help for /v1 form because Azure rejects the query param entirely on /v1)

Repro: control via curl (works)

These all return HTTP 200 with valid responses (run from the same Windows host):

# /v1/responses with api-key header (no api-version)
curl -X POST "https://<RESOURCE>.services.ai.azure.com/api/projects/<PROJECT>/openai/v1/responses" \
  -H "api-key: <AZURE_FOUNDRY_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.5","input":"say hello"}'
# -> 200, response.output[0].content[0].text = "Hello!"

# /v1/chat/completions with api-key header
curl -X POST "https://<RESOURCE>.services.ai.azure.com/openai/v1/chat/completions" \
  -H "api-key: <AZURE_FOUNDRY_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"hi"}],"max_completion_tokens":100}'
# -> 200

# Same with Bearer auth - also 200
curl -X POST "https://<RESOURCE>.services.ai.azure.com/openai/v1/chat/completions" \
  -H "Authorization: Bearer <AZURE_FOUNDRY_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"hi"}],"max_completion_tokens":100}'

So the endpoints work, the key works, the auth works, and the URL is correct. The problem is the body OpenClaw constructs.


Repro: via OpenClaw (fails every time)

  1. Configure azure-foundry provider as above.
  2. Set agents.defaults.model.primary = "azure-foundry/gpt-5.5" (or 5.2, or 5.4-pro — all behave the same).
  3. Start the gateway (schtasks /Run /TN "OpenClaw Gateway" on Windows).
  4. Send any message (even a 5-char "hello") on any channel (Telegram, web, etc.).
  5. Observe a 400 Invalid value: '' or 400 The provided data does not match the expected schema from Azure in the logs.
  6. OpenClaw's failover then tries fallback models on the same provider, all fail the same way, request ultimately surfaces "All models failed" to the user.

Concrete log excerpts

Run 1 — api: "openai-responses" against /openai/v1/responses, GPT-5.5

[telegram] Inbound message telegram:<USER_ID> -> @<BOT_NAME> (direct, 5 chars)
[agent/embedded] [trace:embedded-run] startup stages: ... model-resolution:5878ms,auth:4965ms ...
[openai-transport] [responses] error provider=azure-foundry api=openai-responses model=gpt-5.5
  name=Error status=400 code=invalid_value type=invalid_request_error
  message=400 Invalid value: ''. Supported values are:
    'apply_patch_call', 'apply_patch_call_output', 'code_interpreter_call', 'compaction',
    'computer_call', 'computer_call_output', 'custom_tool_call', 'custom_tool_call_output',
    'file_search_call', 'function_call', 'function_call_output', 'image_generation_call',
    'item_reference', 'local_shell_call', 'local_shell_call_output',
    'mcp_approval_request', 'mcp_approval_response', 'mcp_call', 'mcp_list_tools',
    'message', 'reasoning', 'shell_call', 'shell_call_output',
    'tool_search_call', 'tool_search_output', 'web_search_call'.
[telegram] embedded run agent end: isError=true model=gpt-5.5 provider=azure-foundry
  error=LLM request failed: provider rejected the request schema or tool payload.
[model-fallback/decision] decision=candidate_failed requested=azure-foundry/gpt-5.5
  reason=format next=azure-foundry/gpt-5.2

(Each fallback fails identically. Final error to user: All models failed (3) ....)

Run 2 — api: "openai-responses", GPT-5.4-pro and GPT-5.2 same provider

[openai-transport] [responses] error provider=azure-foundry api=openai-responses model=gpt-5.4-pro
  status=400 code=invalid_payload type=invalid_request_error
  message=400 The provided data does not match the expected schema [Request ID: 942748853d571d96e5807c45920f4eb4]
...
[openai-transport] [responses] error provider=azure-foundry api=openai-responses model=gpt-5.2
  status=400 code=invalid_payload type=invalid_request_error
  message=400 The provided data does not match the expected schema [Request ID: 35fae76995a7bbc4c745aa3707edbfb0]

Two different error codes (invalid_value vs invalid_payload) suggest OpenClaw constructs at least two distinct invalid payload shapes depending on whether tools/reasoning/memory items are present.

Run 3 — api: "azure-openai-responses" (built-in Azure provider type)

[openai-transport] [responses] error provider=azure-foundry api=azure-openai-responses model=gpt-5.5
  status=400
  message=400 Missing required query parameter: api-version

So the built-in azure-openai-responses transport doesn't add api-version to the request, but the /openai/v1/responses endpoint rejects requests without it. The azure-openai-responses transport seems hard-coded to not append api-version while still using the rest of the Azure-specific framing.

If I instead point the same provider at the legacy /openai/deployments/<id>/responses?api-version=... URL with azure-openai-responses, the request now ships api-version correctly — but the deployment-based Responses endpoint returns 404 on the Foundry resource because Foundry only exposes the project-scoped /openai/v1/responses path. So the azure-openai-responses transport is hard-wired for an endpoint shape Foundry no longer ships.

Run 4 — api: "openai-completions" against /openai/v1/chat/completions

[openai-transport] error provider=azure-foundry api=openai-responses model=gpt-5.2
  status=400 code=invalid_payload
  message=400 The provided data does not match the expected schema [Request ID: ...]

Note: log line still says api=openai-responses even though config was changed to openai-completions. Either the change didn't take effect (no hot reload for api field?) or the transport selection ignores the override. This needs verification — but the request still fails with the same schema rejection.


What this looks like on the wire

I haven't proxied the actual request body yet (the gateway uses Node's native fetch + streaming, hard to MitM without modifying source), but the Azure error Invalid value: ''. Supported values are: ['message', 'function_call', 'reasoning', ...] strongly indicates OpenClaw is sending something like:

{
  "model": "gpt-5.5",
  "input": [
    { "type": "message", "role": "user", "content": [...] },
    { "type": "", ...something... }   // <- this is what Azure rejects
  ]
}

This is consistent with how OpenClaw passes prior session compaction items, reasoning continuations, or tool outputs back to the model — one of those item builders likely outputs type as an empty string when the corresponding upstream field is missing.


What I tried (none worked)

  1. Upgrading OpenClaw 2026.2.232026.5.122026.5.282026.6.1.
  2. Switching between 4 different Azure resources (Foundry project endpoint, two AIServices cognitiveservices endpoints, and an AIServices in a different region).
  3. Switching across 5 model deployments (gpt-5.2, gpt-5.3-codex, gpt-5.4, gpt-5.4-pro, gpt-5.5).
  4. Toggling between openai-responses, azure-openai-responses, and openai-completions API types.
  5. Multiple baseUrl shapes:
    • https://<acct>.cognitiveservices.azure.com/openai
    • https://<acct>.cognitiveservices.azure.com/openai/v1
    • https://<acct>.services.ai.azure.com/openai/v1
    • https://<acct>.services.ai.azure.com/api/projects/<project>/openai/v1
    • https://<acct>.cognitiveservices.azure.com/openai/deployments/<model> (legacy)
  6. Auth via api-key header, via Authorization: Bearer ..., both at the same time.
  7. Setting headers.api-key explicitly in the provider config.
  8. Hot reload, soft restart (openclaw gateway restart), hard kill + schtasks restart, full reinstall (openclaw gateway install --force).
  9. Wiping all sessions (~/.openclaw/agents/main/sessions/*) between attempts.
  10. thinkingDefault set to max, off, removed entirely.
  11. NODE preload patch that adds ?api-version=2025-03-01-preview to all outgoing requests for the legacy provider type.

Only direct curl calls succeed.


Impact

  • Telegram channel users get either LLM request failed: provider rejected the request schema or tool payload or a 2–3 minute hang followed by All models failed.
  • WhatsApp channel has its own packaging warning that prevents it from loading at all on v2026.5.x and v2026.6.1 (installed plugin package requires compiled runtime output for TypeScript entry index.ts: expected ./dist/index.js ...) — separate issue, but worth mentioning since it removes the only working channel as a workaround.
  • Memory search, voice, image, and tool features are unusable end-to-end because every model call dies before the first token.

Asks

  1. Fix the openai-responses transport to never emit {"type": ""} items in input[]. Either omit the field, or default to a valid enum value, or drop the item.
  2. Fix the azure-openai-responses transport to support Foundry's /openai/v1/responses path. Specifically:
    • Don't inject api-version on /openai/v1/... URLs (Azure rejects it there).
    • Do inject api-version on /openai/deployments/.../responses URLs (Azure requires it there).
    • Detection should be path-based, not host-based.
  3. Make api field hot-reloadable, or surface a clear warning when it isn't (Run 4 above suggests the api selection is sticky after process start even though other model fields hot-reload fine).
  4. Document the supported endpoint shapes for Azure AI Foundry explicitly — Microsoft has been steadily migrating from deployment-based to project-based to /v1-style paths and OpenClaw's docs don't currently cover any of these clearly.
  5. Optional: a requestBodyLogging: true knob on providers for one-off debugging would have made this trivial to root-cause from outside.

Willing to help

Happy to:

  • Capture and attach the actual outgoing request body if you can point me at the right OpenClaw source file (or merge a --debug-llm-payload flag).
  • Test patches against my Foundry resources.
  • Share full uncut logs and exact openclaw.json (private values redacted).

Thanks for the project — this is the one blocker keeping it from being our team's daily driver.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-infoClawSweeper needs more reporter information before it can verify this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦐 gold shrimpDecent issue quality, but reproduction details are still incomplete.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions