WebSearch fails with 400 output_config.effort when ANTHROPIC_BASE_URL is set
Summary
When ANTHROPIC_BASE_URL points anywhere other than api.anthropic.com, the
WebSearch tool's side query is built from the session's main-loop model and
settings instead of the fixed parameters it uses natively:
model: the session's model, notclaude-haiku-4-5-20251001max_tokens: the session's value, not32000temperature: not pinned to1, so it follows the sessionoutput_config: the session's effort, where the native request has none
The side query hardcodes thinking: {"type": "disabled"}, so when the
inherited effort is invalid alongside disabled thinking, the API rejects it:
400 invalid_request_error
output_config.effort 'xhigh' is not supported when thinking is disabled on
this model. Use effort 'high' or below, or enable thinking.
The 400 error occurs when the inherited effort is above what the model accepts
with thinking disabled. On claude-opus-5, xhigh was rejected and high
was accepted. I have not tested other models or other effort values, and the
message's "on this model" suggests the accepted range varies by model. The
other three differences produce no error. The request simply goes out with
different parameters than the native one.
Version
2.1.220 (BUILD_TIME 2026-07-24, GIT_SHA 4073f59596e272f39393db4f96abc5f4b10eff21)
Linux. ~/.claude/settings.json contains "model": "opus[1m]" and"effortLevel": "xhigh".
Reproduction
- Set
"effortLevel": "xhigh"in~/.claude/settings.json, with the session
model on claude-opus-5.
- Point
ANTHROPIC_BASE_URLat any local proxy that forwards to
api.anthropic.com.
- Ask Claude to use the WebSearch tool.
Every search 400s. Unsetting ANTHROPIC_BASE_URL makes them succeed, as does
lowering effort to high.
Evidence
The same query ("OpenAI Codex CLI latest version release") captured both
ways. The direct capture was taken with mitmproxy over HTTPS_PROXY, which
intercepts at the transport layer, so ANTHROPIC_BASE_URL was unset and
Claude Code still believed it was talking to api.anthropic.com.
Direct (200):
{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 32000,
"temperature": 1,
"thinking": {"type": "disabled"},
"tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 8}],
"tool_choice": {"type": "tool", "name": "web_search"}
}
With ANTHROPIC_BASE_URL set (400):
{
"model": "claude-opus-5",
"max_tokens": 64000,
"output_config": {"effort": "xhigh"},
"thinking": {"type": "disabled"},
"tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 8}],
"tool_choice": {"type": "tool", "name": "web_search"}
}
The two are otherwise byte-identical apart from metadata.user_id and thecch= segment of the billing header. The proxy forwards the body unchanged
(verified against an echo upstream, matching SHA-256), and I reproduced it
through two unrelated proxies.