Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions lib/crewai/src/crewai/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,11 @@ def _matches_provider_pattern(cls, model: str, provider: str) -> bool:
)

if provider == "anthropic" or provider == "claude":
return any(
model_lower.startswith(prefix) for prefix in ["claude-", "anthropic."]
# Match standard prefixes and any model containing "claude" or "anthropic"
# to support custom deployments with non-standard naming (e.g., "anthropic--claude-...")
return (
"claude" in model_lower
or "anthropic" in model_lower
)

if provider == "gemini" or provider == "google":
Expand Down Expand Up @@ -619,6 +622,18 @@ def _infer_provider_from_model(cls, model: str) -> str:
if model in AZURE_MODELS:
return "azure"

# Pattern-based inference for custom deployments
model_lower = model.lower()
if "claude" in model_lower or "anthropic" in model_lower:
return "anthropic"
if any(
model_lower.startswith(prefix)
for prefix in ["gpt-", "o1", "o3", "o4", "whisper-"]
):
return "openai"
if "gemini" in model_lower:
return "gemini"

return "openai"

@classmethod
Expand Down Expand Up @@ -702,8 +717,8 @@ def _is_anthropic_model(model: str) -> bool:
Returns:
bool: True if the model is from Anthropic, False otherwise.
"""
anthropic_prefixes = ("anthropic/", "claude-", "claude/")
return any(prefix in model.lower() for prefix in anthropic_prefixes)
model_lower = model.lower()
return "claude" in model_lower or "anthropic" in model_lower

def _prepare_completion_params(
self,
Expand Down
24 changes: 24 additions & 0 deletions lib/crewai/tests/test_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1177,3 +1177,27 @@ async def _ret(*args, **kwargs):
assert isinstance(result, list)
assert len(result) == 1
assert result[0].function.name == "search"


class TestModelPrefixFiltering:
"""Test that model prefix filtering supports custom deployments."""

def test_anthropic_custom_prefix(self):
"""Models with 'anthropic--claude' prefix should be recognized."""
from crewai.llm import LLM
assert LLM._matches_provider_pattern("anthropic--claude-3-sonnet", "anthropic")

def test_anthropic_standard_prefix(self):
"""Standard claude- prefix should still work."""
from crewai.llm import LLM
assert LLM._matches_provider_pattern("claude-3-sonnet", "anthropic")

def test_anthropic_dot_prefix(self):
"""Standard anthropic. prefix should still work."""
from crewai.llm import LLM
assert LLM._matches_provider_pattern("anthropic.claude-3-sonnet", "anthropic")

def test_infer_anthropic_from_custom_name(self):
"""Should infer anthropic provider from custom model names."""
from crewai.llm import LLM
assert LLM._infer_provider_from_model("anthropic--claude-3-sonnet") == "anthropic"