@@ -76,7 +76,7 @@ def load_agent(self, config: Dict[str, Any], cache_key: Optional[str] = None) ->
76
76
"""Load an Agent from a dictionary configuration.
77
77
78
78
Args:
79
- config: Dictionary containing agent configuration.
79
+ config: Dictionary containing agent configuration with top-level 'agent' key .
80
80
cache_key: Optional key for caching the loaded agent.
81
81
82
82
Returns:
@@ -86,6 +86,14 @@ def load_agent(self, config: Dict[str, Any], cache_key: Optional[str] = None) ->
86
86
ValueError: If required configuration is missing or invalid.
87
87
ImportError: If specified models or tools cannot be imported.
88
88
"""
89
+ # Validate top-level structure
90
+ if "agent" not in config :
91
+ raise ValueError ("Configuration must contain a top-level 'agent' key" )
92
+
93
+ agent_config = config ["agent" ]
94
+ if not isinstance (agent_config , dict ):
95
+ raise ValueError ("The 'agent' configuration must be a dictionary" )
96
+
89
97
# Check cache first
90
98
if cache_key and cache_key in self ._agent_cache :
91
99
logger .debug ("agent_cache_key=<%s> | found in cache" , cache_key )
@@ -100,30 +108,30 @@ def load_agent(self, config: Dict[str, Any], cache_key: Optional[str] = None) ->
100
108
if "structured_output_defaults" in config :
101
109
self ._structured_output_defaults = config ["structured_output_defaults" ]
102
110
103
- # Extract configuration values
104
- model_config = config .get ("model" )
105
- system_prompt = config .get ("system_prompt" )
106
- tools_config = config .get ("tools" , [])
107
- messages_config = config .get ("messages" , [])
111
+ # Extract configuration values from agent_config
112
+ model_config = agent_config .get ("model" )
113
+ system_prompt = agent_config .get ("system_prompt" )
114
+ tools_config = agent_config .get ("tools" , [])
115
+ messages_config = agent_config .get ("messages" , [])
108
116
109
117
# Note: 'prompt' field is handled by AgentAsToolWrapper, not by Agent itself
110
118
# The Agent class doesn't have a prompt parameter - it uses system_prompt
111
119
# The prompt field is used for tool invocation templates
112
120
113
121
# Agent metadata
114
- agent_id = config .get ("agent_id" )
115
- name = config .get ("name" )
116
- description = config .get ("description" )
122
+ agent_id = agent_config .get ("agent_id" )
123
+ name = agent_config .get ("name" )
124
+ description = agent_config .get ("description" )
117
125
118
126
# Advanced configuration
119
- callback_handler_config = config .get ("callback_handler" )
120
- conversation_manager_config = config .get ("conversation_manager" )
121
- record_direct_tool_call = config .get ("record_direct_tool_call" , True )
122
- load_tools_from_directory = config .get ("load_tools_from_directory" , False )
123
- trace_attributes = config .get ("trace_attributes" )
124
- state_config = config .get ("state" )
125
- hooks_config = config .get ("hooks" , [])
126
- session_manager_config = config .get ("session_manager" )
127
+ callback_handler_config = agent_config .get ("callback_handler" )
128
+ conversation_manager_config = agent_config .get ("conversation_manager" )
129
+ record_direct_tool_call = agent_config .get ("record_direct_tool_call" , True )
130
+ load_tools_from_directory = agent_config .get ("load_tools_from_directory" , False )
131
+ trace_attributes = agent_config .get ("trace_attributes" )
132
+ state_config = agent_config .get ("state" )
133
+ hooks_config = agent_config .get ("hooks" , [])
134
+ session_manager_config = agent_config .get ("session_manager" )
127
135
128
136
# Load model
129
137
model = self ._load_model (model_config )
@@ -169,8 +177,8 @@ def load_agent(self, config: Dict[str, Any], cache_key: Optional[str] = None) ->
169
177
)
170
178
171
179
# Configure structured output if specified
172
- if "structured_output" in config :
173
- self ._configure_agent_structured_output (agent , config ["structured_output" ])
180
+ if "structured_output" in agent_config :
181
+ self ._configure_agent_structured_output (agent , agent_config ["structured_output" ])
174
182
175
183
# Cache the agent if cache key provided
176
184
if cache_key :
@@ -186,56 +194,56 @@ def serialize_agent(self, agent: Agent) -> Dict[str, Any]:
186
194
agent: Agent instance to serialize.
187
195
188
196
Returns:
189
- Dictionary containing the agent's configuration.
197
+ Dictionary containing the agent's configuration with top-level 'agent' key .
190
198
191
199
Note:
192
200
The 'prompt' field is not serialized here as it's specific to AgentAsToolWrapper
193
201
and not part of the core Agent configuration.
194
202
"""
195
- config = {}
203
+ agent_config = {}
196
204
197
205
# Basic configuration
198
206
if hasattr (agent .model , "model_id" ):
199
- config ["model" ] = agent .model .model_id
207
+ agent_config ["model" ] = agent .model .model_id
200
208
elif hasattr (agent .model , "config" ) and agent .model .config .get ("model_id" ):
201
- config ["model" ] = agent .model .config ["model_id" ]
209
+ agent_config ["model" ] = agent .model .config ["model_id" ]
202
210
203
211
if agent .system_prompt :
204
- config ["system_prompt" ] = agent .system_prompt
212
+ agent_config ["system_prompt" ] = agent .system_prompt
205
213
206
214
# Tools configuration
207
215
if hasattr (agent , "tool_registry" ) and agent .tool_registry :
208
216
tools_config = []
209
217
for tool_name in agent .tool_names :
210
218
tools_config .append ({"name" : tool_name })
211
219
if tools_config :
212
- config ["tools" ] = tools_config
220
+ agent_config ["tools" ] = tools_config
213
221
214
222
# Messages
215
223
if agent .messages :
216
- config ["messages" ] = agent .messages
224
+ agent_config ["messages" ] = agent .messages
217
225
218
226
# Agent metadata
219
227
if agent .agent_id != "default" :
220
- config ["agent_id" ] = agent .agent_id
228
+ agent_config ["agent_id" ] = agent .agent_id
221
229
if agent .name != "Strands Agents" :
222
- config ["name" ] = agent .name
230
+ agent_config ["name" ] = agent .name
223
231
if agent .description :
224
- config ["description" ] = agent .description
232
+ agent_config ["description" ] = agent .description
225
233
226
234
# Advanced configuration
227
235
if agent .record_direct_tool_call is not True :
228
- config ["record_direct_tool_call" ] = agent .record_direct_tool_call
236
+ agent_config ["record_direct_tool_call" ] = agent .record_direct_tool_call
229
237
if agent .load_tools_from_directory is not False :
230
- config ["load_tools_from_directory" ] = agent .load_tools_from_directory
238
+ agent_config ["load_tools_from_directory" ] = agent .load_tools_from_directory
231
239
if agent .trace_attributes :
232
- config ["trace_attributes" ] = agent .trace_attributes
240
+ agent_config ["trace_attributes" ] = agent .trace_attributes
233
241
234
242
# State
235
243
if agent .state and agent .state .get ():
236
- config ["state" ] = agent .state .get ()
244
+ agent_config ["state" ] = agent .state .get ()
237
245
238
- return config
246
+ return { "agent" : agent_config }
239
247
240
248
def _load_model (self , model_config : Optional [Union [str , Dict [str , Any ]]]) -> Optional [Model ]:
241
249
"""Load a model from configuration.
0 commit comments