13
13
14
14
from azure .ai .agents .telemetry import AIAgentsInstrumentor
15
15
16
+ from azure .ai .agents .models import DeepResearchTool
17
+
16
18
from gen_ai_trace_verifier import GenAiTraceVerifier
17
19
from memory_trace_exporter import MemoryTraceExporter
18
20
from test_agents_client_base import TestAgentClientBase
@@ -49,6 +51,17 @@ def cleanup(self):
49
51
trace ._TRACER_PROVIDER = None
50
52
os .environ .pop (CONTENT_TRACING_ENV_VARIABLE , None )
51
53
54
+ def _get_deep_research_tool (self , ** kwargs ):
55
+ """Get deep research tool."""
56
+ bing_conn_id = kwargs .pop ("azure_ai_agents_tests_bing_connection_id" )
57
+ deep_research_model = kwargs .pop ("azure_ai_agents_tests_deep_research_model" )
58
+
59
+ # Create DeepResearchTool
60
+ return DeepResearchTool (
61
+ bing_grounding_connection_id = bing_conn_id ,
62
+ deep_research_model = deep_research_model ,
63
+ )
64
+
52
65
def _check_spans (
53
66
self ,
54
67
model : str ,
@@ -60,6 +73,7 @@ def _check_spans(
60
73
tool_message_attribute_content : str ,
61
74
event_contents : List [str ],
62
75
run_step_events : Optional [List [List [Dict [str , Any ]]]] = None ,
76
+ has_annotations : bool = False ,
63
77
):
64
78
"""Check the spans for correctness."""
65
79
spans = self .exporter .get_spans_by_name ("create_agent my-agent" )
@@ -210,7 +224,7 @@ def _check_spans(
210
224
assert events_match == True
211
225
212
226
spans = self .exporter .get_spans_by_name ("list_messages" )
213
- assert len (spans ) = = 2
227
+ assert len (spans ) > = 2
214
228
span = spans [0 ]
215
229
expected_attributes = [
216
230
("gen_ai.system" , "az.ai.agents" ),
@@ -221,7 +235,13 @@ def _check_spans(
221
235
attributes_match = GenAiTraceVerifier ().check_span_attributes (span , expected_attributes )
222
236
assert attributes_match == True
223
237
224
- content = '{"content": {"text": {"value": "*"}}, "role": "assistant"}' if recording_enabled else '{"role": "assistant"}'
238
+ if recording_enabled :
239
+ if has_annotations :
240
+ content = '{"content": {"text": {"value": "*", "annotations": "*"}}, "role": "assistant"}'
241
+ else :
242
+ content = '{"content": {"text": {"value": "*"}}, "role": "assistant"}'
243
+ else :
244
+ content = '{"role": "assistant"}'
225
245
expected_events = [
226
246
{
227
247
"name" : "gen_ai.assistant.message" ,
@@ -239,7 +259,7 @@ def _check_spans(
239
259
events_match = GenAiTraceVerifier ().check_span_events (span , expected_events )
240
260
assert events_match == True
241
261
242
- span = spans [1 ]
262
+ span = spans [- 1 ]
243
263
attributes_match = GenAiTraceVerifier ().check_span_attributes (span , expected_attributes )
244
264
assert attributes_match == True
245
265
@@ -260,15 +280,21 @@ def _check_spans(
260
280
261
281
spans = self .exporter .get_spans_by_name ("list_run_steps" )
262
282
if run_step_events :
263
- assert len (spans ) == len (run_step_events )
264
283
expected_attributes = [
265
284
("gen_ai.system" , "az.ai.agents" ),
266
285
("gen_ai.operation.name" , "list_run_steps" ),
267
286
("server.address" , "" ),
268
287
("gen_ai.thread.id" , "" ),
269
288
("gen_ai.thread.run.id" , "" ),
270
289
]
271
- for span , expected_span_events in zip (spans , run_step_events ):
290
+ if len (spans ) < 5 :
291
+ assert len (spans ) == len (run_step_events )
292
+ zip_obj = zip (spans , run_step_events )
293
+ else :
294
+ assert len (run_step_events ) == 5
295
+ # If it is deep research there may be multiple run steps.
296
+ zip_obj = zip (spans [:3 ] + spans [- 2 :], run_step_events )
297
+ for span , expected_span_events in zip_obj :
272
298
attributes_match = GenAiTraceVerifier ().check_span_attributes (span , expected_attributes )
273
299
assert attributes_match == True
274
300
events_match = GenAiTraceVerifier ().check_span_events (span , expected_span_events )
@@ -411,4 +437,57 @@ def get_expected_mcp_spans(self):
411
437
])
412
438
expected_spans .append ([])
413
439
return expected_spans
414
-
440
+
441
+ def get_expected_deep_research_spans (self ):
442
+ expected_event_content = json .dumps (
443
+ {'tool_calls' :
444
+ [
445
+ {
446
+ "id" : "*" ,
447
+ "type" : "deep_research" ,
448
+ "deep_research" : {
449
+ "input" : "*" ,
450
+ "output" : "*"
451
+ },
452
+ }
453
+ ]
454
+ }
455
+ )
456
+
457
+ expected_spans = [
458
+ [
459
+ {
460
+ "name" : "gen_ai.run_step.message_creation" ,
461
+ "attributes" : {
462
+ "gen_ai.system" : "az.ai.agents" ,
463
+ "gen_ai.thread.id" : "*" ,
464
+ "gen_ai.agent.id" : "*" ,
465
+ "gen_ai.thread.run.id" : "*" ,
466
+ "gen_ai.message.id" : "*" ,
467
+ "gen_ai.run_step.status" : "completed" ,
468
+ "gen_ai.run_step.start.timestamp" : "*" ,
469
+ "gen_ai.run_step.end.timestamp" : "*" ,
470
+ "gen_ai.usage.input_tokens" : 0 ,
471
+ "gen_ai.usage.output_tokens" : 0 ,
472
+ },
473
+ },
474
+ ]
475
+ ] * 4
476
+ expected_spans .append ([
477
+ {
478
+ "name" : "gen_ai.run_step.tool_calls" ,
479
+ "attributes" : {
480
+ "gen_ai.system" : "az.ai.agents" ,
481
+ "gen_ai.thread.id" : "*" ,
482
+ "gen_ai.agent.id" : "*" ,
483
+ "gen_ai.thread.run.id" : "*" ,
484
+ "gen_ai.run_step.status" : "completed" ,
485
+ "gen_ai.run_step.start.timestamp" : "*" ,
486
+ "gen_ai.run_step.end.timestamp" : "*" ,
487
+ "gen_ai.usage.input_tokens" : "+" ,
488
+ "gen_ai.usage.output_tokens" : "+" ,
489
+ "gen_ai.event.content" : expected_event_content
490
+ },
491
+ },
492
+ ])
493
+ return expected_spans
0 commit comments