22from enum import Enum
33from inspect import signature
44from secrets import token_hex
5+ from types import AsyncGeneratorType , GeneratorType
56from typing import (
67 Any ,
8+ AsyncIterator ,
79 Awaitable ,
810 Callable ,
911 Dict ,
1012 Iterator ,
13+ List ,
1114 Mapping ,
1215 Optional ,
1316 OrderedDict ,
2023from opentelemetry import trace as trace_api
2124from opentelemetry .util .types import AttributeValue
2225
23- from agno .agent import Agent , RunOutput
26+ from agno .agent import Agent
2427from agno .models .base import Model
28+ from agno .run .agent import RunContentEvent , RunOutput , RunOutputEvent
2529from agno .run .messages import RunMessages
30+ from agno .run .team import RunContentEvent as TeamRunContentEvent
31+ from agno .run .team import TeamRunOutputEvent
2632from agno .team import Team
27- from agno .tools .function import Function , FunctionCall
33+ from agno .tools .function import Function , FunctionCall , ToolResult
2834from agno .tools .toolkit import Toolkit
2935from openinference .instrumentation import get_attributes_from_context , safe_json_dumps
3036from openinference .semconv .trace import (
@@ -210,7 +216,10 @@ def run(
210216 if hasattr (agent , "name" ) and agent .name :
211217 agent_name = agent .name .replace (" " , "_" ).replace ("-" , "_" )
212218 else :
213- agent_name = "Agent"
219+ if isinstance (agent , Team ):
220+ agent_name = "Team"
221+ else :
222+ agent_name = "Agent"
214223 span_name = f"{ agent_name } .run"
215224
216225 # Generate unique node ID for this execution
@@ -268,7 +277,10 @@ def run_stream(
268277 if hasattr (agent , "name" ) and agent .name :
269278 agent_name = agent .name .replace (" " , "_" ).replace ("-" , "_" )
270279 else :
271- agent_name = "Agent"
280+ if isinstance (agent , Team ):
281+ agent_name = "Team"
282+ else :
283+ agent_name = "Agent"
272284 span_name = f"{ agent_name } .run"
273285
274286 # Generate unique node ID for this execution
@@ -301,6 +313,7 @@ def run_stream(
301313 if hasattr (response , "run_id" ):
302314 current_run_id = response .run_id
303315 yield response
316+
304317 if (
305318 "session" in arguments
306319 and (session := arguments .get ("session" )) is not None
@@ -321,14 +334,20 @@ def run_stream(
321334 # Extract session_id from the session object
322335 session_id = None
323336 try :
324- session = arguments .get ("session" )
325- if session and hasattr (session , "session_id" ):
326- session_id = session .session_id
337+ if "session" in arguments :
338+ session = arguments .get ("session" )
339+ if session and hasattr (session , "session_id" ):
340+ session_id = session .session_id
341+ elif "session_id" in arguments :
342+ session_id = arguments .get ("session_id" )
327343 except Exception :
328344 session_id = None
329345
346+ if session_id is None :
347+ session_id = agent .session_id
348+
330349 run_response = None
331- if hasattr (agent , "get_last_run_output" ):
350+ if hasattr (agent , "get_last_run_output" ) and session_id is not None :
332351 run_response = agent .get_last_run_output (session_id = session_id )
333352
334353 span .set_status (trace_api .StatusCode .OK )
@@ -359,8 +378,11 @@ async def arun(
359378 if hasattr (agent , "name" ) and agent .name :
360379 agent_name = agent .name .replace (" " , "_" ).replace ("-" , "_" )
361380 else :
362- agent_name = "Agent"
363- span_name = f"{ agent_name } .run"
381+ if isinstance (agent , Team ):
382+ agent_name = "Team"
383+ else :
384+ agent_name = "Agent"
385+ span_name = f"{ agent_name } .arun"
364386
365387 # Generate unique node ID for this execution
366388 node_id = _generate_node_id ()
@@ -417,8 +439,11 @@ async def arun_stream(
417439 if hasattr (agent , "name" ) and agent .name :
418440 agent_name = agent .name .replace (" " , "_" ).replace ("-" , "_" )
419441 else :
420- agent_name = "Agent"
421- span_name = f"{ agent_name } .run"
442+ if isinstance (agent , Team ):
443+ agent_name = "Team"
444+ else :
445+ agent_name = "Agent"
446+ span_name = f"{ agent_name } .arun"
422447
423448 # Generate unique node ID for this execution
424449 node_id = _generate_node_id ()
@@ -472,14 +497,21 @@ async def arun_stream(
472497 # Extract session_id from the session object
473498 session_id = None
474499 try :
475- session = arguments .get ("session" )
476- if session and hasattr (session , "session_id" ):
477- session_id = session .session_id
500+ if "session" in arguments :
501+ session = arguments .get ("session" )
502+ if session and hasattr (session , "session_id" ):
503+ session_id = session .session_id
504+ elif "session_id" in arguments :
505+ session_id = arguments .get ("session_id" )
506+
478507 except Exception :
479508 session_id = None
480509
510+ if session_id is None :
511+ session_id = agent .session_id
512+
481513 run_response = None
482- if hasattr (agent , "get_last_run_output" ):
514+ if hasattr (agent , "get_last_run_output" ) and session_id is not None :
483515 run_response = agent .get_last_run_output (session_id = session_id )
484516
485517 span .set_status (trace_api .StatusCode .OK )
@@ -1013,7 +1045,25 @@ def run(
10131045 response = wrapped (* args , ** kwargs )
10141046
10151047 if response .status == "success" :
1016- function_result = function_call .result
1048+ function_result = ""
1049+ if isinstance (function_call .result , (GeneratorType , Iterator )):
1050+ events = []
1051+ for item in function_call .result :
1052+ if isinstance (item , RunContentEvent ) or isinstance (
1053+ item , TeamRunContentEvent
1054+ ):
1055+ function_result += self ._parse_content (item .content )
1056+ else :
1057+ function_result += str (item )
1058+ events .append (item )
1059+
1060+ # Convert back to iterator for downstream use
1061+ function_call .result = self ._generator_wrapper (events )
1062+ response .result = function_call .result
1063+ elif isinstance (function_call .result , ToolResult ):
1064+ function_result = function_call .result .content
1065+ else :
1066+ function_result = function_call .result
10171067 span .set_status (trace_api .StatusCode .OK )
10181068 span .set_attributes (
10191069 dict (
@@ -1061,7 +1111,38 @@ async def arun(
10611111 response = await wrapped (* args , ** kwargs )
10621112
10631113 if response .status == "success" :
1064- function_result = function_call .result
1114+ function_result = ""
1115+ if isinstance (function_call .result , (AsyncGeneratorType , AsyncIterator )):
1116+ events = []
1117+ async for item in function_call .result :
1118+ if isinstance (item , RunContentEvent ) or isinstance (
1119+ item , TeamRunContentEvent
1120+ ):
1121+ function_result += self ._parse_content (item .content )
1122+ else :
1123+ function_result += str (item )
1124+ events .append (item )
1125+ # Convert back to iterator for downstream use
1126+ function_call .result = self ._async_generator_wrapper (events )
1127+ response .result = function_call .result
1128+ elif isinstance (function_call .result , (GeneratorType , Iterator )):
1129+ events = []
1130+ for item in function_call .result :
1131+ if isinstance (item , RunContentEvent ) or isinstance (
1132+ item , TeamRunContentEvent
1133+ ):
1134+ function_result += self ._parse_content (item .content )
1135+ else :
1136+ function_result += str (item )
1137+ events .append (item )
1138+ # Convert back to iterator for downstream use
1139+ function_call .result = self ._generator_wrapper (events )
1140+ response .result = function_call .result
1141+ elif isinstance (function_call .result , ToolResult ):
1142+ function_result = function_call .result .content
1143+ else :
1144+ function_result = function_call .result
1145+
10651146 span .set_status (trace_api .StatusCode .OK )
10661147 span .set_attributes (
10671148 dict (
@@ -1080,6 +1161,29 @@ async def arun(
10801161
10811162 return response
10821163
1164+ def _generator_wrapper (
1165+ self ,
1166+ events : List [Union [RunOutputEvent , TeamRunOutputEvent ]],
1167+ ) -> Iterator [Union [RunOutputEvent , TeamRunOutputEvent ]]:
1168+ for event in events :
1169+ yield event
1170+
1171+ async def _async_generator_wrapper (
1172+ self ,
1173+ events : List [Union [RunOutputEvent , TeamRunOutputEvent ]],
1174+ ) -> AsyncIterator [Union [RunOutputEvent , TeamRunOutputEvent ]]:
1175+ for event in events :
1176+ yield event
1177+
1178+ def _parse_content (self , content : Any ) -> str :
1179+ from pydantic import BaseModel
1180+
1181+ if content is not None and isinstance (content , BaseModel ):
1182+ return str (content .model_dump_json ())
1183+ else :
1184+ # Capture output
1185+ return str (content ) if content else ""
1186+
10831187
10841188# span attributes
10851189INPUT_MIME_TYPE = SpanAttributes .INPUT_MIME_TYPE
0 commit comments