@@ -342,6 +342,7 @@ async def _execute_handoff(
342342 ctx = run_context .context .context
343343 event = run_context .context .event
344344 umo = event .unified_msg_origin
345+ agent_name = getattr (tool .agent , "name" , "unknown" )
345346
346347 # Use per-subagent provider override if configured; otherwise fall back
347348 # to the current/default provider resolution.
@@ -368,10 +369,38 @@ async def _execute_handoff(
368369 agent_max_step = int (prov_settings .get ("max_agent_step" , 30 ))
369370 stream = prov_settings .get ("streaming_response" , False )
370371
372+ # Create trace span for subagent execution
373+ from astrbot .core .utils .trace import TraceSpan
374+
375+ parent_trace = getattr (event , "trace" , None )
376+ subagent_trace = TraceSpan (
377+ name = f"SubAgent:{ agent_name } " ,
378+ umo = event .unified_msg_origin ,
379+ sender_name = event .get_sender_name ()
380+ if hasattr (event , "get_sender_name" )
381+ else None ,
382+ message_outline = f"Handoff to { agent_name } : { input_ [:100 ] if input_ else '' } " ,
383+ parent_span_id = parent_trace .span_id if parent_trace else None ,
384+ )
385+ subagent_trace .record (
386+ "subagent_execution_begin" ,
387+ agent_name = agent_name ,
388+ input_preview = input_ [:500 ] if input_ else None ,
389+ image_count = len (image_urls ),
390+ tools = [t .name for t in toolset ] if toolset else [],
391+ max_steps = agent_max_step ,
392+ stream = stream ,
393+ )
394+
371395 # 获取子代理的历史上下文
372396 subagent_history , agent_name = cls ._load_subagent_history (umo , tool )
373397 # 如果有历史上下文,合并到 contexts 中
374398 if subagent_history :
399+ subagent_trace .record (
400+ "subagent_history_loaded" ,
401+ agent_name = agent_name ,
402+ history_messages_count = len (subagent_history ),
403+ )
375404 if contexts is None :
376405 contexts = subagent_history
377406 else :
@@ -381,6 +410,14 @@ async def _execute_handoff(
381410 subagent_system_prompt = cls ._build_subagent_system_prompt (
382411 umo , tool , prov_settings
383412 )
413+ subagent_trace .record (
414+ "subagent_system_prompt" ,
415+ agent_name = agent_name ,
416+ prompt_length = len (subagent_system_prompt ),
417+ prompt_preview = subagent_system_prompt [:300 ]
418+ if subagent_system_prompt
419+ else None ,
420+ )
384421
385422 # 构建子代理的追加内容
386423 extra_content_parts = SubAgentManager .build_subagent_extra_content_parts (
@@ -408,6 +445,7 @@ async def _run_subagent():
408445 stream = stream ,
409446 runner_messages = runner_messages ,
410447 extra_user_content_parts = extra_content_parts ,
448+ trace_span = subagent_trace ,
411449 )
412450
413451 # 添加执行超时控制
@@ -419,6 +457,10 @@ async def _run_subagent():
419457 except asyncio .TimeoutError :
420458 # 若超时,保存已产生的部分历史
421459 cls ._save_subagent_history (umo , runner_messages , agent_name )
460+ subagent_trace .record (
461+ "subagent_execution_timeout" ,
462+ timeout_seconds = execution_timeout ,
463+ )
422464 error_msg = f"SubAgent '{ agent_name } ' execution timeout after { execution_timeout :.1f} seconds."
423465 logger .warning (f"[SubAgent:Timeout] { error_msg } " )
424466
@@ -433,8 +475,26 @@ async def _run_subagent():
433475 else :
434476 # 不设置超时
435477 llm_resp = await _run_subagent ()
478+
479+ execution_time = time .time () - subagent_trace .started_at
480+ subagent_trace .record (
481+ "subagent_execution_complete" ,
482+ agent_name = agent_name ,
483+ result_preview = llm_resp .completion_text [:500 ]
484+ if hasattr (llm_resp , "completion_text" ) and llm_resp .completion_text
485+ else None ,
486+ result_length = len (llm_resp .completion_text )
487+ if hasattr (llm_resp , "completion_text" ) and llm_resp .completion_text
488+ else 0 ,
489+ execution_time = execution_time ,
490+ )
491+
436492 # 保存历史上下文
437493 cls ._save_subagent_history (umo , runner_messages , agent_name )
494+ subagent_trace .record (
495+ "subagent_history_saved" ,
496+ messages_count = len (runner_messages ),
497+ )
438498
439499 yield mcp .types .CallToolResult (
440500 content = [mcp .types .TextContent (type = "text" , text = llm_resp .completion_text )]
@@ -467,6 +527,26 @@ async def _execute_handoff_background(
467527
468528 original_task_id = uuid .uuid4 ().hex
469529
530+ # Create trace span for background task creation
531+ from astrbot .core .utils .trace import TraceSpan
532+
533+ parent_trace = getattr (event , "trace" , None )
534+ bg_trace = TraceSpan (
535+ name = f"SubAgentBackground:{ agent_name } " ,
536+ umo = event .unified_msg_origin ,
537+ sender_name = event .get_sender_name ()
538+ if hasattr (event , "get_sender_name" )
539+ else None ,
540+ message_outline = f"Background handoff to { agent_name } " ,
541+ parent_span_id = parent_trace .span_id if parent_trace else None ,
542+ )
543+ bg_trace .record (
544+ "subagent_background_task_created" ,
545+ agent_name = agent_name ,
546+ subagent_task_id = subagent_task_id ,
547+ original_task_id = original_task_id ,
548+ )
549+
470550 async def _run_handoff_in_background () -> None :
471551 try :
472552 await cls ._do_handoff_background (
@@ -515,6 +595,25 @@ async def _do_handoff_background(
515595 event = run_context .context .event
516596 umo = event .unified_msg_origin
517597 agent_name = getattr (tool .agent , "name" , None )
598+
599+ # Create trace span for background subagent execution
600+ from astrbot .core .utils .trace import TraceSpan
601+
602+ parent_trace = getattr (event , "trace" , None )
603+ bg_trace = TraceSpan (
604+ name = f"SubAgentBackground:{ agent_name } " ,
605+ umo = event .unified_msg_origin ,
606+ sender_name = event .get_sender_name ()
607+ if hasattr (event , "get_sender_name" )
608+ else None ,
609+ message_outline = f"Background handoff to { agent_name } " ,
610+ parent_span_id = parent_trace .span_id if parent_trace else None ,
611+ )
612+ bg_trace .record (
613+ "subagent_background_execution_start" ,
614+ agent_name = agent_name ,
615+ )
616+
518617 # 获取SubAgent的超时时间
519618 execution_timeout = cls ._get_subagent_execution_timeout ()
520619
@@ -550,6 +649,14 @@ async def _run():
550649 )
551650
552651 execution_time = time .time () - start_time
652+ bg_trace .record (
653+ "subagent_background_execution_end" ,
654+ agent_name = agent_name ,
655+ success = error_text is None ,
656+ result_preview = result_text [:500 ] if result_text else None ,
657+ execution_time = execution_time ,
658+ )
659+
553660 # Check if it's enhanced subagent
554661 is_managed = cls ._is_managed_subagent (umo , agent_name )
555662 if is_managed :
0 commit comments