@@ -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,7 +238,14 @@ 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 (
235251 self , span : Span , message : Message , usage : Usage , error : Optional [Exception ] = None
@@ -243,14 +259,19 @@ def end_model_invoke_span(
243259 error: Optional exception if the model call failed.
244260 """
245261 attributes : Dict [str , AttributeValue ] = {
246- "gen_ai.completion" : serialize (message ["content" ]),
247262 "gen_ai.usage.prompt_tokens" : usage ["inputTokens" ],
248263 "gen_ai.usage.input_tokens" : usage ["inputTokens" ],
249264 "gen_ai.usage.completion_tokens" : usage ["outputTokens" ],
250265 "gen_ai.usage.output_tokens" : usage ["outputTokens" ],
251266 "gen_ai.usage.total_tokens" : usage ["totalTokens" ],
252267 }
253268
269+ self ._add_event (
270+ span ,
271+ "gen_ai.choice" ,
272+ event_attributes = {"finish_reason" : "stop" , "message" : serialize (message ["content" ])},
273+ )
274+
254275 self ._end_span (span , attributes , error )
255276
256277 def start_tool_call_span (self , tool : ToolUse , parent_span : Optional [Span ] = None , ** kwargs : Any ) -> Optional [Span ]:
@@ -265,18 +286,29 @@ def start_tool_call_span(self, tool: ToolUse, parent_span: Optional[Span] = None
265286 The created span, or None if tracing is not enabled.
266287 """
267288 attributes : Dict [str , AttributeValue ] = {
268- "gen_ai.prompt " : serialize ( tool ) ,
289+ "gen_ai.operation.name " : "execute_tool" ,
269290 "gen_ai.system" : "strands-agents" ,
270- "tool.name" : tool ["name" ],
271- "tool.id" : tool ["toolUseId" ],
272- "tool.parameters" : serialize (tool ["input" ]),
291+ "gen_ai.tool.name" : tool ["name" ],
292+ "gen_ai.tool.call.id" : tool ["toolUseId" ],
273293 }
274294
275295 # Add additional kwargs as attributes
276296 attributes .update (kwargs )
277297
278298 span_name = f"Tool: { tool ['name' ]} "
279- return self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
299+ span = self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
300+
301+ self ._add_event (
302+ span ,
303+ "gen_ai.tool.message" ,
304+ event_attributes = {
305+ "role" : "tool" ,
306+ "content" : serialize (tool ["input" ]),
307+ "id" : tool ["toolUseId" ],
308+ },
309+ )
310+
311+ return span
280312
281313 def end_tool_call_span (
282314 self , span : Span , tool_result : Optional [ToolResult ], error : Optional [Exception ] = None
@@ -293,30 +325,36 @@ def end_tool_call_span(
293325 status = tool_result .get ("status" )
294326 status_str = str (status ) if status is not None else ""
295327
296- tool_result_content_json = serialize (tool_result .get ("content" ))
297328 attributes .update (
298329 {
299- "tool.result" : tool_result_content_json ,
300- "gen_ai.completion" : tool_result_content_json ,
301330 "tool.status" : status_str ,
302331 }
303332 )
304333
334+ self ._add_event (
335+ span ,
336+ "gen_ai.choice" ,
337+ event_attributes = {
338+ "message" : serialize (tool_result .get ("content" )),
339+ "id" : tool_result .get ("toolUseId" , "" ),
340+ },
341+ )
342+
305343 self ._end_span (span , attributes , error )
306344
307345 def start_event_loop_cycle_span (
308346 self ,
309347 event_loop_kwargs : Any ,
348+ messages : Messages ,
310349 parent_span : Optional [Span ] = None ,
311- messages : Optional [Messages ] = None ,
312350 ** kwargs : Any ,
313351 ) -> Optional [Span ]:
314352 """Start a new span for an event loop cycle.
315353
316354 Args:
317355 event_loop_kwargs: Arguments for the event loop cycle.
318356 parent_span: Optional parent span to link this span to.
319- messages: Optional messages being processed in this cycle.
357+ messages: Messages being processed in this cycle.
320358 **kwargs: Additional attributes to add to the span.
321359
322360 Returns:
@@ -326,7 +364,6 @@ def start_event_loop_cycle_span(
326364 parent_span = parent_span if parent_span else event_loop_kwargs .get ("event_loop_parent_span" )
327365
328366 attributes : Dict [str , AttributeValue ] = {
329- "gen_ai.prompt" : serialize (messages ),
330367 "event_loop.cycle_id" : event_loop_cycle_id ,
331368 }
332369
@@ -337,7 +374,15 @@ def start_event_loop_cycle_span(
337374 attributes .update ({k : v for k , v in kwargs .items () if isinstance (v , (str , int , float , bool ))})
338375
339376 span_name = f"Cycle { event_loop_cycle_id } "
340- return self ._start_span (span_name , parent_span , attributes , span_kind = trace_api .SpanKind .INTERNAL )
377+ span = self ._start_span (span_name , parent_span , attributes )
378+ for message in messages or []:
379+ self ._add_event (
380+ span ,
381+ f"gen_ai.{ message ['role' ]} .message" ,
382+ {"content" : serialize (message ["content" ])},
383+ )
384+
385+ return span
341386
342387 def end_event_loop_cycle_span (
343388 self ,
@@ -354,14 +399,12 @@ def end_event_loop_cycle_span(
354399 tool_result_message: Optional tool result message if a tool was called.
355400 error: Optional exception if the cycle failed.
356401 """
357- attributes : Dict [str , AttributeValue ] = {
358- "gen_ai.completion" : serialize (message ["content" ]),
359- }
402+ event_attributes : Dict [str , AttributeValue ] = {"message" : serialize (message ["content" ])}
360403
361404 if tool_result_message :
362- attributes ["tool.result" ] = serialize (tool_result_message ["content" ])
363-
364- self ._end_span (span , attributes , error )
405+ event_attributes ["tool.result" ] = serialize (tool_result_message ["content" ])
406+ self . _add_event ( span , "gen_ai.choice" , event_attributes = event_attributes )
407+ self ._end_span (span , {} , error )
365408
366409 def start_agent_span (
367410 self ,
@@ -387,17 +430,15 @@ def start_agent_span(
387430 """
388431 attributes : Dict [str , AttributeValue ] = {
389432 "gen_ai.system" : "strands-agents" ,
390- "agent.name" : agent_name ,
391433 "gen_ai.agent.name" : agent_name ,
392- "gen_ai.prompt " : prompt ,
434+ "gen_ai.operation.name " : "invoke_agent" ,
393435 }
394436
395437 if model_id :
396438 attributes ["gen_ai.request.model" ] = model_id
397439
398440 if tools :
399441 tools_json = serialize (tools )
400- attributes ["agent.tools" ] = tools_json
401442 attributes ["gen_ai.agent.tools" ] = tools_json
402443
403444 # Add custom trace attributes if provided
@@ -407,7 +448,18 @@ def start_agent_span(
407448 # Add additional kwargs as attributes
408449 attributes .update ({k : v for k , v in kwargs .items () if isinstance (v , (str , int , float , bool ))})
409450
410- return self ._start_span (agent_name , attributes = attributes , span_kind = trace_api .SpanKind .CLIENT )
451+ span = self ._start_span (
452+ f"invoke_agent { agent_name } " , attributes = attributes , span_kind = trace_api .SpanKind .CLIENT
453+ )
454+ self ._add_event (
455+ span ,
456+ "gen_ai.user.message" ,
457+ event_attributes = {
458+ "content" : prompt ,
459+ },
460+ )
461+
462+ return span
411463
412464 def end_agent_span (
413465 self ,
@@ -426,10 +478,10 @@ def end_agent_span(
426478 attributes : Dict [str , AttributeValue ] = {}
427479
428480 if response :
429- attributes . update (
430- {
431- "gen_ai.completion" : str ( response ) ,
432- }
481+ self . _add_event (
482+ span ,
483+ "gen_ai.choice" ,
484+ event_attributes = { "message" : str ( response ), "finish_reason" : str ( response . stop_reason )},
433485 )
434486
435487 if hasattr (response , "metrics" ) and hasattr (response .metrics , "accumulated_usage" ):
0 commit comments