diff --git a/src/agent_env/agents/agents/claude-code/claude_bridge.py b/src/agent_env/agents/agents/claude-code/claude_bridge.py index fad10df25..e8fcfc651 100644 --- a/src/agent_env/agents/agents/claude-code/claude_bridge.py +++ b/src/agent_env/agents/agents/claude-code/claude_bridge.py @@ -189,6 +189,10 @@ def cli_env(environ: Mapping[str, str], *, model: str | None = None, project_id: if model and env.get("ANTHROPIC_BASE_URL"): for alias in _MODEL_ALIASES: env.setdefault(alias, model) + if "claude" not in model.lower(): + # The CLI sends Anthropic's beta parameters, such as `context_management`, whatever the model; an endpoint + # serving another provider's model through the Messages API, as LiteLLM does, refuses them with a 400. + env.setdefault("CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS", "1") headers = _with_attribution(_model_headers(env.get(MODEL_HEADERS_ENV)), _attribution_headers(project_id, task_id)) if headers: env["ANTHROPIC_CUSTOM_HEADERS"] = "\n".join(f"{name}: {value}" for name, value in headers.items()) diff --git a/tst/unit/agents/claude_code/test_cli_env.py b/tst/unit/agents/claude_code/test_cli_env.py index 7c92fcc82..c76b7d48d 100644 --- a/tst/unit/agents/claude_code/test_cli_env.py +++ b/tst/unit/agents/claude_code/test_cli_env.py @@ -46,6 +46,22 @@ def test_the_cli_offers_its_tools_up_front_unless_tool_search_is_asked_for(): assert claude_bridge.cli_env({**GATEWAY, "ENABLE_TOOL_SEARCH": "auto"})["ENABLE_TOOL_SEARCH"] == "auto" +@pytest.mark.parametrize("model, disabled", [ + ("fireworks_ai/glm-5p3-flash", "1"), + ("claude-sonnet-5-5", None), + ("bedrock/us.anthropic.claude-opus-5-5", None), +]) +def test_a_model_that_isnt_claude_is_sent_none_of_anthropics_beta_parameters(model, disabled): + """LiteLLM refuses `context_management`, which the CLI sends for any model, when the model isn't Anthropic's.""" + assert claude_bridge.cli_env(GATEWAY, model=model).get("CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS") == disabled + + +def test_an_explicit_beta_setting_wins(): + env = claude_bridge.cli_env({**GATEWAY, "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "0"}, model="fireworks_ai/x") + + assert env["CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS"] == "0" + + def test_no_endpoint_leaves_the_cli_to_its_own_and_an_api_key_alone(): env = claude_bridge.cli_env({"ANTHROPIC_API_KEY": "direct"}, model="claude-x")