diff --git a/camel/agents/chat_agent.py b/camel/agents/chat_agent.py index 0e092b64cd..a77e6e0084 100644 --- a/camel/agents/chat_agent.py +++ b/camel/agents/chat_agent.py @@ -107,6 +107,24 @@ from camel.utils.context_utils import ContextUtility from camel.utils.tool_result import ToolResult +def _is_rate_limit_error(error: Exception) -> bool: + """Check if an error is a rate limit error from any LLM provider. + + Handles OpenAI, Anthropic, Google, and other providers that signal + rate limiting via HTTP 429 status codes or error messages. + """ + if isinstance(error, RateLimitError): + return True + # Only check status_code (HTTP-specific), not generic 'code' which + # may be an application error code unrelated to rate limiting. + status_code = getattr(error, 'status_code', None) + if status_code == 429: + return True + error_msg = str(error).lower() + if 'rate limit' in error_msg or 'too many requests' in error_msg: + return True + return False + if TYPE_CHECKING: from camel.terminators import ResponseTerminator @@ -3592,7 +3610,12 @@ def _get_model_response( ) if response: break - except RateLimitError as e: + except Exception as e: + if not _is_rate_limit_error(e): + logger.error( + f"Model error: {self.model_backend.model_type}", + ) + raise last_error = e if attempt < self.retry_attempts - 1: delay = min(self.retry_delay * (2**attempt), 60.0) @@ -3607,11 +3630,6 @@ def _get_model_response( f"Rate limit exhausted after " f"{self.retry_attempts} attempts" ) - except Exception: - logger.error( - f"Model error: {self.model_backend.model_type}", - ) - raise else: # Loop completed without success raise ModelProcessingError( @@ -3654,7 +3672,12 @@ async def _aget_model_response( ) if response: break - except RateLimitError as e: + except Exception as e: + if not _is_rate_limit_error(e): + logger.error( + f"Model error: {self.model_backend.model_type}", + ) + raise last_error = e if attempt < self.retry_attempts - 1: delay = min(self.retry_delay * (2**attempt), 60.0) @@ -3670,12 +3693,6 @@ async def _aget_model_response( f"Rate limit exhausted after " f"{self.retry_attempts} attempts" ) - except Exception: - logger.error( - f"Model error: {self.model_backend.model_type}", - exc_info=True, - ) - raise else: # Loop completed without success raise ModelProcessingError(