Skip to content

Convert 'thinking' parameter to 'reasoning_effort' for Claude models - #28031

Closed
coderback wants to merge 5 commits into
BerriAI:litellm_internal_stagingfrom
coderback:fix/github-copilot-claude-reasoning-effort
Closed

Convert 'thinking' parameter to 'reasoning_effort' for Claude models#28031
coderback wants to merge 5 commits into
BerriAI:litellm_internal_stagingfrom
coderback:fix/github-copilot-claude-reasoning-effort

Conversation

@coderback

@coderback coderback commented May 15, 2026

Copy link
Copy Markdown

…t' for Claude models

Relevant issues

Fixes #25666

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

=============================== test session starts ===============================
platform win32 -- Python 3.12.11, pytest-9.0.3, pluggy-1.6.0 -- C:\Users\tobio\PycharmProjects\litellm\.venv\Scripts\python.exe
codspeed: 4.3.0 (disabled, mode: walltime, callgraph: not supported, timer_resolution: 100.0ns)
cachedir: .pytest_cache
rootdir: C:\Users\tobio\PycharmProjects\litellm
configfile: pyproject.toml
plugins: anyio-4.13.0, ddtrace-2.19.0, langsmith-0.8.0, logfire-4.6.0, asyncio-1.3.0, codspeed-4.3.0, cov-5.0.0, mock-3.15.1, postgresql-7.0.2, recording-0.13.4, rerunfailures-15.1, retry-1.7.0, timeout-2.4.0, xdist-3.8.0, requests-mock-1.12.1, respx-0.22.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=function
collected 19 items                                                                 

tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_completion_github_copilot_mock_response PASSED [  5%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_copilot_vision_request_header_text_only PASSED [ 10%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_copilot_vision_request_header_with_image PASSED [ 15%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_copilot_vision_request_header_with_type_image_url PASSED [ 21%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_get_supported_openai_params_case_insensitive PASSED [ 26%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_get_supported_openai_params_claude_model PASSED [ 31%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_github_copilot_config_get_openai_compatible_provider_info PASSED [ 36%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_map_openai_params_converts_thinking_to_reasoning_effort PASSED [ 42%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_map_openai_params_disabled_thinking_is_dropped PASSED [ 47%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_map_openai_params_no_thinking_leaves_params_unchanged PASSED [ 52%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_map_openai_params_thinking_does_not_overwrite_existing_reasoning_effort PASSED [ 57%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_transform_messages_disable_copilot_system_to_assistant PASSED [ 63%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_agent_request_with_assistant PASSED [ 68%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_agent_request_with_tool PASSED [ 73%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_empty_messages PASSED [ 78%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_mixed_messages_with_agent_roles PASSED [ 84%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_system_only_messages PASSED [ 89%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_user_only_messages PASSED [ 94%]
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py::test_x_initiator_header_user_request PASSED [100%]

=============================== 19 passed in 1.97s ================================

Type

🐛 Bug Fix

Changes

  • Added map_openai_params override to GithubCopilotConfig in litellm/llms/github_copilot/chat/transformation.py
  • When thinking (Anthropic-native) is passed for a github_copilot/claude-* model, it is now converted to reasoning_effort before the request is forwarded to the Copilot API
  • Budget token thresholds: ≥10000→high, ≥5000→medium, ≥2000→low, <2000→minimal
  • Existing reasoning_effort is never overwritten if already set
  • Added 4 unit tests in tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py covering all conversion tiers and edge cases

@coderback

Copy link
Copy Markdown
Author

@greptileai

@greptile-apps

greptile-apps Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a map_openai_params override to GithubCopilotConfig that converts the Anthropic-native thinking parameter into OpenAI-compatible reasoning_effort values before requests are forwarded to the GitHub Copilot API, while leaving non-Claude models unaffected.

  • Converts thinking.budget_tokens to reasoning_effort tiers (high/medium/low/minimal) for Claude models; thinking.type == \"disabled\" is silently dropped.
  • Guards the conversion so a pre-existing reasoning_effort in either non_default_params or optional_params is never overwritten; adds seven mock-only unit tests covering all tiers and edge cases.

Confidence Score: 5/5

Safe to merge; the conversion logic is correctly scoped to Claude models and the no-overwrite invariant now holds for both param sources.

All previously raised blocking concerns have been addressed in this version of the code: non-Claude models are no longer affected, budget_tokens: None is handled via 'or 0', and reasoning_effort already present in optional_params is now checked before conversion. The one remaining inconsistency — the elif branch promoting reasoning_effort for any Claude model without also checking supports_reasoning, unlike get_supported_openai_params — is a low-risk edge case because GitHub Copilot only surfaces reasoning-capable Claude models in practice.

No files require special attention for merge safety.

Important Files Changed

Filename Overview
litellm/llms/github_copilot/chat/transformation.py Adds map_openai_params override to translate Anthropic thinking → OpenAI reasoning_effort for Claude models routed through GitHub Copilot; logic is sound for the common case, with a minor inconsistency in the elif guard vs get_supported_openai_params.
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py Adds 7 new unit tests covering all budget-token tiers, disabled thinking, no-thinking passthrough, and the two guard-invariant cases (reasoning_effort in non_default_params and in optional_params); all tests are mock-only and meet the repo's test-integrity requirements.

Reviews (11): Last reviewed commit: "fix(transformation): prevent 'reasoning_..." | Re-trigger Greptile

Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
Comment thread litellm/llms/github_copilot/chat/transformation.py
@greptile-apps

greptile-apps Bot commented May 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a map_openai_params override to GithubCopilotConfig that translates the Anthropic-native thinking parameter into reasoning_effort before forwarding requests to the GitHub Copilot API, fixing issue #25666 where Claude models on GitHub Copilot received an unrecognised thinking key.

  • Budget tokens are mapped to reasoning_effort tiers (minimal/low/medium/high) using fixed thresholds (2 000 / 5 000 / 10 000), with thinking type disabled silently dropped and any pre-existing reasoning_effort value supposed to take precedence.
  • Four unit tests are added covering all conversion tiers and the "don't overwrite existing reasoning_effort" invariant, though the guard implementation only checks non_default_params and misses the case where a value is already present in optional_params.
  • The thinking pop is applied unconditionally to all models under GithubCopilotConfig, not just Claude models, so a thinking param passed to a non-Claude model with drop_params=False is silently swallowed instead of surfacing an unsupported-param error.

Confidence Score: 3/5

The translation logic works for the happy path, but the guard that is meant to protect an already-set reasoning_effort value is incomplete and can silently overwrite it when the value lives in optional_params rather than non_default_params.

The core conversion is correct and tests pass. However, the never-overwrite invariant stated in the PR description is not fully enforced — the check only reads from non_default_params while the method signature also accepts a non-empty optional_params. A caller who has already placed reasoning_effort into optional_params will have it silently replaced by the budget-token mapping, which is the exact behaviour the guard was written to prevent. The tests do not cover this path, so the gap went undetected.

litellm/llms/github_copilot/chat/transformation.py — specifically the existing_reasoning_effort guard and the unconditional thinking pop on line 154.

Important Files Changed

Filename Overview
litellm/llms/github_copilot/chat/transformation.py Adds map_openai_params override to translate Anthropic thinking to reasoning_effort; the guard for an already-set reasoning_effort only inspects non_default_params, so a value pre-placed in optional_params can be silently overwritten; thinking is also unconditionally dropped for all models, not just Claude models.
tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py Adds 4 new unit tests covering the main conversion tiers and the "don't overwrite existing reasoning_effort" guard, but is missing a test for the case where reasoning_effort is pre-set in optional_params (the actual bug path).

Reviews (2): Last reviewed commit: "fix(transformation): convert 'thinking' ..." | Re-trigger Greptile

Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: This PR is currently BLOCKED from merge.

Score: 2/5

Why blocked:

  • 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.) (pr_related_failures, -2 pts)
  • Greptile 3/5 (greptile_low, -1 pts)

Details: Score docked for: 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.); Greptile 3/5.

Fix the issues above and push an update — the bot will re-review automatically.

Note: This bot is still in beta and might not always work as expected. Please share any feedback via Slack.

…king' is handled correctly for Claude models
@coderback

Copy link
Copy Markdown
Author

@greptileai

@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: This PR is currently BLOCKED from merge.

Score: 2/5

Why blocked:

  • 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.) (pr_related_failures, -2 pts)
  • Greptile 3/5 (greptile_low, -1 pts)

Details: Score docked for: 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.); Greptile 3/5.

Fix the issues above and push an update — the bot will re-review automatically.

Note: This bot is still in beta and might not always work as expected. Please share any feedback via Slack.

@coderback

Copy link
Copy Markdown
Author

@greptileai

@coderback
coderback marked this pull request as draft May 16, 2026 07:24
@coderback
coderback marked this pull request as ready for review May 16, 2026 07:24
@coderback
coderback marked this pull request as draft May 16, 2026 07:24
@coderback
coderback marked this pull request as ready for review May 16, 2026 07:24
Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
@codecov

codecov Bot commented May 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@coderback

Copy link
Copy Markdown
Author

@greptile

Comment thread litellm/llms/github_copilot/chat/transformation.py Outdated
@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: This PR is currently BLOCKED from merge.

Score: 2/5

Why blocked:

  • 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.) (pr_related_failures, -2 pts)
  • Greptile 3/5 (greptile_low, -1 pts)

Details: Score docked for: 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.); Greptile 3/5.

Fix the issues above and push an update — the bot will re-review automatically.

Note: This bot is still in beta and might not always work as expected. Please share any feedback via Slack.

@coderback

Copy link
Copy Markdown
Author

@greptileai

@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: This PR is currently BLOCKED from merge.

Score: 2/5

Why blocked:

  • 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.) (pr_related_failures, -2 pts)
  • Greptile 3/5 (greptile_low, -1 pts)

Details: Score docked for: 1 PR-related CI failure (Greptile gate: score 3/5 below required 4/5 — request a Greptile review (@greptileai) and resolve its comments before maintainer review.); Greptile 3/5.

Fix the issues above and push an update — the bot will re-review automatically.

Note: This bot is still in beta and might not always work as expected. Please share any feedback via Slack.

@coderback

Copy link
Copy Markdown
Author

@greptileai provide a new summary

@coderback

Copy link
Copy Markdown
Author

@greptileai

Comment on lines +172 to +175
elif budget_tokens >= 2000:
reasoning_effort = "low"
else:
reasoning_effort = "minimal"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The "minimal" value is not part of the standard reasoning_effort enum recognised by OpenAI-compatible APIs (valid values are "low", "medium", "high"). GitHub Copilot proxies to an OpenAI-compatible endpoint, so sending "minimal" for any request whose budget_tokens falls below 2 000 will likely result in a 400/422 from the Copilot backend. Consider mapping the lowest tier to "low" instead, or verify that Copilot accepts "minimal" before shipping.

Suggested change
elif budget_tokens >= 2000:
reasoning_effort = "low"
else:
reasoning_effort = "minimal"
elif budget_tokens >= 2000:
reasoning_effort = "low"
else:
reasoning_effort = "low"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"minimal" is a valid reasoning_effort value, not an invalid one.

@coderback

Copy link
Copy Markdown
Author

@greptileai

1 similar comment
@coderback

Copy link
Copy Markdown
Author

@greptileai

@Sameerlite

Copy link
Copy Markdown
Contributor

The fix for #25666 was merged. Closing this

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.

[Bug]: GitHub Copilot provider does not support reasoning_effort from Claude Code

2 participants