From c542cc9f7046ae3b32c9cfc3d03db0c68321bcee Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Tue, 24 Mar 2026 07:21:19 -0400 Subject: [PATCH] fix: raise value error on no file support --- lib/crewai/src/crewai/llm.py | 25 +++++++++++++++++-- lib/crewai/src/crewai/llms/base_llm.py | 11 +++++++- .../llms/providers/anthropic/completion.py | 9 ++++++- .../llms/providers/bedrock/completion.py | 6 +++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/crewai/src/crewai/llm.py b/lib/crewai/src/crewai/llm.py index 8a4ac2edd..ffb1905ef 100644 --- a/lib/crewai/src/crewai/llm.py +++ b/lib/crewai/src/crewai/llm.py @@ -1984,7 +1984,16 @@ class LLM(BaseLLM): Returns: Messages with files formatted into content blocks. """ - if not HAS_CREWAI_FILES or not self.supports_multimodal(): + if not HAS_CREWAI_FILES: + return messages + + if not self.supports_multimodal(): + if any(msg.get("files") for msg in messages): + raise ValueError( + f"Model '{self.model}' does not support multimodal input, " + "but files were provided via 'input_files'. " + "Use a vision-capable model or remove the file inputs." + ) return messages provider = getattr(self, "provider", None) or self.model @@ -2026,7 +2035,16 @@ class LLM(BaseLLM): Returns: Messages with files formatted into content blocks. """ - if not HAS_CREWAI_FILES or not self.supports_multimodal(): + if not HAS_CREWAI_FILES: + return messages + + if not self.supports_multimodal(): + if any(msg.get("files") for msg in messages): + raise ValueError( + f"Model '{self.model}' does not support multimodal input, " + "but files were provided via 'input_files'. " + "Use a vision-capable model or remove the file inputs." + ) return messages provider = getattr(self, "provider", None) or self.model @@ -2398,6 +2416,9 @@ class LLM(BaseLLM): "gpt-4.1", "claude-3", "claude-4", + "claude-sonnet-4", + "claude-opus-4", + "claude-haiku-4", "gemini", ) model_lower = self.model.lower() diff --git a/lib/crewai/src/crewai/llms/base_llm.py b/lib/crewai/src/crewai/llms/base_llm.py index 19ac3ffba..6e81271e1 100644 --- a/lib/crewai/src/crewai/llms/base_llm.py +++ b/lib/crewai/src/crewai/llms/base_llm.py @@ -641,7 +641,16 @@ class BaseLLM(ABC): Returns: Messages with files formatted into content blocks. """ - if not HAS_CREWAI_FILES or not self.supports_multimodal(): + if not HAS_CREWAI_FILES: + return messages + + if not self.supports_multimodal(): + if any(msg.get("files") for msg in messages): + raise ValueError( + f"Model '{self.model}' does not support multimodal input, " + "but files were provided via 'input_files'. " + "Use a vision-capable model or remove the file inputs." + ) return messages provider = getattr(self, "provider", None) or getattr(self, "model", "openai") diff --git a/lib/crewai/src/crewai/llms/providers/anthropic/completion.py b/lib/crewai/src/crewai/llms/providers/anthropic/completion.py index a22ff5b91..d492d48ec 100644 --- a/lib/crewai/src/crewai/llms/providers/anthropic/completion.py +++ b/lib/crewai/src/crewai/llms/providers/anthropic/completion.py @@ -1766,7 +1766,14 @@ class AnthropicCompletion(BaseLLM): Returns: True if the model supports images and PDFs. """ - return "claude-3" in self.model.lower() or "claude-4" in self.model.lower() + model_lower = self.model.lower() + return ( + "claude-3" in model_lower + or "claude-4" in model_lower + or "claude-sonnet-4" in model_lower + or "claude-opus-4" in model_lower + or "claude-haiku-4" in model_lower + ) def get_file_uploader(self) -> Any: """Get an Anthropic file uploader using this LLM's clients. diff --git a/lib/crewai/src/crewai/llms/providers/bedrock/completion.py b/lib/crewai/src/crewai/llms/providers/bedrock/completion.py index 83b664d98..b17c98874 100644 --- a/lib/crewai/src/crewai/llms/providers/bedrock/completion.py +++ b/lib/crewai/src/crewai/llms/providers/bedrock/completion.py @@ -2119,12 +2119,18 @@ class BedrockCompletion(BaseLLM): model_lower = self.model.lower() vision_models = ( "anthropic.claude-3", + "anthropic.claude-sonnet-4", + "anthropic.claude-opus-4", + "anthropic.claude-haiku-4", "amazon.nova-lite", "amazon.nova-pro", "amazon.nova-premier", "us.amazon.nova-lite", "us.amazon.nova-pro", "us.amazon.nova-premier", + "us.anthropic.claude-sonnet-4", + "us.anthropic.claude-opus-4", + "us.anthropic.claude-haiku-4", ) return any(model_lower.startswith(m) for m in vision_models)