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:
- Either clamp unsupported
/run effort values the same way chat already does (max/xhigh -> high, or whatever the binding actually accepts), or
- 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
- Worker with
ai.binding = "AI" and a named AI Gateway that has OpenAI BYOK.
- 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 },
}),
);
- Agent or stream with:
useModel('cloudflare/openai/gpt-5.6-luna', { thinkingLevel: 'max' });
- Observe binding
/run 400 with the reasoning.effort error above.
- Same call with
thinkingLevel: 'high' succeeds.
- 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/xhigh → high) 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.
Describe the Bug
After #525,
cloudflareBindingProvidercorrectly uses the OpenAI Responses wire format for AI Gatewayopenai/…models. That path still forwards catalog thinking levels straight through, including"max".For
cloudflare/openai/gpt-5.6-lunawiththinkingLevel: "max",env.AI.runfails immediately:AI Gateway logs the call as path
/run, modelopenai/gpt-5.6-luna, status400.The interesting part is the split inside the same provider file:
high | xhigh | max -> "high"(mapReasoningEffort)applyResponsesReasoningdoes:pi-ai's AI Gateway catalog currently marks Luna as:
So Flue happily emits
reasoning.effort: "max", and Workers AI/runrejects it.Same model + same
effort: "max"previously succeeded on the older AI Gateway HTTP Responses path (cloudflare-ai-gateway/gpt-5.6-luna, pathresponses). 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:
/runeffort values the same way chat already does (max/xhigh->high, or whatever the binding actually accepts), orenv.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
ai.binding = "AI"and a named AI Gateway that has OpenAI BYOK./run400 with thereasoning.efforterror above.thinkingLevel: 'high'succeeds.effort: "max"for the same model.Environment
@flue/runtime2.0.0/2.0.0-nightly.202607240825(same Responses reasoning code on local main)@earendil-works/pi-ai0.82.1/0.83.0openai/gpt-5.6-lunavia binding + named AI GatewayWorkaround
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/xhigh→high) beforeenv.AI.run.We are shipping that as a temporary
pnpmpatch on@flue/runtime@2.0.0and posted the source-form fix in a comment on this issue. When this lands upstream, drop the patch and upgrade Flue; app config staysmax.