diff --git a/nanobot/providers/anthropic_provider.py b/nanobot/providers/anthropic_provider.py index 0625d23b7..00a7f8271 100644 --- a/nanobot/providers/anthropic_provider.py +++ b/nanobot/providers/anthropic_provider.py @@ -49,6 +49,8 @@ class AnthropicProvider(LLMProvider): client_kw["base_url"] = api_base if extra_headers: client_kw["default_headers"] = extra_headers + # Keep retries centralized in LLMProvider._run_with_retry to avoid retry amplification. + client_kw["max_retries"] = 0 self._client = AsyncAnthropic(**client_kw) @staticmethod diff --git a/nanobot/providers/openai_compat_provider.py b/nanobot/providers/openai_compat_provider.py index 10323d0ae..4fa057b90 100644 --- a/nanobot/providers/openai_compat_provider.py +++ b/nanobot/providers/openai_compat_provider.py @@ -135,6 +135,7 @@ class OpenAICompatProvider(LLMProvider): api_key=api_key or "no-key", base_url=effective_base, default_headers=default_headers, + max_retries=0, ) def _setup_env(self, api_key: str, api_base: str | None) -> None: diff --git a/tests/providers/test_provider_sdk_retry_defaults.py b/tests/providers/test_provider_sdk_retry_defaults.py new file mode 100644 index 000000000..4c79febc4 --- /dev/null +++ b/tests/providers/test_provider_sdk_retry_defaults.py @@ -0,0 +1,20 @@ +from unittest.mock import patch + +from nanobot.providers.anthropic_provider import AnthropicProvider +from nanobot.providers.openai_compat_provider import OpenAICompatProvider + + +def test_openai_compat_disables_sdk_retries_by_default() -> None: + with patch("nanobot.providers.openai_compat_provider.AsyncOpenAI") as mock_client: + OpenAICompatProvider(api_key="sk-test", default_model="gpt-4o") + + kwargs = mock_client.call_args.kwargs + assert kwargs["max_retries"] == 0 + + +def test_anthropic_disables_sdk_retries_by_default() -> None: + with patch("anthropic.AsyncAnthropic") as mock_client: + AnthropicProvider(api_key="sk-test", default_model="claude-sonnet-4-5") + + kwargs = mock_client.call_args.kwargs + assert kwargs["max_retries"] == 0