Repository: BrainBlend-AI/atomic-agents

Issue:
Retry behavior configuration
The `BaseAgent` class currently doesn't support retry functionality through the `max_retries` parameter that instructor provides. In the `get_response` and `run_async` methods, API calls to instructor don't pass any retry configuration:

```python
# Current implementation in get_response
response = self.client.chat.completions.create(
    messages=messages,
    model=self.model,
    response_model=response_model,
    temperature=self.temperature,
    max_tokens=self.max_tokens,
)
```

Adding `max_retries` to the `BaseAgentConfig` would be a simple yet valuable improvement.

Also, maybe other instructor parameters should be added such as `context` or `validation_context`.

Hints from issue comments:
@KennyVaneetvelde: This and https://github.com/BrainBlend-AI/atomic-agents/issues/75 are related (in that the fix for both would be the same)

A good solution here would be to allow for extra kwargs to be passed

Solution patch:
diff --git a/atomic-agents/atomic_agents/agents/base_agent.py b/atomic-agents/atomic_agents/agents/base_agent.py
index 98b68c93..4d83ba29 100644
--- a/atomic-agents/atomic_agents/agents/base_agent.py
+++ b/atomic-agents/atomic_agents/agents/base_agent.py
@@ -76,6 +76,7 @@ class BaseAgentConfig(BaseModel):
         None,
         description="Maximum number of token allowed in the response generation.",
     )
+    model_api_parameters: Optional[dict] = Field(None, description="Additional parameters passed to the API provider.")
 
 
 class BaseAgent:
@@ -93,7 +94,12 @@ class BaseAgent:
         memory (AgentMemory): Memory component for storing chat history.
         system_prompt_generator (SystemPromptGenerator): Component for generating system prompts.
         initial_memory (AgentMemory): Initial state of the memory.
-        max_tokens (int): Maximum number of tokens allowed in the response
+        temperature (float): Temperature for response generation, typically ranging from 0 to 1.  For models such as
+            OpenAI o3-mini that do not support temperature, you must explicitly pass 'None'.
+            DEPRECATED: Include 'temperature' in model_api_parameters instead.
+        max_tokens (int): Maximum number of tokens allowed in the response.
+            DEPRECATED: Include 'max_tokens' in model_api_parameters instead.
+        model_api_parameters (dict): Additional parameters passed to the API provider.
     """
 
     input_schema = BaseAgentInputSchema
@@ -114,8 +120,20 @@ def __init__(self, config: BaseAgentConfig):
         self.system_prompt_generator = config.system_prompt_generator or SystemPromptGenerator()
         self.initial_memory = self.memory.copy()
         self.current_user_input = None
-        self.temperature = config.temperature
-        self.max_tokens = config.max_tokens
+        self.model_api_parameters = config.model_api_parameters or {}
+        if config.temperature is not None:
+            warnings.warn(
+                "'temperature' is deprecated and will soon be removed. Please use 'model_api_parameters' instead.",
+                DeprecationWarning,
+            )
+            if "temperature" not in self.model_api_parameters:
+                self.model_api_parameters["temperature"] = config.temperature
+        if config.max_tokens is not None:
+            warnings.warn(
+                "'max_tokens' is deprecated and will soon be removed. Please use 'model_api_parameters' instead.",
+                DeprecationWarning,
+            )
+            self.model_api_parameters["max_tokens"] = config.max_tokens
 
     def reset_memory(self):
         """
@@ -148,8 +166,7 @@ def get_response(self, response_model=None) -> Type[BaseModel]:
             messages=messages,
             model=self.model,
             response_model=response_model,
-            temperature=self.temperature,
-            max_tokens=self.max_tokens,
+            **self.model_api_parameters,
         )
 
         return response
@@ -200,8 +217,7 @@ async def run_async(self, user_input: Optional[BaseIOSchema] = None):
             model=self.model,
             messages=messages,
             response_model=self.output_schema,
-            temperature=self.temperature,
-            max_tokens=self.max_tokens,
+            **self.model_api_parameters,
             stream=True,
         )
 
diff --git a/atomic-examples/quickstart/quickstart/4_basic_chatbot_different_providers.py b/atomic-examples/quickstart/quickstart/4_basic_chatbot_different_providers.py
index e48f66bd..1be31a4c 100644
--- a/atomic-examples/quickstart/quickstart/4_basic_chatbot_different_providers.py
+++ b/atomic-examples/quickstart/quickstart/4_basic_chatbot_different_providers.py
@@ -77,7 +77,7 @@ def setup_client(provider):
 client, model = setup_client(provider)
 
 # Agent setup with specified configuration
-agent = BaseAgent(config=BaseAgentConfig(client=client, model=model, memory=memory, max_tokens=2048))
+agent = BaseAgent(config=BaseAgentConfig(client=client, model=model, memory=memory, model_api_parameters={"max_tokens": 2048}))
 
 # Generate the default system prompt for the agent
 default_system_prompt = agent.system_prompt_generator.generate_prompt()


Test patch:
diff --git a/atomic-agents/tests/agents/test_base_agent.py b/atomic-agents/tests/agents/test_base_agent.py
index 40a3d28d..6ffabb13 100644
--- a/atomic-agents/tests/agents/test_base_agent.py
+++ b/atomic-agents/tests/agents/test_base_agent.py
@@ -63,8 +63,22 @@ def test_initialization(agent, mock_instructor, mock_memory, mock_system_prompt_
     assert agent.system_prompt_generator == mock_system_prompt_generator
     assert agent.input_schema == BaseAgentInputSchema
     assert agent.output_schema == BaseAgentOutputSchema
-    assert agent.temperature == 0
-    assert agent.max_tokens is None
+    assert agent.model_api_parameters["temperature"] == 0
+    assert "max_tokens" not in agent.model_api_parameters
+
+
+# model_api_parameters should have priority over the deprecated temperature parameter if both are provided.
+def test_initialization_temperature_priority(mock_instructor, mock_memory, mock_system_prompt_generator):
+    config = BaseAgentConfig(
+        client=mock_instructor,
+        model="gpt-4o-mini",
+        memory=mock_memory,
+        system_prompt_generator=mock_system_prompt_generator,
+        temperature=0.5,
+        model_api_parameters={"temperature": 1.0},
+    )
+    agent = BaseAgent(config)
+    assert agent.model_api_parameters["temperature"] == 1.0
 
 
 def test_reset_memory(agent, mock_memory):
@@ -90,7 +104,6 @@ def test_get_response(agent, mock_instructor, mock_memory, mock_system_prompt_ge
         messages=[{"role": "system", "content": "System prompt"}, {"role": "user", "content": "Hello"}],
         response_model=BaseAgentOutputSchema,
         temperature=0,
-        max_tokens=None,
     )