Bug: azure-openai-responses can return non_deliverable_terminal_turn with assistantTexts=[] even when direct Azure /responses succeeds
Summary
azure-openai-responses is currently not stable enough to use as an OpenClaw production route for Azure / Foundry Responses. In our environment, the same Azure Foundry project endpoint succeeds with direct POST /openai/v1/responses, but an OpenClaw isolated no-tools canary using model="azure/gpt-5.5" fails with:
terminalError = "non_deliverable_terminal_turn"
assistantTexts = []
aborted = false
timedOut = false
idleTimedOut = false
promptErrorSource = null
This is different from #79570: this is not a synthetic 0-token refusal. The direct Azure Responses API call completes and returns normal output. The failure appears to be in OpenClaw's Azure Responses integration / response-item normalization / terminal assistant-text extraction path.
Environment
OpenClaw app: 2026.5.28
OS: Linux 6.12.68+ x64
Node: v24.14.0
Runtime: OpenClaw default runtime
Provider/model: azure/gpt-5.5
Azure provider config used for the failing canary:
I also observed a related failure on the Azure resource-host form:
baseUrl = "${AZURE_FOUNDRY_BASE_URL}/openai/v1"
api = "azure-openai-responses"
That route succeeded for several short OpenClaw turns, then failed on a large real Telegram turn with the same terminal class:
trace.artifacts.finalStatus = "error"
terminalError = "non_deliverable_terminal_turn"
assistantTexts = []
aborted = false
timedOut = false
idleTimedOut = false
promptErrorSource = null
usage.input ~= 284729
usage.cacheRead ~= 410624
usage.output ~= 2186
usage.reasoningTokens ~= 322
So the project endpoint is not the only surface affected, but the project endpoint gave the smallest repro: trivial no-tools OpenClaw canary.
Direct API smoke succeeds
Direct calls to the same Foundry project endpoint succeeded:
POST https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1/responses
Observed results:
no-tools response: HTTP 200, status=completed, output types included reasoning/message
tools + reasoning response: HTTP 200, status=completed, output type function_call
This strongly suggests the endpoint/key/model path is valid. The failure boundary is OpenClaw's integration/runtime handling of the Azure Responses output, not basic connectivity.
OpenClaw repro
Minimal failing case
- Configure
azure/gpt-5.5 as above using api: "azure-openai-responses" and the Foundry project endpoint.
- Run an isolated OpenClaw canary with no tools and a deterministic response instruction, for example:
Return exactly: AZURE_RESPONSES_CANARY_OK
- Inspect the run/trajectory result.
Expected:
assistantTexts = ["AZURE_RESPONSES_CANARY_OK"]
finalStatus = "completed" // or equivalent successful terminal status
Actual:
terminalError = "non_deliverable_terminal_turn"
assistantTexts = []
aborted = false
timedOut = false
idleTimedOut = false
promptErrorSource = null
Control case
After changing the same provider back to Azure OpenAI Chat Completions:
The same style of isolated no-tools OpenClaw canary succeeds:
AZURE_COMPLETIONS_CANARY_OK
Why this matters
Azure / Foundry Responses is the desired route for GPT-5.x reasoning + tools. But in this failure mode OpenClaw reaches a terminal turn with no deliverable assistant text, so users see fallback behavior or missing replies even though direct Azure Responses calls are healthy.
The route is especially dangerous because short/direct API tests can pass while OpenClaw terminal delivery still fails.
AI triage section
This section is written for an AI maintainer / issue triage agent.
Triage classification
Likely code areas to inspect
Search terms:
azure-openai-responses
runResponsesStreamLifecycle
createResponsesAssistantOutput
convertResponsesMessages
assistantTexts
non_deliverable_terminal_turn
collectAssistantTexts
Likely files / modules based on the built app layout:
src/llm/providers/azure-openai-responses.ts
src/llm/providers/openai-responses-shared.ts
extensions/codex/src/app-server/event-projector.ts
extensions/codex/src/app-server/run-attempt.ts
extensions/codex/src/app-server/attempt-results.ts
Built artifacts in the 2026.5.28 package include similarly named chunks such as:
/app/dist/azure-openai-responses-*.js
/app/dist/openai-responses-shared-*.js
/app/dist/selection-*.js
Hypothesis to test, not assume
The Azure Responses stream/result likely contains a completed response with items that OpenClaw does not normalize into a final assistant text for this provider/path. Candidate item-shape gaps:
- Azure emits
output items with a provider-specific message/reasoning content shape that createResponsesAssistantOutput or the shared Responses lifecycle does not map into the app-server event shape consumed by collectAssistantTexts().
- A reasoning item preceding the message changes which item is considered terminal/deliverable.
- The Azure adapter emits lifecycle/tool/reasoning events but misses the final assistant-message event expected by the event projector.
- Project endpoint vs resource endpoint may differ in output item shape, but both should be normalized before app-server terminal delivery.
Do not assume the endpoint is broken: direct /openai/v1/responses returned HTTP 200 status=completed.
Suggested tests to add
1. Unit test: Azure Responses completed message with reasoning + message output
Add a fixture that mimics the direct Azure successful no-tools response:
Expected OpenClaw projection:
assistantTexts === ["AZURE_RESPONSES_CANARY_OK"]
terminalError === undefined
2. Unit test: Azure Responses message content alternate text shape
If Azure returns a different content shape, cover it explicitly. Examples to verify against captured Azure payloads:
Expected: both normalize to a deliverable assistant text if Azure emits them in a completed assistant message.
3. Integration/canary test: no-tools isolated turn
With a live Azure/Foundry Responses config:
Prompt: Return exactly: AZURE_RESPONSES_CANARY_OK
Tools: none
Expected assistantTexts: ["AZURE_RESPONSES_CANARY_OK"]
Expected terminal status: success
This is the smallest repro observed here.
4. Integration/canary test: function-call continuation then final text
Because a related resource-host failure occurred on a real tool/context turn, add a live canary or mock stream for:
assistant function_call -> tool_result -> assistant final message
Expected: final assistant text survives through the event projector and does not end in non_deliverable_terminal_turn.
Acceptance criteria
azure-openai-responses direct no-tools OpenClaw canary produces non-empty assistantTexts and a deliverable terminal turn.
- Tool-call continuation canary produces final assistant text after tool result.
- No synthetic fallback to another provider is required for the above canaries.
- Existing OpenAI Responses and Chat Completions behavior remains unchanged.
- If Azure returns a completed response with no assistant text, diagnostics should include enough raw-safe item metadata to distinguish provider-empty output from adapter-normalization failure.
Related issues
Workaround
For now, Azure production use is safer on Chat Completions with reasoning disabled:
This avoids the Responses terminal-turn failure, but sacrifices Azure Responses/reasoning support.
Important caveat: on this Azure GPT-5.5 deployment, Chat Completions fails if reasoning_effort is present together with function tools, even if the value is none. Therefore the workaround must suppress the reasoning_effort field entirely for tool turns, e.g. by configuring the model route with reasoning:false.
Bug:
azure-openai-responsescan returnnon_deliverable_terminal_turnwithassistantTexts=[]even when direct Azure/responsessucceedsSummary
azure-openai-responsesis currently not stable enough to use as an OpenClaw production route for Azure / Foundry Responses. In our environment, the same Azure Foundry project endpoint succeeds with directPOST /openai/v1/responses, but an OpenClaw isolated no-tools canary usingmodel="azure/gpt-5.5"fails with:This is different from #79570: this is not a synthetic 0-token refusal. The direct Azure Responses API call completes and returns normal output. The failure appears to be in OpenClaw's Azure Responses integration / response-item normalization / terminal assistant-text extraction path.
Environment
Azure provider config used for the failing canary:
{ "models": { "providers": { "azure": { "baseUrl": "https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1", "apiKey": "${AZURE_FOUNDRY_API_KEY}", "api": "azure-openai-responses", "models": [ { "id": "gpt-5.5", "name": "GPT-5.5 (Azure)", "reasoning": true, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 128000, "compat": { "supportsStore": false, "supportsUsageInStreaming": true } } ] } } } }I also observed a related failure on the Azure resource-host form:
That route succeeded for several short OpenClaw turns, then failed on a large real Telegram turn with the same terminal class:
So the project endpoint is not the only surface affected, but the project endpoint gave the smallest repro: trivial no-tools OpenClaw canary.
Direct API smoke succeeds
Direct calls to the same Foundry project endpoint succeeded:
Observed results:
This strongly suggests the endpoint/key/model path is valid. The failure boundary is OpenClaw's integration/runtime handling of the Azure Responses output, not basic connectivity.
OpenClaw repro
Minimal failing case
azure/gpt-5.5as above usingapi: "azure-openai-responses"and the Foundry project endpoint.Expected:
Actual:
Control case
After changing the same provider back to Azure OpenAI Chat Completions:
{ "baseUrl": "${AZURE_OPENAI_BASE_URL}/openai/v1", "api": "openai-completions", "models": [ { "id": "gpt-5.5", "reasoning": false, "compat": { "supportsStore": false, "supportsUsageInStreaming": true } } ] }The same style of isolated no-tools OpenClaw canary succeeds:
Why this matters
Azure / Foundry Responses is the desired route for GPT-5.x reasoning + tools. But in this failure mode OpenClaw reaches a terminal turn with no deliverable assistant text, so users see fallback behavior or missing replies even though direct Azure Responses calls are healthy.
The route is especially dangerous because short/direct API tests can pass while OpenClaw terminal delivery still fails.
AI triage section
This section is written for an AI maintainer / issue triage agent.
Triage classification
azure-openai-responsesnon_deliverable_terminal_turnassistantTexts=[]aborted=false,timedOut=false,idleTimedOut=falsepromptErrorSource=nullusage.totalTokens == 0Likely code areas to inspect
Search terms:
Likely files / modules based on the built app layout:
Built artifacts in the 2026.5.28 package include similarly named chunks such as:
Hypothesis to test, not assume
The Azure Responses stream/result likely contains a completed response with items that OpenClaw does not normalize into a final assistant text for this provider/path. Candidate item-shape gaps:
outputitems with a provider-specificmessage/reasoningcontent shape thatcreateResponsesAssistantOutputor the shared Responses lifecycle does not map into the app-server event shape consumed bycollectAssistantTexts().Do not assume the endpoint is broken: direct
/openai/v1/responsesreturned HTTP 200status=completed.Suggested tests to add
1. Unit test: Azure Responses completed message with reasoning + message output
Add a fixture that mimics the direct Azure successful no-tools response:
{ "status": "completed", "output": [ { "type": "reasoning", "id": "..." }, { "type": "message", "role": "assistant", "content": [ { "type": "output_text", "text": "AZURE_RESPONSES_CANARY_OK" } ] } ] }Expected OpenClaw projection:
2. Unit test: Azure Responses message content alternate text shape
If Azure returns a different content shape, cover it explicitly. Examples to verify against captured Azure payloads:
{ "type": "text", "text": "AZURE_RESPONSES_CANARY_OK" } { "type": "output_text", "text": "AZURE_RESPONSES_CANARY_OK" }Expected: both normalize to a deliverable assistant text if Azure emits them in a completed assistant message.
3. Integration/canary test: no-tools isolated turn
With a live Azure/Foundry Responses config:
This is the smallest repro observed here.
4. Integration/canary test: function-call continuation then final text
Because a related resource-host failure occurred on a real tool/context turn, add a live canary or mock stream for:
Expected: final assistant text survives through the event projector and does not end in
non_deliverable_terminal_turn.Acceptance criteria
azure-openai-responsesdirect no-tools OpenClaw canary produces non-emptyassistantTextsand a deliverable terminal turn.Related issues
openai-responses; this report isazure-openai-responsesproducingnon_deliverable_terminal_turnwithassistantTexts=[]while direct Azure/responsessucceeds.Workaround
For now, Azure production use is safer on Chat Completions with reasoning disabled:
{ "api": "openai-completions", "reasoning": false }This avoids the Responses terminal-turn failure, but sacrifices Azure Responses/reasoning support.
Important caveat: on this Azure GPT-5.5 deployment, Chat Completions fails if
reasoning_effortis present together with function tools, even if the value isnone. Therefore the workaround must suppress thereasoning_effortfield entirely for tool turns, e.g. by configuring the model route withreasoning:false.