Skip to content

[Bug]: @ai-sdk/openai headers not forwarded to HTTP requests when using Responses API with APIM #18089

Closed as not planned

Description

@tbrandenburg

Summary

OpenCode's bundled @ai-sdk/openai implementation fails to forward constructor-level headers to HTTP requests when using the OpenAI Responses API, causing 401 "missing" errors with Azure API Management (APIM) and other services that require custom authentication headers.

Problem Details

Text-level substitution works correctly - environment variables like {env:AZURE_APIM_KEY} are properly resolved in configuration.

However, when using GPT-5+ models (which trigger shouldUseCopilotResponsesApi), the headers from createOpenAI({ headers: {...} }) constructor are not included in the actual HTTP requests to the /responses endpoint.

Evidence

  1. Azure APIM reports "missing" (not "invalid") - indicates header never arrives
  2. Text substitution confirmed working - {env:AZURE_APIM_KEY} resolves to real key
  3. Only affects Responses API - Chat Completions API works fine with same config
  4. Model-specific routing - GPT-4 works, GPT-5+ fails (due to API switching)

Root Cause Analysis

OpenCode has two different @ai-sdk/openai implementations:

  1. Official @ai-sdk/openai (line 116 in BUNDLED_PROVIDERS) - works correctly
  2. Custom GitHub Copilot implementation (line 131) - used for GPT-5+ models via Responses API

The issue is in the custom implementation path:

createOpenAI({ headers }) → 
shouldUseCopilotResponsesApi(modelID) → 
createGitHubCopilotOpenAICompatible() → 
OpenAIResponsesLanguageModel

The headers from the original createOpenAI({ headers }) constructor don't make it through this chain to the final HTTP requests.

Affected Code Locations

  • packages/opencode/src/provider/provider.ts:55 - shouldUseCopilotResponsesApi routing logic
  • packages/opencode/src/provider/provider.ts:190-199 - GitHub Copilot custom loader
  • packages/opencode/src/provider/sdk/copilot/copilot-provider.ts:78-83 - Custom provider creation
  • packages/opencode/src/provider/sdk/copilot/responses/openai-responses-language-model.ts:409,782 - Header forwarding logic (correct but receives no headers)

Reproduction

Working Configuration (GPT-4)

{
  "provider": {
    "openai": {
      "options": {
        "apiKey": "{env:OPENAI_API_KEY}",
        "baseURL": "https://my-apim.azure-api.net/openai",
        "headers": {
          "Ocp-Apim-Subscription-Key": "{env:AZURE_APIM_KEY}"
        }
      }
    }
  }
}

Broken Configuration (GPT-5+)

Same config, different model triggers custom Responses API implementation and headers are lost.

Expected Behavior

Headers from createOpenAI({ headers }) constructor should be forwarded to all HTTP requests regardless of whether the model uses Chat Completions API or Responses API.

Actual Behavior

  • GPT-4 (Chat API): Headers forwarded ✅
  • GPT-5+ (Responses API): Headers missing ❌

Impact

  • Azure APIM integration broken for GPT-5+ models
  • Enterprise proxies requiring custom auth headers fail
  • Inconsistent behavior between model families
  • Silent failures - no error indicating headers were dropped

Workaround Approaches Tried

  1. Provider-level headers (options.headers) - ❌ Not forwarded
  2. Model-level headers (models.{model}.headers) - ❌ Not forwarded
  3. Custom User-Agent - ❌ Not forwarded

Related Issues

Environment

  • OpenCode version: v1.2.x
  • Provider: @ai-sdk/openai
  • Models affected: gpt-5, gpt-5.1, gpt-5.2, etc. (any model triggering Responses API)
  • Models working: gpt-4, gpt-4-turbo, etc. (Chat Completions API)

Fix Direction

The headers need to be properly passed through the custom provider chain:
createOpenAI options → GitHub Copilot provider → OpenAI Responses model → HTTP requests

Likely requires updating the header passing logic in the custom loader or provider creation chain.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 18, 2026
  2. tbrandenburg commented on Apr 19, 2026

    @tbrandenburg
    Author

    Status check against v1.14.17 (current as of 2026-04-19)

    Partially still relevant, but the scope has narrowed.

    What changed since the original report

    The original report was filed against v1.2.x. Since then the codebase was significantly restructured in the provider layer. The key change relevant to this issue: the @ai-sdk/github-copilot bundled provider now uses a custom copilot provider (packages/opencode/src/provider/sdk/copilot/copilot-provider.ts) that explicitly accepts and forwards headers through both the chat and responses model constructors via a getHeaders closure (lines 60-83). So for the GitHub Copilot provider specifically, headers should now be forwarded to the Responses API path.

    What is still broken

    The original report describes using the openai provider (not github-copilot) with a custom baseURL pointing to an APIM gateway. In that case:

    1. provider.options.headers from user config is correctly merged in resolveSDK (provider.ts:1382+1415-1419) and passed to @ai-sdk/openai@3.0.53 as constructor options.
    2. The routing between Chat Completions and Responses API is still done via shouldUseCopilotResponsesApi (provider.ts:34-38) — this only triggers for models named gpt-5+, and only for the github-copilot custom loader (lines 191-199). The plain openai provider does not go through this routing — it uses sdk.languageModel(modelID) by default (line 1551).
    3. For the plain openai provider, whether headers reach the Responses API endpoint depends entirely on whether @ai-sdk/openai v3.0.53 forwards constructor headers to its Responses implementation — this is an upstream SDK concern, not an opencode one.

    Current code paths

    • openai provider + gpt-5+ model: Uses @ai-sdk/openai@3.0.53 via sdk.languageModel(). Headers forwarding is upstream SDK responsibility.
    • github-copilot provider + gpt-5+ model: Uses the custom copilot provider, which explicitly forwards headers to OpenAIResponsesLanguageModel. Likely fixed.
    • Model-level headers (model.headers in config): Applied at resolveSDK line 1415 and merged into the constructor options before SDK instantiation. Should work for both paths.

    Recommendation

    If you're hitting this with the openai provider pointing at an APIM, the fix is to use model-level headers in config (which are merged at SDK construction time) rather than provider-level options.headers. If that also doesn't work with `@ai-sdk/openai@3.0.53, the issue is upstream in the AI SDK and should be filed there.

    If you're hitting this with the github-copilot provider, test with current v1.14.17 — the custom copilot provider now forwards headers through getHeaders to both chat and responses models.

  3. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  4. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions