DEV Community

Ahab
Ahab

Posted on Originally published at indieseek.co

Qwen Code 0.23.3 adds an OpenAI Responses provider: migrate with replay and SSE canaries

Qwen Code 0.23.3 adds an OpenAI Responses provider: migrate with replay and SSE canaries

Quick answer

Qwen Code 0.23.3 adds an opt-in openai-responses model provider that talks directly to /v1/responses over HTTP and server-sent events. It supports streamed output, tool calls, reasoning summaries, and replay of encrypted reasoning when the endpoint returns reasoning.encrypted_content.

Do not switch an existing automation fleet by renaming an openai provider. The two wires have different request, stream, and reasoning contracts. Pin 0.23.3, add a separate provider entry, run one fresh-session canary and one saved-session replay, then prove that an HTTP 200 followed by an SSE error still becomes a visible terminal failure. Promote only after you have provider identity, response, tool, error, and rollback receipts.

This release does not make every OpenAI-compatible endpoint Responses-compatible. Your configured baseUrl must implement the expected /v1/responses contract.

Who this is for

This guide is for developers routing Qwen Code through OpenAI or another endpoint that explicitly supports the Responses API, especially when long sessions, reasoning continuity, custom headers, or unattended retries matter.

It is a provider migration, not an external-agent handoff. If your task is delegating a child turn to another coding agent, use the Qwen Code ACP delegation checklist. If you expose sessions over a network, separately apply the Remote Serve token and QR checklist.

What changed in 0.23.3

The stable 0.23.3 release, published September 10, includes the new Responses content generator and a follow-up fix that preserves provider error details from streamed responses. The npm package and release tag resolve to commit b695664b8df06d06c625db3e30b97045d82092c7.

The tagged provider documentation uses a bare array under modelProviders. A built-in openai-responses entry routes automatically; a friendly custom provider id also needs a top-level providerProtocol mapping. Credentials belong in an environment variable, not in the settings file.

{
  "modelProviders": {
    "responses-canary": [
      {
        "id": "your-supported-model",
        "envKey": "RESPONSES_CANARY_API_KEY",
        "baseUrl": "https://your-endpoint.example/v1",
        "generationConfig": {
          "timeout": 60000,
          "reasoning": { "effort": "high" }
        }
      }
    ]
  },
  "providerProtocol": {
    "responses-canary": "openai-responses"
  }
}
Enter fullscreen mode Exit fullscreen mode

Use a real model id documented by your endpoint. The example intentionally does not claim that any particular third-party model implements the protocol.

Migration boundary matrix

Surface Verify on the Responses route Hold condition
Provider selection /model shows the canary id and the request reaches the intended host Entry is skipped, wrong route receives traffic, or identity is ambiguous
Streaming Only text/event-stream is accepted and deltas assemble once Buffered JSON, duplicated text, or a silent empty success
Tools Arguments, call id, result, and final answer stay paired Orphaned, duplicated, or reordered tool calls
Reasoning Visible summary renders; encrypted content replays only when returned Resume depends on opaque state the endpoint never supplied
Errors HTTP failures and in-stream response.failed details reach logs safely HTTP 200 hides a provider failure or triggers unbounded retries
Secrets URL and headers are redacted in diagnostics API key or URL credential appears in logs

A seven-stage canary workflow

1. Freeze the runtime and route

Record Qwen Code 0.23.3, package integrity, tag commit, settings-file hash, provider id, model id, normalized host, and secret variable name. Never record the secret value. Resolve the actual CLI binary; a successful install is not proof that the running process uses it.

2. Keep the old provider intact

Add responses-canary beside the current route instead of editing the production entry. Select it explicitly for one disposable repository. Keep the prior provider id and model pinned as the rollback target.

3. Run a fresh-session contract test

Ask for a deterministic short response, then one harmless read-only tool call. Capture the request id or provider receipt, streamed text, tool call id, tool result, final terminal state, latency, and usage if available. Reject partial output presented as success.

4. Test reasoning controls

Run once with configured reasoning.effort, then a request-level operation with thinking disabled. The tagged documentation says thinkingConfig.includeThoughts: false is honored for one-off calls. Do not send extra_body.enable_thinking as if it were a native Responses field; set reasoning.effort directly.

If the endpoint streams visible reasoning but does not return encrypted content, visible summaries may work while opaque replay cannot. Record those as separate capabilities.

5. Replay a saved session

Resume the canary and ask a question that depends on the prior turn. When a newly selected route explicitly rejects stored reasoning ids, Qwen's implementation can send the original request once, then retry at most once after removing incompatible opaque reasoning payloads for that request. It preserves visible summaries and does not rewrite saved history.

Treat that as bounded recovery, not proof of cross-provider portability. Unknown or malformed errors do not get the special retry.

6. Inject stream and input failures

Use a mock or test endpoint to exercise a non-2xx response, malformed content type, dropped SSE connection, nested error, top-level error, and response.failed. Also send one unsupported image fixture: the generator is designed to convert unsupported or malformed image input into an in-band text notice instead of aborting the whole request. Verify that notice cannot be confused with model output.

The follow-up stream fix maps too_many_requests to 429 so existing status handling may retry. Assign retry ownership to one layer and cap attempts. Use the OpenAI API 429 runbook to separate provider throttling from whole-run spend control.

7. Decide, promote, or roll back

Move one low-risk workflow only after both fresh and resumed sessions pass. Roll back if provider identity is unclear, a tool call loses its result, any in-stream failure becomes success, secrets appear in diagnostics, or replay requires more than the documented bounded recovery.

Copyable acceptance record

date / owner / workspace:
qwen_version / package_integrity / tag_commit:
settings_hash / provider_id / provider_protocol:
model_id / normalized_host / secret_variable_name:
fresh_request_receipt / terminal_state:
stream_content_type / assembled_output_hash:
tool_call_id / result_id / final_answer:
reasoning_summary / encrypted_replay_available:
resume_receipt / sanitized_retry_count:
http_error / sse_error / response_failed_result:
unsupported_image_notice:
secret_scan_result / retry_owner / retry_cap:
rollback_provider / rollback_test:
decision: hold | limited-rollout | promote | rollback
Enter fullscreen mode Exit fullscreen mode

Common mistakes

  • Reusing an openai Chat Completions entry and assuming the wire changes automatically.
  • Putting the API key itself in envKey instead of the environment variable name.
  • Calling visible reasoning a guarantee that encrypted replay is available.
  • Treating HTTP 200 as success before the SSE stream reaches a valid terminal event.
  • Letting the provider client, proxy, and job runner all retry the same 429.
  • Logging a credential-bearing URL while debugging custom headers.

Building something? Turn your product page into a show people want to watch with PromoFast—hosted, embeddable, and ready to export.

FAQ

Is openai-responses the same as the existing openai provider?

No. The existing provider uses the OpenAI SDK and Chat Completions-compatible wire. openai-responses sends direct HTTP/SSE requests to /v1/responses and has a different reasoning-replay contract.

Will any OpenAI-compatible proxy work?

Not necessarily. The endpoint must support the Responses request shape, SSE events, and the features your workflow uses. Test the actual host and model combination.

Does Qwen rewrite saved history during reasoning recovery?

The merged implementation says no. Its compatibility recovery sanitizes one retried request, preserves visible summaries, and does not rewrite stored history. Still back up important sessions and verify replay with your endpoint.

Does 0.23.3 guarantee automatic recovery from every provider error?

No. The special reasoning-id recovery is narrow, and the stream fix preserves known nested or top-level error details. Unknown or malformed errors should remain visible terminal failures.

Sources

Originally published on IndieSeek.

Top comments (0)