Skip to content

feat(opencode): native OpenAI and Anthropic passthroughs for Cloudflare AI Gateway - #42634

Merged
rekram1-node merged 4 commits into
devfrom
gateway-native-routing
Aug 17, 2026
Merged

feat(opencode): native OpenAI and Anthropic passthroughs for Cloudflare AI Gateway#42634
rekram1-node merged 4 commits into
devfrom
gateway-native-routing

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Cloudflare AI Gateway models currently all ride the unified OpenAI-compatible `/compat` endpoint. That breaks new OpenAI models (gpt-5.5+/pro reject `tools` + `reasoning_effort` on chat completions and require the Responses API) and squeezes Claude through an OpenAI-shaped body (no native thinking blocks, no `cache_control`, reasoning efforts silently dropped or mistranslated).

This PR routes gateway models through the provider-native passthroughs that `ai-gateway-provider` 3.2 ships:

  • `openai/*` → native OpenAI passthrough on the Responses API
  • `anthropic/*` → native Anthropic passthrough on the Messages API
  • everything else → unified `/compat`, unchanged

The passthrough wrappers inject a `CF_TEMP_TOKEN` sentinel the gateway strips before dispatch, so upstream billing stays on the gateway (Unified Billing / stored BYOK) and the Cloudflare token never reaches a third-party provider.

Changes

  • `provider.ts` loader: prefix routing in `getModel`; keeps the Workers AI token scoping (the Cloudflare token is only forwarded upstream for `workers-ai/` and `@cf/` models — includes fix(provider): scope AI Gateway token to first-party Workers AI models #33597, co-authored)
  • `provider.ts` `cloudflareGatewayNpm`: resolves the native npm (`@ai-sdk/openai` / `@ai-sdk/anthropic`) before variants are computed, so reasoning variants produce payloads the native SDKs understand — Claude effort variants become `thinking` + `output_config.effort` (previously silently dropped), OpenAI variants gain `reasoningSummary` + encrypted reasoning includes for stateless multi-turn
  • `plugin/cloudflare.ts`: removed the `chat.params` maxOutputTokens workaround — it existed because compat couldn't rename `max_tokens` for OpenAI reasoning models; the Responses API accepts `max_output_tokens`, so the hack now just uncapped output
  • Tests: e2e suite asserts the envelope per route (provider + endpoint + wire payload), reasoning-effort fidelity on all three routes, and the token-scoping invariants (`authorization`/`x-api-key` stripped on passthroughs, secret never in the body, Workers AI still receives the token)

Live verification

Tested against a real gateway with Unified Billing: OpenAI models with tools + reasoning efforts (the previously failing case), Claude models, and `workers-ai/@cf/moonshotai/kimi-k2.6` (compat regression). Also live-verified the gateway's boundaries, which shaped this scope: under Unified Billing the legacy endpoint serves exactly `openai/`, `anthropic/`, and `workers-ai/` — Google/xAI fail spend-limit resolution (catalog slug ≠ route prefix) and DeepSeek gets no managed credentials. The models.dev catalog was aligned accordingly (models.dev#4674, #4676, #4693, #4715). Other providers arrive with the REST (`/ai/v1`) transport in V2.

Supersedes #33597 — its token-scoping fix is included here with commit authorship preserved and co-author credit.

Fixes: #40344

keefetang and others added 4 commits June 24, 2026 11:52
#32052 fixed #32051 (Workers AI 401s) by passing apiKey to createUnified,
but applied it to every model — so the Cloudflare API token was sent as the
upstream Authorization header for third-party providers (OpenAI, Anthropic),
causing them to 401 with "Invalid API Key".

Scope token forwarding to be model-aware: attach the Cloudflare token only
for first-party Workers AI models, whose upstream is Cloudflare itself. The
Unified API addresses Workers AI both as "workers-ai/..." and as bare
"@cf/..." ids, so match both; "@cf/" is Cloudflare's reserved namespace, so
this never matches a third-party model. Other providers receive no upstream
Authorization and fall back to the gateway's stored/BYOK keys. Applied in
both the v1 provider (provider.ts) and v2 plugin
(core/.../cloudflare-ai-gateway.ts) paths.

Tests assert both directions, including that third-party sub-requests carry
no upstream authorization header.

Reapplies and extends the approach from #33407.
…ls through native passthroughs

Co-authored-by: Keefe Tang <keefe@pentagram.me>
@rekram1-node
rekram1-node merged commit cba6b5f into dev Aug 17, 2026
13 checks passed
@rekram1-node
rekram1-node deleted the gateway-native-routing branch August 17, 2026 04:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants