1212from typing_extensions import assert_never
1313
1414from . import messages as _messages
15+ from ._instrumentation import InstrumentationNames
1516from ._run_context import AgentDepsT , RunContext
1617from .exceptions import ModelRetry , ToolRetryError , UnexpectedModelBehavior
1718from .messages import ToolCallPart
@@ -115,6 +116,7 @@ async def handle_call(
115116 wrap_validation_errors ,
116117 self .ctx .tracer ,
117118 self .ctx .trace_include_content ,
119+ self .ctx .instrumentation_version ,
118120 usage_limits ,
119121 )
120122
@@ -203,15 +205,18 @@ async def _call_tool_traced(
203205 allow_partial : bool ,
204206 wrap_validation_errors : bool ,
205207 tracer : Tracer ,
206- include_content : bool = False ,
208+ include_content : bool ,
209+ instrumentation_version : int ,
207210 usage_limits : UsageLimits | None = None ,
208211 ) -> Any :
209212 """See <https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#execute-tool-span>."""
213+ instrumentation_names = InstrumentationNames .for_version (instrumentation_version )
214+
210215 span_attributes = {
211216 'gen_ai.tool.name' : call .tool_name ,
212217 # NOTE: this means `gen_ai.tool.call.id` will be included even if it was generated by pydantic-ai
213218 'gen_ai.tool.call.id' : call .tool_call_id ,
214- ** ({'tool_arguments' : call .args_as_json_str ()} if include_content else {}),
219+ ** ({instrumentation_names . tool_arguments_attr : call .args_as_json_str ()} if include_content else {}),
215220 'logfire.msg' : f'running tool: { call .tool_name } ' ,
216221 # add the JSON schema so these attributes are formatted nicely in Logfire
217222 'logfire.json_schema' : json .dumps (
@@ -220,8 +225,8 @@ async def _call_tool_traced(
220225 'properties' : {
221226 ** (
222227 {
223- 'tool_arguments' : {'type' : 'object' },
224- 'tool_response' : {'type' : 'object' },
228+ instrumentation_names . tool_arguments_attr : {'type' : 'object' },
229+ instrumentation_names . tool_result_attr : {'type' : 'object' },
225230 }
226231 if include_content
227232 else {}
@@ -232,18 +237,21 @@ async def _call_tool_traced(
232237 }
233238 ),
234239 }
235- with tracer .start_as_current_span ('running tool' , attributes = span_attributes ) as span :
240+ with tracer .start_as_current_span (
241+ instrumentation_names .get_tool_span_name (call .tool_name ),
242+ attributes = span_attributes ,
243+ ) as span :
236244 try :
237245 tool_result = await self ._call_tool (call , allow_partial , wrap_validation_errors , usage_limits )
238246 except ToolRetryError as e :
239247 part = e .tool_retry
240248 if include_content and span .is_recording ():
241- span .set_attribute ('tool_response' , part .model_response ())
249+ span .set_attribute (instrumentation_names . tool_result_attr , part .model_response ())
242250 raise e
243251
244252 if include_content and span .is_recording ():
245253 span .set_attribute (
246- 'tool_response' ,
254+ instrumentation_names . tool_result_attr ,
247255 tool_result
248256 if isinstance (tool_result , str )
249257 else _messages .tool_return_ta .dump_json (tool_result ).decode (),
0 commit comments