Skip to content

cloudflareBindingProvider sends reasoning.effort max on Responses path; Workers AI /run rejects it #544

Description

@Divkix

Describe the Bug

After #525, cloudflareBindingProvider correctly uses the OpenAI Responses wire format for AI Gateway openai/… models. That path still forwards catalog thinking levels straight through, including "max".

For cloudflare/openai/gpt-5.6-luna with thinkingLevel: "max", env.AI.run fails immediately:

Model execution failed (User Input Error): Invalid value at reasoning.effort: Invalid option: expected one of "none"|"low"|"medium"|"high"

AI Gateway logs the call as path /run, model openai/gpt-5.6-luna, status 400.

The interesting part is the split inside the same provider file:

  • chat-completions binding path already clamps:
    high | xhigh | max -> "high" (mapReasoningEffort)
  • Responses binding path does not. applyResponsesReasoning does:
const effort = model.thinkingLevelMap?.[clamped] ?? clamped;
payload.reasoning = { effort, summary: 'auto' };

pi-ai's AI Gateway catalog currently marks Luna as:

thinkingLevelMap: {
  low: "low",
  medium: "medium",
  high: "high",
  xhigh: "xhigh",
  max: "max",
}

So Flue happily emits reasoning.effort: "max", and Workers AI /run rejects it.

Same model + same effort: "max" previously succeeded on the older AI Gateway HTTP Responses path (cloudflare-ai-gateway/gpt-5.6-luna, path responses). This started failing only after moving Support onto the stock binding provider.

This is not a duplicate of #525. #525 was "wrong wire format" (chat vs Responses). This is "Responses path is on, but effort enums are not clamped the way chat already is."

Expected Behavior

For binding-backed OpenAI Responses models:

  1. Either clamp unsupported /run effort values the same way chat already does (max/xhigh -> high, or whatever the binding actually accepts), or
  2. Fail fast client-side with a clear unsupported-level error before calling env.AI.run.

Apps should not get a hard 400 after admission for a thinking level Flue itself accepts and catalogs as valid.

Steps to Reproduce

  1. Worker with ai.binding = "AI" and a named AI Gateway that has OpenAI BYOK.
  2. Register stock binding provider:
import { setProvider } from '@flue/runtime';
import { cloudflareBindingProvider } from '@flue/runtime/cloudflare/workers-ai';

setProvider(
  cloudflareBindingProvider({
    binding: env.AI,
    gateway: { id: 'your-gateway-id', skipCache: true, collectLog: true },
  }),
);
  1. Agent or stream with:
useModel('cloudflare/openai/gpt-5.6-luna', { thinkingLevel: 'max' });
  1. Observe binding /run 400 with the reasoning.effort error above.
  2. Same call with thinkingLevel: 'high' succeeds.
  3. Optional contrast: older HTTP AI Gateway Responses path accepted effort: "max" for the same model.

Environment

  • @flue/runtime 2.0.0 / 2.0.0-nightly.202607240825 (same Responses reasoning code on local main)
  • @earendil-works/pi-ai 0.82.1 / 0.83.0
  • Model: openai/gpt-5.6-luna via binding + named AI Gateway
  • Cloudflare Workers

Workaround

Do not change app config off thinkingLevel: "max". Keep the product pin and patch Flue so Responses binding effort is clamped the same way chat already is (max/xhighhigh) before env.AI.run.

We are shipping that as a temporary pnpm patch on @flue/runtime@2.0.0 and posted the source-form fix in a comment on this issue. When this lands upstream, drop the patch and upgrade Flue; app config stays max.

Metadata

Metadata

Assignees

No one assigned

    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