1414
1515from ..agent .agent_result import AgentResult
1616from ..types .content import Message , Messages
17- from ..types .streaming import Usage
17+ from ..types .streaming import StopReason , Usage
1818from ..types .tools import ToolResult , ToolUse
1919from ..types .traces import AttributeValue
2020
@@ -196,20 +196,31 @@ def end_span_with_error(self, span: Span, error_message: str, exception: Optiona
196196 error = exception or Exception (error_message )
197197 self ._end_span (span , error = error )
198198
199+ def _add_event (self , span : Optional [Span ], event_name : str , event_attributes : Dict [str , AttributeValue ]) -> None :
200+ """Add an event with attributes to a span.
201+
202+ Args:
203+ span: The span to add the event to
204+ event_name: Name of the event
205+ event_attributes: Dictionary of attributes to set on the event
206+ """
207+ if not span :
208+ return
209+
210+ span .add_event (event_name , attributes = event_attributes )
211+
199212 def start_model_invoke_span (
200213 self ,
214+ messages : Messages ,
201215 parent_span : Optional [Span ] = None ,
202- agent_name : str = "Strands Agent" ,
203- messages : Optional [Messages ] = None ,
204216 model_id : Optional [str ] = None ,
205217 ** kwargs : Any ,
206218 ) -> Optional [Span ]:
207219 """Start a new span for a model invocation.
208220
209221 Args:
222+ messages: Messages being sent to the model.
210223 parent_span: Optional parent span to link this span to.
211- agent_name: Name of the agent making the model call.
212- messages: Optional messages being sent to the model.
213224 model_id: Optional identifier for the model being invoked.
214225 **kwargs: Additional attributes to add to the span.
215226
@@ -219,8 +230,6 @@ def start_model_invoke_span(
219230 attributes : Dict [str , AttributeValue ] = {
220231 "gen_ai.system" : "strands-agents" ,
221232 "gen_ai.operation.name" : "chat" ,
222- "gen_ai.agent.name" : agent_name ,
223- "gen_ai.prompt" : serialize (messages ),
224233 }
225234
226235 if model_id :
@@ -229,28 +238,41 @@ def start_model_invoke_span(
229238 # Add additional kwargs as attributes
230239 attributes .update ({k : v for k , v in kwargs .items () if isinstance (v , (str , int , float , bool ))})
231240
232- return self ._start_span ("Model invoke" , parent_span , attributes , span_kind = trace_api .SpanKind .CLIENT )
241+ span = self ._start_span ("Model invoke" , parent_span , attributes , span_kind = trace_api .SpanKind .CLIENT )
242+ for message in messages :
243+ self ._add_event (
244+ span ,
245+ f"gen_ai.{ message ['role' ]} .message" ,
246+ {"content" : serialize (message ["content" ])},
247+ )
248+ return span
233249
234250 def end_model_invoke_span (
235- self , span : Span , message : Message , usage : Usage , error : Optional [Exception ] = None
251+ self , span : Span , message : Message , usage : Usage , stop_reason : StopReason , error : Optional [Exception ] = None
236252 ) -> None :
237253 """End a model invocation span with results and metrics.
238254
239255 Args:
240256 span: The span to end.
241257 message: The message response from the model.
242258 usage: Token usage information from the model call.
259+ stop_reason (StopReason): The reason the model stopped generating.
243260 error: Optional exception if the model call failed.
244261 """
245262 attributes : Dict [str , AttributeValue ] = {
246- "gen_ai.completion" : serialize (message ["content" ]),
247263 "gen_ai.usage.prompt_tokens" : usage ["inputTokens" ],
248264 "gen_ai.usage.input_tokens" : usage ["inputTokens" ],
249265 "gen_ai.usage.completion_tokens" : usage ["outputTokens" ],
250266 "gen_ai.usage.output_tokens" : usage ["outputTokens" ],
251267 "gen_ai.usage.total_tokens" : usage ["totalTokens" ],
252268 }
253269
270+ self ._add_event (
271+ span ,
272+ "gen_ai.choice" ,
273+ event_attributes = {"finish_reason" : str (stop_reason ), "message" : serialize (message ["content" ])},
274+ )
275+
254276 self ._end_span (span , attributes , error )
255277
256278 def start_tool_call_span (self , tool : ToolUse , parent_span : Optional [Span ] = None , ** kwargs : Any ) -> Optional [Span ]:
@@ -265,18 +287,29 @@ def start_tool_call_span(self, tool: ToolUse, parent_span: Optional[Span] = None
265287 The created span, or None if tracing is not enabled.
266288 """
267289 attributes : Dict [str , AttributeValue ] = {
268- "gen_ai.prompt " : serialize ( tool ) ,
290+ "gen_ai.operation.name " : "execute_tool" ,
269291 "gen_ai.system" : "strands-agents" ,
270- "tool.name" : tool ["name" ],
271- "tool.id" : tool ["toolUseId" ],
272- "tool.parameters" : serialize (tool ["input" ]),
292+ "gen_ai.tool.name" : tool ["name" ],
293+ "gen_ai.tool.call.id" : tool ["toolUseId" ],
273294 }
274295
275296 # Add additional kwargs as attributes
276297 attributes .update (kwargs )
277298
278299 span_name = f"Tool: { tool ['name' ]} "
279- return self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
300+ span = self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
301+
302+ self ._add_event (
303+ span ,
304+ "gen_ai.tool.message" ,
305+ event_attributes = {
306+ "role" : "tool" ,
307+ "content" : serialize (tool ["input" ]),
308+ "id" : tool ["toolUseId" ],
309+ },
310+ )
311+
312+ return span
280313
281314 def end_tool_call_span (
282315 self , span : Span , tool_result : Optional [ToolResult ], error : Optional [Exception ] = None
@@ -293,30 +326,36 @@ def end_tool_call_span(
293326 status = tool_result .get ("status" )
294327 status_str = str (status ) if status is not None else ""
295328
296- tool_result_content_json = serialize (tool_result .get ("content" ))
297329 attributes .update (
298330 {
299- "tool.result" : tool_result_content_json ,
300- "gen_ai.completion" : tool_result_content_json ,
301331 "tool.status" : status_str ,
302332 }
303333 )
304334
335+ self ._add_event (
336+ span ,
337+ "gen_ai.choice" ,
338+ event_attributes = {
339+ "message" : serialize (tool_result .get ("content" )),
340+ "id" : tool_result .get ("toolUseId" , "" ),
341+ },
342+ )
343+
305344 self ._end_span (span , attributes , error )
306345
307346 def start_event_loop_cycle_span (
308347 self ,
309348 event_loop_kwargs : Any ,
349+ messages : Messages ,
310350 parent_span : Optional [Span ] = None ,
311- messages : Optional [Messages ] = None ,
312351 ** kwargs : Any ,
313352 ) -> Optional [Span ]:
314353 """Start a new span for an event loop cycle.
315354
316355 Args:
317356 event_loop_kwargs: Arguments for the event loop cycle.
318357 parent_span: Optional parent span to link this span to.
319- messages: Optional messages being processed in this cycle.
358+ messages: Messages being processed in this cycle.
320359 **kwargs: Additional attributes to add to the span.
321360
322361 Returns:
@@ -326,7 +365,6 @@ def start_event_loop_cycle_span(
326365 parent_span = parent_span if parent_span else event_loop_kwargs .get ("event_loop_parent_span" )
327366
328367 attributes : Dict [str , AttributeValue ] = {
329- "gen_ai.prompt" : serialize (messages ),
330368 "event_loop.cycle_id" : event_loop_cycle_id ,
331369 }
332370
@@ -337,7 +375,15 @@ def start_event_loop_cycle_span(
337375 attributes .update ({k : v for k , v in kwargs .items () if isinstance (v , (str , int , float , bool ))})
338376
339377 span_name = f"Cycle { event_loop_cycle_id } "
340- return self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
378+ span = self ._start_span (span_name , parent_span , attributes )
379+ for message in messages or []:
380+ self ._add_event (
381+ span ,
382+ f"gen_ai.{ message ['role' ]} .message" ,
383+ {"content" : serialize (message ["content" ])},
384+ )
385+
386+ return span
341387
342388 def end_event_loop_cycle_span (
343389 self ,
@@ -354,13 +400,12 @@ def end_event_loop_cycle_span(
354400 tool_result_message: Optional tool result message if a tool was called.
355401 error: Optional exception if the cycle failed.
356402 """
357- attributes : Dict [str , AttributeValue ] = {
358- "gen_ai.completion" : serialize (message ["content" ]),
359- }
403+ attributes : Dict [str , AttributeValue ] = {}
404+ event_attributes : Dict [str , AttributeValue ] = {"message" : serialize (message ["content" ])}
360405
361406 if tool_result_message :
362- attributes ["tool.result" ] = serialize (tool_result_message ["content" ])
363-
407+ event_attributes ["tool.result" ] = serialize (tool_result_message ["content" ])
408+ self . _add_event ( span , "gen_ai.choice" , event_attributes = event_attributes )
364409 self ._end_span (span , attributes , error )
365410
366411 def start_agent_span (
@@ -387,17 +432,15 @@ def start_agent_span(
387432 """
388433 attributes : Dict [str , AttributeValue ] = {
389434 "gen_ai.system" : "strands-agents" ,
390- "agent.name" : agent_name ,
391435 "gen_ai.agent.name" : agent_name ,
392- "gen_ai.prompt " : prompt ,
436+ "gen_ai.operation.name " : "invoke_agent" ,
393437 }
394438
395439 if model_id :
396440 attributes ["gen_ai.request.model" ] = model_id
397441
398442 if tools :
399443 tools_json = serialize (tools )
400- attributes ["agent.tools" ] = tools_json
401444 attributes ["gen_ai.agent.tools" ] = tools_json
402445
403446 # Add custom trace attributes if provided
@@ -407,7 +450,18 @@ def start_agent_span(
407450 # Add additional kwargs as attributes
408451 attributes .update ({k : v for k , v in kwargs .items () if isinstance (v , (str , int , float , bool ))})
409452
410- return self ._start_span (agent_name , attributes = attributes , span_kind = trace_api .SpanKind .CLIENT )
453+ span = self ._start_span (
454+ f"invoke_agent { agent_name } " , attributes = attributes , span_kind = trace_api .SpanKind .CLIENT
455+ )
456+ self ._add_event (
457+ span ,
458+ "gen_ai.user.message" ,
459+ event_attributes = {
460+ "content" : prompt ,
461+ },
462+ )
463+
464+ return span
411465
412466 def end_agent_span (
413467 self ,
@@ -426,10 +480,10 @@ def end_agent_span(
426480 attributes : Dict [str , AttributeValue ] = {}
427481
428482 if response :
429- attributes . update (
430- {
431- "gen_ai.completion" : str ( response ) ,
432- }
483+ self . _add_event (
484+ span ,
485+ "gen_ai.choice" ,
486+ event_attributes = { "message" : str ( response ), "finish_reason" : str ( response . stop_reason )},
433487 )
434488
435489 if hasattr (response , "metrics" ) and hasattr (response .metrics , "accumulated_usage" ):
0 commit comments