Skip to content

fix: send reasoning_effort="none" so gpt-5.6 models accept function tools - #479

Open
ivancrneto wants to merge 1 commit into
ReflexioAI:mainfrom
ivancrneto:fix/gpt-5.6-function-tools
Open

fix: send reasoning_effort="none" so gpt-5.6 models accept function tools#479
ivancrneto wants to merge 1 commit into
ReflexioAI:mainfrom
ivancrneto:fix/gpt-5.6-function-tools

Conversation

@ivancrneto

@ivancrneto ivancrneto commented Sep 4, 2026

Copy link
Copy Markdown

The problem

OpenAI rejects function tools on /v1/chat/completions for every gpt-5.6 variant while reasoning is on:

Function tools with reasoning_effort are not supported for gpt-5.6-luna in /v1/chat/completions. To use function tools, use /v1/responses or set reasoning_effort to 'none'.

The extraction agent is a tool loop on chat/completions, so this makes the whole gpt-5.6 family unusable for extraction — and there is currently no way to reach reasoning_effort from configuration (no LLMConfig field, no extra_body, no kwargs passthrough).

Two things make it unpleasant to diagnose:

  1. It looks partial. Non-tool calls to the same model keep succeeding, so generation and evaluation appear healthy while every extraction fails.
  2. LiteLLM hides the cause. It masks the provider message behind a TypeError of its own — BadRequestError.__init__() missing 2 required positional arguments: 'model' and 'llm_provider' — so the logs never show the sentence above.

I hit this on a self-hosted deployment: pointing the org config at gpt-5.6-luna failed 9 extraction runs in ~9 minutes before I rolled back, with only that TypeError to go on.

The fix

Follows the existing TEMPERATURE_RESTRICTED_MODELS idiom rather than inventing a new one:

  • TOOLS_REQUIRE_REASONING_DISABLED_MODELS = {"gpt-5.6"}, declared next to TEMPERATURE_RESTRICTED_MODELS with the API error quoted in a comment.
  • _tools_require_reasoning_disabled(), mirroring _is_temperature_restricted_model() — same prefix-strip for provider routing (openrouter/openai/gpt-5.6-luna), same startswith matching.
  • In _build_completion_params, when the request carries tools and the model matches, default reasoning_effort to "none".

Scope is deliberately narrow:

  • setdefault, placed before params.update(kwargs), so an explicit caller-supplied reasoning_effort still wins.
  • Non-tool calls to gpt-5.6 keep reasoning enabled — only the tools path is affected.
  • No other model is touched.

Verification

Against the live OpenAI API through LiteLLM (1.89.3), using the same drop_params=True the client sets — that mattered, because if LiteLLM stripped the parameter the fix would be inert:

call result
gpt-5.6-luna + tools + reasoning_effort="none" tool call returned
gpt-5.6-luna + tools, no reasoning_effort the 400 above
gpt-5.6-terra + tools, no reasoning_effort the same 400
gpt-5.5 + tools unaffected, works either way

Added 16 unit tests in TestToolsRequireReasoningDisabled, mirroring TestTemperatureRestriction: affected/unaffected model matching, provider-prefix stripping, and four param-level tests driving generate_chat_response through a patched litellm.completion — tools set it, no-tools does not, unaffected models are untouched, and an explicit caller value survives.

pytest tests/server/llm/719 passed, all 16 new tests among them.

Two caveats on my local run, since I would rather state them than let them look like passes:

  • test_litellm_client.py::test_installed_litellm_transport_round_trip fails on a clean checkout of main here too — pre-existing in my environment, unrelated.
  • test_embedding_service_model_contract.py failures vary between runs in my environment (1 of 3 on clean main, 3 of 3 with this branch, 0 of 3 in isolation on both). They also collect before the file I touched, so they cannot be affected by these tests. I believe it is local flakiness around the HF model download, but I could not fully rule it out locally — worth a glance at CI.

Alternatives considered

  • Routing gpt-5.6 tool calls to /v1/responses, as the error suggests. Correct long-term, but a much larger change than making the completions path work.
  • Exposing reasoning_effort as an LLMConfig field. Useful on its own, but it would leave the default broken — callers would have to know to set it. Happy to add it as well, or instead, if you would prefer that shape.

Summary by CodeRabbit

  • Bug Fixes
    • Improved compatibility with GPT-5.6 models when function tools are used.
    • Reasoning is automatically disabled in affected tool-enabled requests when no explicit setting is provided.
    • Explicit reasoning preferences remain unchanged, and unaffected models and requests without tools continue to behave as before.

…ools

OpenAI rejects function tools on /v1/chat/completions for every gpt-5.6
variant while reasoning is on:

  Function tools with reasoning_effort are not supported for gpt-5.6-luna
  in /v1/chat/completions. To use function tools, use /v1/responses or set
  reasoning_effort to 'none'.

That makes gpt-5.6 unusable for the extraction agent, which is a tool loop
on chat/completions, and there is currently no way to reach the parameter
from configuration. The failure is easy to misread: non-tool calls to the
same model keep succeeding, so extraction fails while generation looks
healthy. LiteLLM compounds it by masking the provider message behind a
TypeError of its own (BadRequestError.__init__() missing 2 required
positional arguments: 'model' and 'llm_provider').

Add TOOLS_REQUIRE_REASONING_DISABLED_MODELS alongside the existing
TEMPERATURE_RESTRICTED_MODELS set, with a matching
_tools_require_reasoning_disabled helper that strips provider routing
prefixes the same way. When a request carries tools and the model is in
that set, default reasoning_effort to "none".

setdefault, placed before params.update(kwargs), so an explicit
caller-supplied reasoning_effort still wins. Non-tool calls to gpt-5.6 keep
reasoning enabled, and no other model is affected.
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: 0d448e69-9f61-4e9a-9314-6cc5bbad0a9a

📥 Commits

Reviewing files that changed from the base of the PR and between 695070a and ed58d0d.

📒 Files selected for processing (2)
  • reflexio/server/llm/_litellm_text_generation.py
  • tests/server/llm/test_litellm_client_unit.py

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The change detects GPT-5.6 model variants when function tools are used and injects reasoning_effort="none" unless the caller provides another value. Unit tests cover model matching, provider prefixes, tool presence, unaffected models, and overrides.

Changes

Tool reasoning compatibility

Layer / File(s) Summary
Affected model detection
reflexio/server/llm/_litellm_text_generation.py
Adds the affected-model set and detects matching model names after lowercasing and removing provider prefixes.
Completion parameter handling and validation
reflexio/server/llm/_litellm_text_generation.py, tests/server/llm/test_litellm_client_unit.py
Sets reasoning_effort to "none" for affected tool calls while preserving explicit caller values. Tests cover tool and non-tool calls, model variants, prefixes, unaffected models, and overrides.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to ed58d

Tool-enabled GPT-5.6 chat-completion requests now disable reasoning by default to avoid provider rejection, while explicit settings and other request types retain their existing behavior. The change is ready to merge.

Suggested reviewers: yyiilluu, guangyu-reflexio, yilu331

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: setting reasoning_effort="none" for gpt-5.6 models so they accept function tools.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

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