#35334 [Bug]: websearch interception leaks a litellm_web_search tool_use to the client on /v1/messages (forced tool_choice survives into the follow-up call)
### What happened?
On the `/v1/messages` websearch-interception path, the follow-up model call inherits the caller's forced `tool_choice`, which by then has been repointed at `litellm_web_search`. The model is therefore obliged to call the search tool again, and that second `tool_use` is returned to the client verbatim — for a tool the client never declared and cannot execute.
The two sibling paths both strip it; only the Anthropic one does not:
```python # _execute_chat_completion_agentic_loop params.pop("tool_choice", None)
# _build_chat_completion_request_patch / _build_responses_request_patch if k not in {"tools", "tool_choice", ...}
# _build_anthropic_request_patch <-- only max_tokens is removed optional_params_without_max_tokens = { k: v for k, v in anthropic_messages_optional_request_params.items() if k != "max_tokens" } ```
`anthropic_messages_optional_request_params` carries `tools` and `tool_choice`, so both survive into `anthropic_messages.acreate(...)`.
This is reachable through LiteLLM's own code. `_sync_forced_tool_choice` exists precisely because native clients force the search tool — its docstring names Claude Code sending `tool_choice={"type": "tool", "…