14
14
import logging
15
15
import random
16
16
from concurrent .futures import ThreadPoolExecutor
17
- from pathlib import Path
18
- from typing import Any , AsyncGenerator , AsyncIterator , Callable , Dict , Mapping , Optional , Type , TypeVar , Union , cast
17
+ from typing import Any , AsyncGenerator , AsyncIterator , Callable , Mapping , Optional , Type , TypeVar , Union , cast
19
18
20
- import yaml
21
19
from opentelemetry import trace as trace_api
22
20
from pydantic import BaseModel
23
21
@@ -200,8 +198,8 @@ def __init__(
200
198
Union [Callable [..., Any ], _DefaultCallbackHandlerSentinel ]
201
199
] = _DEFAULT_CALLBACK_HANDLER ,
202
200
conversation_manager : Optional [ConversationManager ] = None ,
203
- record_direct_tool_call : Optional [ bool ] = None ,
204
- load_tools_from_directory : Optional [ bool ] = None ,
201
+ record_direct_tool_call : bool = True ,
202
+ load_tools_from_directory : bool = False ,
205
203
trace_attributes : Optional [Mapping [str , AttributeValue ]] = None ,
206
204
* ,
207
205
agent_id : Optional [str ] = None ,
@@ -210,7 +208,6 @@ def __init__(
210
208
state : Optional [Union [AgentState , dict ]] = None ,
211
209
hooks : Optional [list [HookProvider ]] = None ,
212
210
session_manager : Optional [SessionManager ] = None ,
213
- config : Optional [Union [str , Path , Dict [str , Any ]]] = None ,
214
211
):
215
212
"""Initialize the Agent with the specified configuration.
216
213
@@ -237,11 +234,9 @@ def __init__(
237
234
conversation_manager: Manager for conversation history and context window.
238
235
Defaults to strands.agent.conversation_manager.SlidingWindowConversationManager if None.
239
236
record_direct_tool_call: Whether to record direct tool calls in message history.
240
- Defaults to True. When using config, this parameter only overrides the config value
241
- if explicitly provided.
237
+ Defaults to True.
242
238
load_tools_from_directory: Whether to load and automatically reload tools in the `./tools/` directory.
243
- Defaults to False. When using config, this parameter only overrides the config value
244
- if explicitly provided.
239
+ Defaults to False.
245
240
trace_attributes: Custom trace attributes to apply to the agent's trace span.
246
241
agent_id: Optional ID for the agent, useful for session management and multi-agent scenarios.
247
242
Defaults to "default".
@@ -255,108 +250,10 @@ def __init__(
255
250
Defaults to None.
256
251
session_manager: Manager for handling agent sessions including conversation history and state.
257
252
If provided, enables session-based persistence and state management.
258
- config: Configuration for initializing the agent from a file or dictionary.
259
- Can be specified as:
260
-
261
- - String: Path to a YAML (.yaml, .yml) or JSON (.json) configuration file
262
- - Path: Path object to a YAML (.yaml, .yml) or JSON (.json) configuration file
263
- - Dict: Configuration dictionary with agent parameters
264
-
265
- When provided, the agent is initialized using the AgentConfigLoader with the specified
266
- configuration. The config takes precedence over individual parameters, but individual
267
- parameters can override config values when both are provided.
268
253
269
254
Raises:
270
255
ValueError: If agent id contains path separators.
271
- FileNotFoundError: If config is a string/Path that doesn't exist.
272
- ValueError: If config file format is not supported (must be .yaml, .yml, or .json).
273
256
"""
274
- # Handle config-based initialization
275
- if config is not None :
276
- # Load configuration from file or use provided dict
277
- config_dict = self ._load_config (config )
278
-
279
- # Handle both direct agent config and config with 'agent' key
280
- if "agent" in config_dict :
281
- agent_config = config_dict ["agent" ]
282
- else :
283
- agent_config = config_dict
284
-
285
- # Import AgentConfigLoader here to avoid circular imports
286
- from ..experimental .config_loader .agent import AgentConfigLoader
287
-
288
- # Create agent from config and return early
289
- config_loader = AgentConfigLoader ()
290
- configured_agent = config_loader .load_agent (agent_config )
291
-
292
- # There is an odd mypy type discrepancy in this file for some reason
293
- # There is a mismatch between src.strands.* and strands.*
294
- # type/ignore annotations allow type checking to pass
295
-
296
- # Override config values with any explicitly provided parameters
297
- if model is not None :
298
- configured_agent .model = (
299
- BedrockModel () if not model else BedrockModel (model_id = model ) if isinstance (model , str ) else model # type: ignore
300
- )
301
- if messages is not None :
302
- configured_agent .messages = messages
303
- if tools is not None :
304
- # Need to reinitialize tool registry with new tools
305
- configured_agent .tool_registry = ToolRegistry () # type: ignore
306
- configured_agent .tool_registry .process_tools (tools )
307
- configured_agent .tool_registry .initialize_tools (load_tools_from_directory ) # type: ignore
308
- if system_prompt is not None :
309
- configured_agent .system_prompt = system_prompt
310
- if not isinstance (callback_handler , _DefaultCallbackHandlerSentinel ):
311
- if callback_handler is None :
312
- configured_agent .callback_handler = null_callback_handler
313
- else :
314
- configured_agent .callback_handler = callback_handler
315
- if conversation_manager is not None :
316
- configured_agent .conversation_manager = conversation_manager # type: ignore
317
- if trace_attributes is not None :
318
- configured_agent .trace_attributes = {}
319
- for k , v in trace_attributes .items ():
320
- if isinstance (v , (str , int , float , bool )) or (
321
- isinstance (v , list ) and all (isinstance (x , (str , int , float , bool )) for x in v )
322
- ):
323
- configured_agent .trace_attributes [k ] = v
324
- if agent_id is not None :
325
- configured_agent .agent_id = _identifier .validate (agent_id , _identifier .Identifier .AGENT )
326
- if name is not None :
327
- configured_agent .name = name
328
- if description is not None :
329
- configured_agent .description = description
330
- if state is not None :
331
- if isinstance (state , dict ):
332
- configured_agent .state = AgentState (state ) # type: ignore
333
- elif isinstance (state , AgentState ):
334
- configured_agent .state = state # type: ignore
335
- else :
336
- raise ValueError ("state must be an AgentState object or a dict" )
337
- if hooks is not None :
338
- for hook in hooks :
339
- configured_agent .hooks .add_hook (hook ) # type: ignore
340
- if session_manager is not None :
341
- configured_agent ._session_manager = session_manager # type: ignore
342
- configured_agent .hooks .add_hook (session_manager ) # type: ignore
343
-
344
- # Override record_direct_tool_call and load_tools_from_directory only if explicitly provided
345
- if record_direct_tool_call is not None :
346
- configured_agent .record_direct_tool_call = record_direct_tool_call
347
- if load_tools_from_directory is not None :
348
- configured_agent .load_tools_from_directory = load_tools_from_directory
349
- if load_tools_from_directory :
350
- if hasattr (configured_agent , "tool_watcher" ):
351
- configured_agent .tool_watcher = ToolWatcher (tool_registry = configured_agent .tool_registry ) # type: ignore
352
- else :
353
- configured_agent .tool_watcher = ToolWatcher (tool_registry = configured_agent .tool_registry ) # type: ignore
354
-
355
- # Copy all attributes from configured agent to self
356
- self .__dict__ .update (configured_agent .__dict__ )
357
- return
358
-
359
- # Standard initialization when no config is provided
360
257
self .model = BedrockModel () if not model else BedrockModel (model_id = model ) if isinstance (model , str ) else model
361
258
self .messages = messages if messages is not None else []
362
259
@@ -387,8 +284,8 @@ def __init__(
387
284
):
388
285
self .trace_attributes [k ] = v
389
286
390
- self .record_direct_tool_call = record_direct_tool_call if record_direct_tool_call is not None else True
391
- self .load_tools_from_directory = load_tools_from_directory if load_tools_from_directory is not None else False
287
+ self .record_direct_tool_call = record_direct_tool_call
288
+ self .load_tools_from_directory = load_tools_from_directory
392
289
393
290
self .tool_registry = ToolRegistry ()
394
291
@@ -432,42 +329,6 @@ def __init__(
432
329
self .hooks .add_hook (hook )
433
330
self .hooks .invoke_callbacks (AgentInitializedEvent (agent = self ))
434
331
435
- def _load_config (self , config : Union [str , Path , Dict [str , Any ]]) -> Dict [str , Any ]:
436
- """Load configuration from file or return provided dictionary.
437
-
438
- Args:
439
- config: Either a file path (string or Path), or configuration dictionary
440
-
441
- Returns:
442
- Configuration dictionary
443
-
444
- Raises:
445
- FileNotFoundError: If config is a string/Path that doesn't exist
446
- ValueError: If config file format is not supported
447
- """
448
- if isinstance (config , dict ):
449
- return config
450
-
451
- # Handle both str and Path objects
452
- if isinstance (config , (str , Path )):
453
- config_path = Path (config )
454
-
455
- if not config_path .exists ():
456
- raise FileNotFoundError (f"Configuration file not found: { config } " )
457
-
458
- suffix = config_path .suffix .lower ()
459
-
460
- if suffix in [".yaml" , ".yml" ]:
461
- with open (config_path , "r" , encoding = "utf-8" ) as f :
462
- return dict [str , Any ](yaml .safe_load (f ))
463
- elif suffix == ".json" :
464
- with open (config_path , "r" , encoding = "utf-8" ) as f :
465
- return dict [str , Any ](json .load (f ))
466
- else :
467
- raise ValueError (f"Unsupported config file format: { suffix } . Supported formats: .yaml, .yml, .json" )
468
-
469
- raise ValueError (f"Config must be a string (file path), Path object, or dictionary, got: { type (config )} " )
470
-
471
332
@property
472
333
def tool (self ) -> ToolCaller :
473
334
"""Call tool as a function.
@@ -859,4 +720,4 @@ def _end_agent_trace_span(
859
720
def _append_message (self , message : Message ) -> None :
860
721
"""Appends a message to the agent's list of messages and invokes the callbacks for the MessageCreatedEvent."""
861
722
self .messages .append (message )
862
- self .hooks .invoke_callbacks (MessageAddedEvent (agent = self , message = message ))
723
+ self .hooks .invoke_callbacks (MessageAddedEvent (agent = self , message = message ))
0 commit comments