diff --git a/agentops/instrumentation/providers/openai/attributes/response.py b/agentops/instrumentation/providers/openai/attributes/response.py index 9cf8f4b80..0b07dad83 100644 --- a/agentops/instrumentation/providers/openai/attributes/response.py +++ b/agentops/instrumentation/providers/openai/attributes/response.py @@ -462,9 +462,9 @@ def get_response_output_message_attributes(index: int, message: "ResponseOutputM attributes = _extract_attributes_from_mapping_with_index(message, RESPONSE_OUTPUT_MESSAGE_ATTRIBUTES, index) if message.content: - for i, content in enumerate(message.content): + for content in message.content: if isinstance(content, ResponseOutputText): - attributes.update(get_response_output_text_attributes(content, i)) + attributes.update(get_response_output_text_attributes(content, index)) else: logger.debug( diff --git a/tests/unit/instrumentation/openai_core/test_response_attributes.py b/tests/unit/instrumentation/openai_core/test_response_attributes.py index 24809423f..250138683 100644 --- a/tests/unit/instrumentation/openai_core/test_response_attributes.py +++ b/tests/unit/instrumentation/openai_core/test_response_attributes.py @@ -10,6 +10,8 @@ import os from unittest.mock import MagicMock, patch +from openai.types.responses import ResponseOutputMessage, ResponseOutputText, ResponseReasoningItem + from agentops.instrumentation.providers.openai.attributes.response import ( get_response_kwarg_attributes, get_response_response_attributes, @@ -400,6 +402,35 @@ def test_get_response_output_message_attributes(self): # Verify basic expected attributes assert isinstance(result, dict) + def test_response_message_content_uses_parent_output_index(self): + """Message text must share the parent output item's completion index.""" + reasoning = ResponseReasoningItem( + id="reasoning_1", + summary=[], + type="reasoning", + status="completed", + ) + message = ResponseOutputMessage( + id="msg_1", + content=[ + ResponseOutputText( + annotations=[], + text="answer", + type="output_text", + ) + ], + role="assistant", + status="completed", + type="message", + ) + + attributes = get_response_output_attributes([reasoning, message]) + + assert attributes[MessageAttributes.COMPLETION_ID.format(i=0)] == "reasoning_1" + assert MessageAttributes.COMPLETION_CONTENT.format(i=0) not in attributes + assert attributes[MessageAttributes.COMPLETION_ID.format(i=1)] == "msg_1" + assert attributes[MessageAttributes.COMPLETION_CONTENT.format(i=1)] == "answer" + def test_get_response_output_text_attributes(self): """Test extraction of attributes from output text""" # Create a mock text content