Skip to content

Add extra_headers for OpenAI-family LLM providers - #1588

Open
uusp wants to merge 1 commit into
TokenRhythm:mainfrom
uusp:feat/llm-extra-headers
Open

uusp wants to merge 1 commit into
TokenRhythm:mainfrom
uusp:feat/llm-extra-headers

Conversation

@uusp

@uusp uusp commented Sep 9, 2026

Copy link
Copy Markdown

Summary

Adds operator-defined extra_headers for OpenAI-family text providers
(openai chat-completions and openai_responses), plumbed from [llm]
config through the runtime (LlmRuntimeConfig) and selector
(ProviderConfig / ProviderBuildContext) into request headers.
Adapter-managed framing (Authorization / Content-Type / Accept)
always wins; the merge is case-insensitive.

Motivation (verified against a live gateway)

The opencode Zen/Go gateway requires x-opencode-session on /responses
and answers 400 MissingSessionID without it:

{"type":"error","error":{"type":"MissingSessionID","message":"Error from provider (Console Go): Request is missing x-opencode-session and cannot be routed efficiently."}}

OpenSquilla had no way to send custom headers — no CLI flag, no schema
field (headers exists only on MemoryEmbeddingRemoteConfig) — so any
model behind such a gateway was unusable through it. Verified live with
curl: same key + endpoint + model fails without the header and succeeds
with it. After this change (plus the header in config), opensquilla agent
completes against that gateway.

Usage

[llm]
provider = "openai_responses"
model = "muse-spark-1.3-contributor"
api_key_env = "GOKEY"
base_url = "https://opencode.ai/zen/go/v1"
extra_headers = { x-opencode-session = "my-session" }

Never store secrets in extra_headers; Authorization cannot be
overridden through it. CLI wizard / Web UI fields for this are intentionally
left out to keep this change small — happy to follow up if wanted.

Tests

  • New tests/test_provider_extra_headers.py: 10 offline tests
    (MockTransport wire assertions for both adapters including list_models,
    reserved-header protection, selector plumbing, config parsing). 10/10 pass.
  • ruff check clean on all touched files.
  • Related suites green: test_provider_openai_responses +
    test_provider_selector (56 passed), test_provider_stream_contract +
    test_gateway_config_default_provider (43 passed).
  • Full suite and webui build not run locally (no frontend changes; full
    suite includes live tests — leaving those to CI).

Linked Issues: None

Routing gateways in front of a model API sometimes require extra HTTP headers (e.g. opencode Zen/Go answers 400 MissingSessionID on /responses without x-opencode-session). This carries operator-defined headers from [llm] config through the runtime and selector into the OpenAI chat and responses adapters. Adapter-managed framing (Authorization/Content-Type/Accept) always wins. Covered by offline tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant