Repository navigation
Reasoning routing: effortMode=force with targetEffort=none does not remove effort fields (REASONING_ROUTING.md vs 3.8.52 behavior) #18543
Replies: 2 comments
|
In v3.8.52, this is an explicit behavior in the implementation, rather than a missing removal branch. In ""applyReasoningRuleDirective"" (https://github.com/cheaper-inference/OmniRoute/blob/v3.8.52/src/lib/reasoningRouting/policy.ts), "force" + "none" first calls "clearReasoning(body)", then sets: body.reasoning_effort = "none"; The accompanying comment explains why: some providers enable thinking when the field is absent, so omission would not reliably mean “disable thinking.” It delegates handling of providers that reject literal "none" to the dispatch-time sanitizer. That explains why your rule matches and budgets disappear, but "reasoning_effort" remains. The "v3.8.52 documentation" (https://github.com/cheaper-inference/OmniRoute/blob/v3.8.52/docs/routing/REASONING_ROUTING.md) does disagree with that implementation. For your Cloudflare case, the distinction is therefore between “disable thinking” and “omit unsupported request fields.” Those need different provider-aware handling; changing the rule priority would not fix this branch. AI-assisted analysis: I ran the extracted v3.8.52 directive function and its helper functions locally and reproduced "{"reasoning_effort":"none"}". I have not tested the full proxy or a live Cloudflare request. |
|
@SmiLoDoN161 @shoka-jp has it right, and the docs are the part that's wrong. Since #14873, The rule then relies on the dispatch sanitizer ( |
Uh oh!
There was an error while loading. Please reload this page.
Version: 3.8.52 (observed 2026-10-29) · Docs:
docs/routing/REASONING_ROUTING.mdWhat the docs promise
What actually happens
Rule created via
POST /api/settings/reasoning-routing-rules:{"scope":"combo","comboId":"<combo>","sourceEffort":"none","effortMode":"force","targetEffort":"none","budgetAction":"remove","targetKind":"keep"}POST /api/settings/reasoning-routing-rules/simulate→matched: trueREASONING_ROUTE Rule <id>: <combo>/none -> <combo>/none_omnirouteReasoningRulemarker(
effortMode: force, targetEffort: none, budgetAction: remove)…but the upstream body still contains
"reasoning_effort": "none"verbatim instead of omitting the field.Repro
none, forcenone).POST /v1/chat/completionswith that combo asmodeland"reasoning_effort":"none".request_body):reasoning_effort: "none"is still there.Control: flipping the same rule to
targetEffort: "low"rewrites the field correctly(
reasoning_effort: "low", plusreasoning.effort/output_config.effort), so the pipelineworks — only the removal branch seems missing.
Why it matters
Some upstreams reject
reasoning_effort: "none"on their OpenAI-compatible endpoint —Cloudflare Workers Ai answers exactly this value with
400 AiError: Invalid input (code 8001),while
low/mediumand an absent field are accepted. With the documented removal we would stripthe field and hit the provider on the first try; today the only workaround is forcing a non-
nonevalue, which costs extra thinking tokens + seconds on lightweight internal subcalls
(command-approval gate / session-title calls fire with
effort=none).Expected
effortMode: force+targetEffort: noneremovesreasoning_effort/reasoning.effort/output_config.effort(+ budget fields) from the upstream request — as documented — or thedoc is corrected if removal is intentionally budget-only.
Happy to capture and paste the exact wire body from a repro build if useful.
All reactions