6
6
from a2a .types import AgentCapabilities , AgentCard
7
7
from fastapi import FastAPI
8
8
from starlette .applications import Starlette
9
-
10
9
from strands .multiagent .a2a .server import A2AServer
11
10
12
11
@@ -16,7 +15,7 @@ def test_a2a_agent_initialization(mock_strands_agent):
16
15
mock_tool_config = {"test_tool" : {"name" : "test_tool" , "description" : "A test tool" }}
17
16
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
18
17
19
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
18
+ a2a_agent = A2AServer (mock_strands_agent )
20
19
21
20
assert a2a_agent .strands_agent == mock_strands_agent
22
21
assert a2a_agent .name == "Test Agent"
@@ -26,7 +25,6 @@ def test_a2a_agent_initialization(mock_strands_agent):
26
25
assert a2a_agent .http_url == "http://0.0.0.0:9000/"
27
26
assert a2a_agent .version == "0.0.1"
28
27
assert isinstance (a2a_agent .capabilities , AgentCapabilities )
29
- # Should have skills from tools
30
28
assert len (a2a_agent .agent_skills ) == 1
31
29
assert a2a_agent .agent_skills [0 ].name == "test_tool"
32
30
@@ -38,7 +36,6 @@ def test_a2a_agent_initialization_with_custom_values(mock_strands_agent):
38
36
host = "127.0.0.1" ,
39
37
port = 8080 ,
40
38
version = "1.0.0" ,
41
- skills = None ,
42
39
)
43
40
44
41
assert a2a_agent .host == "127.0.0.1"
@@ -110,7 +107,7 @@ def test_agent_skills_empty_registry(mock_strands_agent):
110
107
# Mock empty tool registry
111
108
mock_strands_agent .tool_registry .get_all_tools_config .return_value = {}
112
109
113
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
110
+ a2a_agent = A2AServer (mock_strands_agent )
114
111
skills = a2a_agent .agent_skills
115
112
116
113
assert isinstance (skills , list )
@@ -123,7 +120,7 @@ def test_agent_skills_with_single_tool(mock_strands_agent):
123
120
mock_tool_config = {"calculator" : {"name" : "calculator" , "description" : "Performs basic mathematical calculations" }}
124
121
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
125
122
126
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
123
+ a2a_agent = A2AServer (mock_strands_agent )
127
124
skills = a2a_agent .agent_skills
128
125
129
126
assert isinstance (skills , list )
@@ -146,7 +143,7 @@ def test_agent_skills_with_multiple_tools(mock_strands_agent):
146
143
}
147
144
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
148
145
149
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
146
+ a2a_agent = A2AServer (mock_strands_agent )
150
147
skills = a2a_agent .agent_skills
151
148
152
149
assert isinstance (skills , list )
@@ -186,7 +183,7 @@ def test_agent_skills_with_complex_tool_config(mock_strands_agent):
186
183
}
187
184
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
188
185
189
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
186
+ a2a_agent = A2AServer (mock_strands_agent )
190
187
skills = a2a_agent .agent_skills
191
188
192
189
assert isinstance (skills , list )
@@ -213,7 +210,7 @@ def test_agent_skills_preserves_tool_order(mock_strands_agent):
213
210
)
214
211
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
215
212
216
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
213
+ a2a_agent = A2AServer (mock_strands_agent )
217
214
skills = a2a_agent .agent_skills
218
215
219
216
assert len (skills ) == 3
@@ -233,9 +230,11 @@ def test_agent_skills_handles_missing_description(mock_strands_agent):
233
230
}
234
231
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
235
232
236
- # This should raise a KeyError during initialization when trying to access missing description
233
+ a2a_agent = A2AServer (mock_strands_agent )
234
+
235
+ # This should raise a KeyError when accessing agent_skills due to missing description
237
236
with pytest .raises (KeyError ):
238
- A2AServer ( mock_strands_agent , skills = None )
237
+ _ = a2a_agent . agent_skills
239
238
240
239
241
240
def test_agent_skills_handles_missing_name (mock_strands_agent ):
@@ -249,9 +248,11 @@ def test_agent_skills_handles_missing_name(mock_strands_agent):
249
248
}
250
249
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
251
250
252
- # This should raise a KeyError during initialization when trying to access missing name
251
+ a2a_agent = A2AServer (mock_strands_agent )
252
+
253
+ # This should raise a KeyError when accessing agent_skills due to missing name
253
254
with pytest .raises (KeyError ):
254
- A2AServer ( mock_strands_agent , skills = None )
255
+ _ = a2a_agent . agent_skills
255
256
256
257
257
258
def test_agent_skills_setter (mock_strands_agent ):
@@ -262,9 +263,9 @@ def test_agent_skills_setter(mock_strands_agent):
262
263
mock_tool_config = {"test_tool" : {"name" : "test_tool" , "description" : "A test tool" }}
263
264
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
264
265
265
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
266
+ a2a_agent = A2AServer (mock_strands_agent )
266
267
267
- # Initially should get skills from tools
268
+ # Initially should get skills from tools (lazy loaded)
268
269
initial_skills = a2a_agent .agent_skills
269
270
assert len (initial_skills ) == 1
270
271
assert initial_skills [0 ].name == "test_tool"
@@ -293,7 +294,7 @@ def test_get_skills_from_tools_method(mock_strands_agent):
293
294
}
294
295
mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
295
296
296
- a2a_agent = A2AServer (mock_strands_agent , skills = None )
297
+ a2a_agent = A2AServer (mock_strands_agent )
297
298
skills = a2a_agent ._get_skills_from_tools ()
298
299
299
300
assert isinstance (skills , list )
@@ -317,7 +318,7 @@ def test_initialization_with_none_skills_uses_tools(mock_strands_agent):
317
318
318
319
a2a_agent = A2AServer (mock_strands_agent , skills = None )
319
320
320
- # Should get skills from tools
321
+ # Should get skills from tools (lazy loaded)
321
322
skills = a2a_agent .agent_skills
322
323
assert len (skills ) == 1
323
324
assert skills [0 ].name == "test_tool"
@@ -334,6 +335,70 @@ def test_initialization_with_empty_skills_list(mock_strands_agent):
334
335
assert len (skills ) == 0
335
336
336
337
338
+ def test_lazy_loading_behavior (mock_strands_agent ):
339
+ """Test that skills are only loaded from tools when accessed and no explicit skills are provided."""
340
+ mock_tool_config = {"test_tool" : {"name" : "test_tool" , "description" : "A test tool" }}
341
+ mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
342
+
343
+ # Create agent without explicit skills
344
+ a2a_agent = A2AServer (mock_strands_agent )
345
+
346
+ # Verify that _agent_skills is None initially (not loaded yet)
347
+ assert a2a_agent ._agent_skills is None
348
+
349
+ # Access agent_skills property - this should trigger lazy loading
350
+ skills = a2a_agent .agent_skills
351
+
352
+ # Verify skills were loaded from tools
353
+ assert len (skills ) == 1
354
+ assert skills [0 ].name == "test_tool"
355
+
356
+ # Verify that _agent_skills is still None (lazy loading doesn't cache)
357
+ assert a2a_agent ._agent_skills is None
358
+
359
+
360
+ def test_explicit_skills_override_tools (mock_strands_agent ):
361
+ """Test that explicitly provided skills override tool-based skills."""
362
+ from a2a .types import AgentSkill
363
+
364
+ # Mock tool registry with tools
365
+ mock_tool_config = {"test_tool" : {"name" : "test_tool" , "description" : "A test tool" }}
366
+ mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
367
+
368
+ # Provide explicit skills
369
+ explicit_skills = [AgentSkill (name = "explicit_skill" , id = "explicit_skill" , description = "An explicit skill" , tags = [])]
370
+
371
+ a2a_agent = A2AServer (mock_strands_agent , skills = explicit_skills )
372
+
373
+ # Should use explicit skills, not tools
374
+ skills = a2a_agent .agent_skills
375
+ assert len (skills ) == 1
376
+ assert skills [0 ].name == "explicit_skill"
377
+ assert skills [0 ].description == "An explicit skill"
378
+
379
+
380
+ def test_skills_not_loaded_during_initialization (mock_strands_agent ):
381
+ """Test that skills are not loaded from tools during initialization."""
382
+ # Create a mock that would raise an exception if called
383
+ mock_strands_agent .tool_registry .get_all_tools_config .side_effect = Exception ("Should not be called during init" )
384
+
385
+ # This should not raise an exception because tools are not accessed during initialization
386
+ a2a_agent = A2AServer (mock_strands_agent )
387
+
388
+ # Verify that _agent_skills is None
389
+ assert a2a_agent ._agent_skills is None
390
+
391
+ # Reset the mock to return proper data for when skills are actually accessed
392
+ mock_tool_config = {"test_tool" : {"name" : "test_tool" , "description" : "A test tool" }}
393
+ mock_strands_agent .tool_registry .get_all_tools_config .side_effect = None
394
+ mock_strands_agent .tool_registry .get_all_tools_config .return_value = mock_tool_config
395
+
396
+ # Now accessing skills should work
397
+ skills = a2a_agent .agent_skills
398
+ assert len (skills ) == 1
399
+ assert skills [0 ].name == "test_tool"
400
+
401
+
337
402
def test_public_agent_card_with_custom_skills (mock_strands_agent ):
338
403
"""Test that public_agent_card includes custom skills."""
339
404
from a2a .types import AgentSkill
0 commit comments