mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
feat: Add support for custom User-Agent header in Anthropic provider
Fixes #19017 This commit adds the ability to customize the User-Agent header for Anthropic/Claude API requests to avoid credential blocks when using restricted API keys (e.g., Claude Code credentials). Changes: - Added `custom_user_agent` parameter support in AnthropicConfig - Added `ANTHROPIC_USER_AGENT` environment variable support - Modified validate_environment() to set User-Agent header when custom value is provided - Added comprehensive unit tests for custom User-Agent functionality Priority order for User-Agent: 1. custom_user_agent parameter 2. ANTHROPIC_USER_AGENT environment variable 3. User-Agent in extra_headers 4. Default litellm/{version} Users can now override the User-Agent by: - Passing custom_user_agent parameter: litellm.completion(model="anthropic/...", custom_user_agent="Claude Code/1.0") - Setting environment variable: export ANTHROPIC_USER_AGENT="Claude Code/1.0" - Using extra_headers: litellm.completion(model="anthropic/...", extra_headers={"User-Agent": "..."})
This commit is contained in:
parent
a02c43d300
commit
509dfd9a5f
3 changed files with 113 additions and 1 deletions
|
|
@ -189,6 +189,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
"response_format",
|
||||
"user",
|
||||
"web_search_options",
|
||||
"custom_user_agent",
|
||||
]
|
||||
|
||||
if "claude-3-7-sonnet" in model or supports_reasoning(
|
||||
|
|
@ -802,6 +803,8 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
)
|
||||
elif param == "extra_headers":
|
||||
optional_params["extra_headers"] = value
|
||||
elif param == "custom_user_agent":
|
||||
optional_params["custom_user_agent"] = value
|
||||
|
||||
## handle thinking tokens
|
||||
self.update_optional_params_with_thinking_tokens(
|
||||
|
|
|
|||
|
|
@ -397,6 +397,8 @@ class AnthropicModelInfo(BaseLLMModelInfo):
|
|||
api_key: Optional[str] = None,
|
||||
api_base: Optional[str] = None,
|
||||
) -> Dict:
|
||||
import os
|
||||
|
||||
# Check for Anthropic OAuth token in headers
|
||||
headers, api_key = optionally_handle_anthropic_oauth(headers=headers, api_key=api_key)
|
||||
if api_key is None:
|
||||
|
|
@ -444,6 +446,16 @@ class AnthropicModelInfo(BaseLLMModelInfo):
|
|||
|
||||
headers = {**headers, **anthropic_headers}
|
||||
|
||||
# Handle custom User-Agent header
|
||||
# Priority: custom_user_agent parameter > ANTHROPIC_USER_AGENT env var > User-Agent in extra_headers > default
|
||||
custom_user_agent = (
|
||||
optional_params.get("custom_user_agent")
|
||||
or os.getenv("ANTHROPIC_USER_AGENT")
|
||||
)
|
||||
|
||||
if custom_user_agent:
|
||||
headers["User-Agent"] = custom_user_agent
|
||||
|
||||
return headers
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -81,4 +81,101 @@ def test_regular_api_keys_still_work():
|
|||
# Regular key should be unchanged
|
||||
assert extracted_api_key == regular_key
|
||||
# OAuth headers should NOT be added
|
||||
assert "anthropic-dangerous-direct-browser-access" not in updated_headers
|
||||
assert "anthropic-dangerous-direct-browser-access" not in updated_headers
|
||||
|
||||
|
||||
def test_custom_user_agent_via_parameter():
|
||||
"""Test 5: Custom User-Agent via custom_user_agent parameter"""
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
config = AnthropicModelInfo()
|
||||
custom_agent = "Claude Code/1.0"
|
||||
|
||||
updated_headers = config.validate_environment(
|
||||
headers={},
|
||||
model="claude-3-haiku-20240307",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
optional_params={"custom_user_agent": custom_agent},
|
||||
litellm_params={},
|
||||
api_key="sk-ant-api03-test-key",
|
||||
api_base=None,
|
||||
)
|
||||
|
||||
assert updated_headers["User-Agent"] == custom_agent
|
||||
|
||||
|
||||
def test_custom_user_agent_via_env_var():
|
||||
"""Test 6: Custom User-Agent via ANTHROPIC_USER_AGENT environment variable"""
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
config = AnthropicModelInfo()
|
||||
custom_agent = "Claude Code/1.0"
|
||||
|
||||
# Set environment variable
|
||||
os.environ["ANTHROPIC_USER_AGENT"] = custom_agent
|
||||
|
||||
try:
|
||||
updated_headers = config.validate_environment(
|
||||
headers={},
|
||||
model="claude-3-haiku-20240307",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
api_key="sk-ant-api03-test-key",
|
||||
api_base=None,
|
||||
)
|
||||
|
||||
assert updated_headers["User-Agent"] == custom_agent
|
||||
finally:
|
||||
# Clean up
|
||||
del os.environ["ANTHROPIC_USER_AGENT"]
|
||||
|
||||
|
||||
def test_custom_user_agent_parameter_priority():
|
||||
"""Test 7: custom_user_agent parameter takes priority over environment variable"""
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
config = AnthropicModelInfo()
|
||||
param_agent = "Claude Code/2.0"
|
||||
env_agent = "Claude Code/1.0"
|
||||
|
||||
# Set environment variable
|
||||
os.environ["ANTHROPIC_USER_AGENT"] = env_agent
|
||||
|
||||
try:
|
||||
updated_headers = config.validate_environment(
|
||||
headers={},
|
||||
model="claude-3-haiku-20240307",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
optional_params={"custom_user_agent": param_agent},
|
||||
litellm_params={},
|
||||
api_key="sk-ant-api03-test-key",
|
||||
api_base=None,
|
||||
)
|
||||
|
||||
# Parameter should take priority over environment variable
|
||||
assert updated_headers["User-Agent"] == param_agent
|
||||
finally:
|
||||
# Clean up
|
||||
del os.environ["ANTHROPIC_USER_AGENT"]
|
||||
|
||||
|
||||
def test_no_custom_user_agent():
|
||||
"""Test 8: Default User-Agent is preserved when no custom agent is provided"""
|
||||
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||||
|
||||
config = AnthropicModelInfo()
|
||||
default_agent = "litellm/1.0.0"
|
||||
|
||||
updated_headers = config.validate_environment(
|
||||
headers={"User-Agent": default_agent},
|
||||
model="claude-3-haiku-20240307",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
api_key="sk-ant-api03-test-key",
|
||||
api_base=None,
|
||||
)
|
||||
|
||||
# Default User-Agent should be preserved
|
||||
assert updated_headers["User-Agent"] == default_agent
|
||||
Loading…
Add table
Reference in a new issue