openclaw - 💡(How to fix) Fix Bug: azure-openai-responses can return non_deliverable_terminal_turn with assistantTexts=[] even when direct Azure /responses succeeds

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

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.

Error Message

trace.artifacts.finalStatus = "error"

  • Primary error string: non_deliverable_terminal_turn
  • Not a prompt construction error: promptErrorSource=null

Root Cause

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.

Fix Action

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_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.

Code Example

terminalError = "non_deliverable_terminal_turn"
assistantTexts = []
aborted = false
timedOut = false
idleTimedOut = false
promptErrorSource = null

---

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

---

{
  "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
            }
          }
        ]
      }
    }
  }
}

---

baseUrl = "${AZURE_FOUNDRY_BASE_URL}/openai/v1"
api = "azure-openai-responses"

---

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

---

POST https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1/responses

---

no-tools response: HTTP 200, status=completed, output types included reasoning/message
tools + reasoning response: HTTP 200, status=completed, output type function_call

---

Return exactly: AZURE_RESPONSES_CANARY_OK

---

assistantTexts = ["AZURE_RESPONSES_CANARY_OK"]
finalStatus = "completed" // or equivalent successful terminal status

---

terminalError = "non_deliverable_terminal_turn"
assistantTexts = []
aborted = false
timedOut = false
idleTimedOut = false
promptErrorSource = null

---

{
  "baseUrl": "${AZURE_OPENAI_BASE_URL}/openai/v1",
  "api": "openai-completions",
  "models": [
    {
      "id": "gpt-5.5",
      "reasoning": false,
      "compat": {
        "supportsStore": false,
        "supportsUsageInStreaming": true
      }
    }
  ]
}

---

AZURE_COMPLETIONS_CANARY_OK

---

azure-openai-responses
runResponsesStreamLifecycle
createResponsesAssistantOutput
convertResponsesMessages
assistantTexts
non_deliverable_terminal_turn
collectAssistantTexts

---

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

---

/app/dist/azure-openai-responses-*.js
/app/dist/openai-responses-shared-*.js
/app/dist/selection-*.js

---

{
  "status": "completed",
  "output": [
    { "type": "reasoning", "id": "..." },
    {
      "type": "message",
      "role": "assistant",
      "content": [
        { "type": "output_text", "text": "AZURE_RESPONSES_CANARY_OK" }
      ]
    }
  ]
}

---

assistantTexts === ["AZURE_RESPONSES_CANARY_OK"]
terminalError === undefined

---

{ "type": "text", "text": "AZURE_RESPONSES_CANARY_OK" }
{ "type": "output_text", "text": "AZURE_RESPONSES_CANARY_OK" }

---

Prompt: Return exactly: AZURE_RESPONSES_CANARY_OK
Tools: none
Expected assistantTexts: ["AZURE_RESPONSES_CANARY_OK"]
Expected terminal status: success

---

assistant function_call -> tool_result -> assistant final message

---

{
  "api": "openai-completions",
  "reasoning": false
}
RAW_BUFFERClick to expand / collapse

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:

{
  "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:

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

  1. Configure azure/gpt-5.5 as above using api: "azure-openai-responses" and the Foundry project endpoint.
  2. Run an isolated OpenClaw canary with no tools and a deterministic response instruction, for example:
Return exactly: AZURE_RESPONSES_CANARY_OK
  1. 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:

{
  "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:

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

  • Provider family: Azure / Foundry Responses
  • OpenClaw provider API: azure-openai-responses
  • Symptom class: terminal delivery/extraction failure
  • Primary error string: non_deliverable_terminal_turn
  • Diagnostic marker: assistantTexts=[]
  • Not a transport timeout: aborted=false, timedOut=false, idleTimedOut=false
  • Not a prompt construction error: promptErrorSource=null
  • Not the same as #79570 synthetic refusal / usage.totalTokens == 0

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:

{
  "status": "completed",
  "output": [
    { "type": "reasoning", "id": "..." },
    {
      "type": "message",
      "role": "assistant",
      "content": [
        { "type": "output_text", "text": "AZURE_RESPONSES_CANARY_OK" }
      ]
    }
  ]
}

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:

{ "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:

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

  • #79570: related Azure OpenAI Responses issue, but different symptom. #79570 reports synthetic refusal / 0-token behavior on generic openai-responses; this report is azure-openai-responses producing non_deliverable_terminal_turn with assistantTexts=[] while direct Azure /responses succeeds.
  • Other Azure Responses issues/PRs may be relevant, especially around Azure output item normalization and session replay/fallback behavior.

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_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.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Bug: azure-openai-responses can return non_deliverable_terminal_turn with assistantTexts=[] even when direct Azure /responses succeeds