Skip to content

Commit 91caaee

Browse files
authored
Merge branch 'Arize-ai:main' into alisaleh/ticket-2037
2 parents f379059 + 11aefbc commit 91caaee

File tree

5 files changed

+147
-24
lines changed

5 files changed

+147
-24
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"python/openinference-semantic-conventions": "0.1.24",
3-
"python/instrumentation/openinference-instrumentation-agno": "0.1.18",
3+
"python/instrumentation/openinference-instrumentation-agno": "0.1.19",
44
"python/instrumentation/openinference-instrumentation-openai": "0.1.39",
55
"python/instrumentation/openinference-instrumentation-llama-index": "4.3.7",
66
"python/instrumentation/openinference-instrumentation-dspy": "0.1.30",

python/instrumentation/openinference-instrumentation-agno/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [0.1.19](https://github.com/Arize-ai/openinference/compare/python-openinference-instrumentation-agno-v0.1.18...python-openinference-instrumentation-agno-v0.1.19) (2025-10-22)
4+
5+
6+
### Bug Fixes
7+
8+
* Agno Session ID issues ([#2313](https://github.com/Arize-ai/openinference/issues/2313)) ([34402a0](https://github.com/Arize-ai/openinference/commit/34402a0a8478e1b047a76c6a885c5256cec015bc))
9+
310
## [0.1.18](https://github.com/Arize-ai/openinference/compare/python-openinference-instrumentation-agno-v0.1.17...python-openinference-instrumentation-agno-v0.1.18) (2025-10-15)
411

512

python/instrumentation/openinference-instrumentation-agno/src/openinference/instrumentation/agno/__init__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,20 +215,32 @@ def _uninstrument(self, **kwargs: Any) -> None:
215215
from agno.tools.function import FunctionCall
216216

217217
if self._original_run_method is not None:
218-
Agent.run = self._original_run_method # type: ignore[method-assign]
218+
Agent._run = self._original_run_method # type: ignore[method-assign]
219219
self._original_run_method = None
220+
if self._original_run_stream_method is not None:
221+
Agent._run_stream = self._original_run_stream_method # type: ignore[method-assign]
222+
self._original_run_stream_method = None
220223

221224
if self._original_arun_method is not None:
222-
Agent.arun = self._original_arun_method # type: ignore[method-assign]
225+
Agent._arun = self._original_arun_method # type: ignore[method-assign]
223226
self._original_arun_method = None
227+
if self._original_arun_stream_method is not None:
228+
Agent._arun_stream = self._original_arun_stream_method # type: ignore[method-assign]
229+
self._original_arun_stream_method = None
224230

225231
if self._original_team_run_method is not None:
226-
Team.run = self._original_team_run_method # type: ignore[method-assign]
232+
Team._run = self._original_team_run_method # type: ignore[method-assign]
227233
self._original_team_run_method = None
234+
if self._original_team_run_stream_method is not None:
235+
Team._run_stream = self._original_team_run_stream_method # type: ignore[method-assign]
236+
self._original_team_run_stream_method = None
228237

229238
if self._original_team_arun_method is not None:
230-
Team.arun = self._original_team_arun_method # type: ignore[method-assign]
239+
Team._arun = self._original_team_arun_method # type: ignore[method-assign]
231240
self._original_team_arun_method = None
241+
if self._original_team_arun_stream_method is not None:
242+
Team._arun_stream = self._original_team_arun_stream_method # type: ignore[method-assign]
243+
self._original_team_arun_stream_method = None
232244

233245
if self._original_model_call_methods is not None:
234246
for (

python/instrumentation/openinference-instrumentation-agno/src/openinference/instrumentation/agno/_wrappers.py

Lines changed: 122 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
from enum import Enum
33
from inspect import signature
44
from secrets import token_hex
5+
from types import AsyncGeneratorType, GeneratorType
56
from typing import (
67
Any,
8+
AsyncIterator,
79
Awaitable,
810
Callable,
911
Dict,
1012
Iterator,
13+
List,
1114
Mapping,
1215
Optional,
1316
OrderedDict,
@@ -20,11 +23,14 @@
2023
from opentelemetry import trace as trace_api
2124
from opentelemetry.util.types import AttributeValue
2225

23-
from agno.agent import Agent, RunOutput
26+
from agno.agent import Agent
2427
from agno.models.base import Model
28+
from agno.run.agent import RunContentEvent, RunOutput, RunOutputEvent
2529
from agno.run.messages import RunMessages
30+
from agno.run.team import RunContentEvent as TeamRunContentEvent
31+
from agno.run.team import TeamRunOutputEvent
2632
from agno.team import Team
27-
from agno.tools.function import Function, FunctionCall
33+
from agno.tools.function import Function, FunctionCall, ToolResult
2834
from agno.tools.toolkit import Toolkit
2935
from openinference.instrumentation import get_attributes_from_context, safe_json_dumps
3036
from 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
10851189
INPUT_MIME_TYPE = SpanAttributes.INPUT_MIME_TYPE
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.1.18"
1+
__version__ = "0.1.19"

0 commit comments

Comments
 (0)