From 74c5409c0867e467376dd6548f46c67e74c2b1c9 Mon Sep 17 00:00:00 2001 From: Aaron Personal Date: Thu, 23 Jul 2026 13:16:14 +0530 Subject: [PATCH 1/5] feat(log-enrichment): add custom session ID attribute for enriched spans --- src/agentevals/trace_attrs.py | 3 +++ src/agentevals/utils/log_enrichment.py | 35 +++++++++++++++----------- tests/test_log_enrichment.py | 8 +++--- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/agentevals/trace_attrs.py b/src/agentevals/trace_attrs.py index 35da68a..32a4006 100644 --- a/src/agentevals/trace_attrs.py +++ b/src/agentevals/trace_attrs.py @@ -81,3 +81,6 @@ GENAI_ATTRIBUTE_ALIASES: dict[str, list[str]] = { OTEL_GENAI_PROVIDER_NAME: [OTEL_GENAI_SYSTEM], } + +# agentevals custom attributes (repository-specific, outside OTel semconv) +AGENTEVALS_SESSION_ID = "agentevals.session.id" diff --git a/src/agentevals/utils/log_enrichment.py b/src/agentevals/utils/log_enrichment.py index eecd3d4..1107dfe 100644 --- a/src/agentevals/utils/log_enrichment.py +++ b/src/agentevals/utils/log_enrichment.py @@ -7,7 +7,7 @@ from collections import defaultdict from ..trace_attrs import ( - OTEL_GENAI_AGENT_NAME, + AGENTEVALS_SESSION_ID, OTEL_GENAI_INPUT_MESSAGES, OTEL_GENAI_OUTPUT_MESSAGES, ) @@ -28,7 +28,7 @@ def enrich_spans_with_logs(spans: list[dict], logs: list[dict], session_id: str Args: spans: List of OTLP span dictionaries logs: List of GenAI log event dictionaries - session_id: Optional session ID to add as agent.name attribute + session_id: Optional session ID to add as the agentevals.session.id attribute Returns: List of enriched span dictionaries with message attributes added @@ -88,6 +88,22 @@ def _extract_messages_from_logs( return input_messages, output_messages +def _append_session_id(attrs: list[dict], session_id: str | None) -> None: + """Append the session ID attribute to *attrs* in place, if present. + + Written to the custom ``agentevals.session.id`` attribute rather than + ``gen_ai.agent.name`` so real agent names (from the SDK or OTLP) are + never overwritten. + """ + if session_id: + attrs.append( + { + "key": AGENTEVALS_SESSION_ID, + "value": {"stringValue": session_id}, + } + ) + + def _inject_messages( span: dict, input_messages: list[dict], @@ -113,13 +129,7 @@ def _inject_messages( "value": {"stringValue": json.dumps(output_messages)}, } ) - if session_id: - attrs.append( - { - "key": OTEL_GENAI_AGENT_NAME, - "value": {"stringValue": session_id}, - } - ) + _append_session_id(attrs, session_id) return span_copy @@ -148,12 +158,7 @@ def _enrich_per_span( span_copy = span.copy() if session_id: attrs = list(span_copy.get("attributes", [])) - attrs.append( - { - "key": OTEL_GENAI_AGENT_NAME, - "value": {"stringValue": session_id}, - } - ) + _append_session_id(attrs, session_id) span_copy["attributes"] = attrs enriched.append(span_copy) diff --git a/tests/test_log_enrichment.py b/tests/test_log_enrichment.py index 42361a7..ccac523 100644 --- a/tests/test_log_enrichment.py +++ b/tests/test_log_enrichment.py @@ -84,8 +84,8 @@ def test_session_id_injected(self): logs = [_make_log("gen_ai.user.message", {"content": "hi"})] result = enrich_spans_with_logs(spans, logs, session_id="my-session") - agent_name = _get_injected_attr(result[0], "gen_ai.agent.name", parse_json=False) - assert agent_name == "my-session" + session_attr = _get_injected_attr(result[0], "agentevals.session.id", parse_json=False) + assert session_attr == "my-session" def test_choice_extracts_nested_content(self): spans = [_make_span()] @@ -156,8 +156,8 @@ def test_session_id_on_all_spans(self): ] result = enrich_spans_with_logs(spans, logs, session_id="test") - assert _get_injected_attr(result[0], "gen_ai.agent.name", parse_json=False) == "test" - assert _get_injected_attr(result[1], "gen_ai.agent.name", parse_json=False) == "test" + assert _get_injected_attr(result[0], "agentevals.session.id", parse_json=False) == "test" + assert _get_injected_attr(result[1], "agentevals.session.id", parse_json=False) == "test" def test_tool_calls_in_assistant_message(self): spans = [_make_span("s1")] From 844b4746abcfe2d640e8352e073a969cd52c9333 Mon Sep 17 00:00:00 2001 From: Aaron Personal Date: Fri, 24 Jul 2026 18:28:44 +0530 Subject: [PATCH 2/5] fix(log-enrichment): update session ID attribute to use underscore notation --- src/agentevals/trace_attrs.py | 2 +- src/agentevals/utils/log_enrichment.py | 4 ++-- tests/test_log_enrichment.py | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/agentevals/trace_attrs.py b/src/agentevals/trace_attrs.py index 32a4006..e4cd16a 100644 --- a/src/agentevals/trace_attrs.py +++ b/src/agentevals/trace_attrs.py @@ -83,4 +83,4 @@ } # agentevals custom attributes (repository-specific, outside OTel semconv) -AGENTEVALS_SESSION_ID = "agentevals.session.id" +AGENTEVALS_SESSION_ID = "agentevals.session_id" diff --git a/src/agentevals/utils/log_enrichment.py b/src/agentevals/utils/log_enrichment.py index 1107dfe..c58f4fa 100644 --- a/src/agentevals/utils/log_enrichment.py +++ b/src/agentevals/utils/log_enrichment.py @@ -28,7 +28,7 @@ def enrich_spans_with_logs(spans: list[dict], logs: list[dict], session_id: str Args: spans: List of OTLP span dictionaries logs: List of GenAI log event dictionaries - session_id: Optional session ID to add as the agentevals.session.id attribute + session_id: Optional session ID to add as the agentevals.session_id attribute Returns: List of enriched span dictionaries with message attributes added @@ -91,7 +91,7 @@ def _extract_messages_from_logs( def _append_session_id(attrs: list[dict], session_id: str | None) -> None: """Append the session ID attribute to *attrs* in place, if present. - Written to the custom ``agentevals.session.id`` attribute rather than + Written to the custom ``agentevals.session_id`` attribute rather than ``gen_ai.agent.name`` so real agent names (from the SDK or OTLP) are never overwritten. """ diff --git a/tests/test_log_enrichment.py b/tests/test_log_enrichment.py index ccac523..ba71351 100644 --- a/tests/test_log_enrichment.py +++ b/tests/test_log_enrichment.py @@ -84,7 +84,7 @@ def test_session_id_injected(self): logs = [_make_log("gen_ai.user.message", {"content": "hi"})] result = enrich_spans_with_logs(spans, logs, session_id="my-session") - session_attr = _get_injected_attr(result[0], "agentevals.session.id", parse_json=False) + session_attr = _get_injected_attr(result[0], "agentevals.session_id", parse_json=False) assert session_attr == "my-session" def test_choice_extracts_nested_content(self): @@ -156,8 +156,8 @@ def test_session_id_on_all_spans(self): ] result = enrich_spans_with_logs(spans, logs, session_id="test") - assert _get_injected_attr(result[0], "agentevals.session.id", parse_json=False) == "test" - assert _get_injected_attr(result[1], "agentevals.session.id", parse_json=False) == "test" + assert _get_injected_attr(result[0], "agentevals.session_id", parse_json=False) == "test" + assert _get_injected_attr(result[1], "agentevals.session_id", parse_json=False) == "test" def test_tool_calls_in_assistant_message(self): spans = [_make_span("s1")] From f21396efc37c024faedb0effee13165413f2dc5f Mon Sep 17 00:00:00 2001 From: Aaron Personal Date: Fri, 24 Jul 2026 18:34:57 +0530 Subject: [PATCH 3/5] tests: add regression test for agent name preservation with session ID --- tests/test_log_enrichment.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_log_enrichment.py b/tests/test_log_enrichment.py index ba71351..5a39289 100644 --- a/tests/test_log_enrichment.py +++ b/tests/test_log_enrichment.py @@ -139,6 +139,22 @@ def test_logs_matched_to_correct_span(self): msgs_s2 = _get_injected_attr(result[1], "gen_ai.input.messages") assert msgs_s2 == [{"role": "user", "content": "question 2"}] + def test_agent_name_preserved_with_session_id(self): + """Regression: real gen_ai.agent.name attr must survive enrichment, + session_id lands in its own attr, doesn't clobber it.""" + span = _make_span( + "s1", + attrs=[{"key": "gen_ai.agent.name", "value": {"stringValue": "roll_die_agent"}}], + ) + logs = [_make_log("gen_ai.user.message", {"content": "hi"}, span_id="s1")] + result = enrich_spans_with_logs([span], logs, session_id="sess-123") + + agent_name = _get_injected_attr(result[0], "gen_ai.agent.name", parse_json=False) + assert agent_name == "roll_die_agent" + + session_attr = _get_injected_attr(result[0], "agentevals.session_id", parse_json=False) + assert session_attr == "sess-123" + def test_span_without_logs_not_enriched(self): spans = [_make_span("s1"), _make_span("s2")] logs = [ From 67e3274d6e7f59026bcf406eb42047beacb4adaf Mon Sep 17 00:00:00 2001 From: Aaron Personal Date: Fri, 24 Jul 2026 19:09:54 +0530 Subject: [PATCH 4/5] test: enhance session ID and agent name assertions --- tests/test_log_enrichment.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_log_enrichment.py b/tests/test_log_enrichment.py index 5a39289..dc03268 100644 --- a/tests/test_log_enrichment.py +++ b/tests/test_log_enrichment.py @@ -149,8 +149,13 @@ def test_agent_name_preserved_with_session_id(self): logs = [_make_log("gen_ai.user.message", {"content": "hi"}, span_id="s1")] result = enrich_spans_with_logs([span], logs, session_id="sess-123") - agent_name = _get_injected_attr(result[0], "gen_ai.agent.name", parse_json=False) - assert agent_name == "roll_die_agent" + agent_name_attrs = [ + a for a in result[0]["attributes"] if a["key"] == "gen_ai.agent.name" + ] + assert len(agent_name_attrs) == 1, ( + f"expected exactly one gen_ai.agent.name attr, found {len(agent_name_attrs)}" + ) + assert agent_name_attrs[0]["value"]["stringValue"] == "roll_die_agent" session_attr = _get_injected_attr(result[0], "agentevals.session_id", parse_json=False) assert session_attr == "sess-123" From 7ef33b6eda8cafb5b0bd7a3e47134e67476ce2b8 Mon Sep 17 00:00:00 2001 From: Aaron Personal Date: Fri, 24 Jul 2026 19:14:05 +0530 Subject: [PATCH 5/5] style: ruff format check --- tests/test_log_enrichment.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/test_log_enrichment.py b/tests/test_log_enrichment.py index dc03268..d5830a0 100644 --- a/tests/test_log_enrichment.py +++ b/tests/test_log_enrichment.py @@ -149,12 +149,8 @@ def test_agent_name_preserved_with_session_id(self): logs = [_make_log("gen_ai.user.message", {"content": "hi"}, span_id="s1")] result = enrich_spans_with_logs([span], logs, session_id="sess-123") - agent_name_attrs = [ - a for a in result[0]["attributes"] if a["key"] == "gen_ai.agent.name" - ] - assert len(agent_name_attrs) == 1, ( - f"expected exactly one gen_ai.agent.name attr, found {len(agent_name_attrs)}" - ) + agent_name_attrs = [a for a in result[0]["attributes"] if a["key"] == "gen_ai.agent.name"] + assert len(agent_name_attrs) == 1, f"expected exactly one gen_ai.agent.name attr, found {len(agent_name_attrs)}" assert agent_name_attrs[0]["value"]["stringValue"] == "roll_die_agent" session_attr = _get_injected_attr(result[0], "agentevals.session_id", parse_json=False)