fix(anthropic): default tool_choice to auto when only parallel_tool_calls is set - #1292
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 6 remain after this review. WalkthroughThe Anthropic provider now defaults unspecified tool choice to ChangesAnthropic tool choice conversion
Suggested reviewers: Merge Risk: ⚪ Minimal · up to This is a localized Anthropic tool-choice fix with tests added, and no actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests.
... and 31 files with indirect coverage changes 🚀 New features to boost your workflow:
|
## Description Bedrock and SageMaker `_convert_params` gated `temperature` and `top_p` on truthiness, so `0.0` was dropped and the request used the model default (e.g. Claude 1.0 on Bedrock) instead of greedy decoding. Other providers already use `is not None`. `max_tokens` and `stop` stay on truthiness: `0` and empty sequences are rejected by both providers. ## PR Type - Bug Fix ## Relevant issues No open issue. Distinct from #1292 (Anthropic tool_choice) and our #1296/#1297/#1298. ## Checklist - [x] I understand the code I am submitting. - [x] I have added unit tests that prove my fix/feature works - [x] I have run this code locally and verified it fixes the issue. - [x] New and existing tests pass locally - [x] Documentation was updated where necessary - [x] I have read and followed the contribution guidelines - [x] **AI Usage:** - [x] This is fully AI-generated. ## AI Usage Information - AI Model used: Claude Opus 5 - AI Developer Tool used: Cursor cloud agent - [x] I am an AI Agent filling out this form (check box if true) `uv run pytest tests/unit` → 2161 passed, 69 skipped. Target files fail on current main (`KeyError: inferenceConfig` / missing keys) and pass after. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * AWS Bedrock and SageMaker integrations now correctly honour explicitly configured zero values for temperature and top-p sampling parameters. * Unset sampling parameters continue to be omitted from requests. * **Tests** * Added coverage confirming zero-valued parameters are forwarded and unset values are excluded. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
## Description Non-streaming _convert_response mapped only text, tool_use, and thinking, then raised ValueError on anything else. Anthropic returns redacted_thinking when safety flags part of an extended-thinking trace, so completion() crashed even though the rest of the answer was fine. The streaming converter already ignores unmapped block types. Skip redacted_thinking quietly; warn and skip other unmapped types. Shared by anthropic, azureanthropic, vertexaianthropic, and meta. Tests: uv run pytest tests/unit -> 2158 passed. Distinct from #1292 and #1296-#1302. ## PR Type - Bug Fix ## Relevant issues No open issue. ## Checklist - [x] I understand the code I am submitting. - [x] I have added unit tests that prove my fix/feature works - [x] I have run this code locally and verified it fixes the issue. - [x] New and existing tests pass locally - [x] Documentation was updated where necessary - [x] I have read and followed the contribution guidelines - [x] **AI Usage:** - [x] This is fully AI-generated. ## AI Usage Information - AI Model used: Claude Opus 5 - AI Developer Tool used: Cursor cloud agent - [x] I am an AI Agent filling out this form (check box if true) Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Brings in upstream's merges of our mozilla-ai#1291/mozilla-ai#1292/mozilla-ai#1310 plus mozilla-ai#1297, mozilla-ai#1299, mozilla-ai#1301, mozilla-ai#1302, mozilla-ai#1303, mozilla-ai#1305. Carried-until-merged fork work stays: mozilla-ai#1294 (gemini reasoning_effort=none), mozilla-ai#1308 (aresponses timeout), mozilla-ai#1309 (gemini native tool dicts), and the mozilla-ai#1300 carry. One conflict in tests/unit/test_responses.py: kept our mozilla-ai#1308 timeout test next to upstream's flatten test. Unit suite: 2234 passed. Claude-Session: https://claude.ai/code/session_018D3FGNvb1hRZQmsXFoA44J
…mozilla-ai#1319 Upstream has merged mozilla-ai#1291, mozilla-ai#1292, mozilla-ai#1308, mozilla-ai#1309, mozilla-ai#1310, mozilla-ai#1317, mozilla-ai#1318, mozilla-ai#1320, mozilla-ai#1325 and mozilla-ai#1352 in their final form, so the fork's own copies are dropped in favour of upstream's. The tree is exactly upstream main plus the two fixes still open there: gemini reasoning_effort="none" (mozilla-ai#1294) and closing the provider stream when the wrapped stream closes (mozilla-ai#1319). Claude-Session: https://claude.ai/code/session_01MmJSSofg7Lk7nBKZZyKV7w
Description
Anthropic and OpenAI set tool calling differently:
tool_choice:"auto"(default),"required","none", or a dict naming one functiontool_choiceobject:{"type": "auto"},{"type": "any"}(="required"),{"type": "tool", "name": ...},{"type": "none"}parallel_tool_calls, a separate top-level booleandisable_parallel_tool_uselives inside thetool_choiceobjectSo
_convert_tool_choicehas two jobs:parallel_tool_callsintodisable_parallel_tool_useinside whatevertool_choiceobject it sends.The corner case is a caller who passes only
parallel_tool_calls. Anthropic has no standalone field for it, so the converter must synthesize atool_choiceobject just to carry the flag.The neutral carrier is
{"type": "auto"}: identical model behavior to not mentioning tool choice at all. What happens today instead:tool_choiceto"any": Anthropic's "must call a tool" mode. So a caller who only asked about parallelism gets forced tool use;if params.tool_choice or params.parallel_tool_calls), soparallel_tool_calls=Falsenever reaches the converter at all (the restriction is silently dropped).The fix is two lines: default the synthesized
tool_choiceto"auto"and gate onis not None.With the fix,
parallel_tool_calls=Falsealone sends{"type": "auto", "disable_parallel_tool_use": true}. Explicittool_choicevalues ("auto"/"required"/dict form) are unchanged.Example
Before (live,
main): the model is not allowed to reply in text, so it fabricates a tool call:After (live, this branch):
PR Type
Relevant issues
Related: #646 (fixed the dict-form translation; this fixes the unset-default path)
Checklist
AI Usage Information
AI Model used: Claude (Fable 5)
AI Developer Tool used: Claude Code
Any other info you'd like to share:
I am an AI Agent filling out this form (check box if true)
Summary by CodeRabbit
Bug Fixes
Tests