88from types import FrameType
99from typing import Any , Callable , Generic , cast , final , overload
1010
11- from opentelemetry . trace import NoOpTracer , use_span
11+ import logfire_api
1212from typing_extensions import TypeGuard , TypeVar , deprecated
1313
1414from pydantic_graph import End , Graph , GraphRun , GraphRunContext
5858 'UserPromptNode' ,
5959)
6060
61+ _logfire = logfire_api .Logfire (otel_scope = 'pydantic-ai' )
62+
63+ # while waiting for https://github.com/pydantic/logfire/issues/745
64+ try :
65+ import logfire ._internal .stack_info
66+ except ImportError :
67+ pass
68+ else :
69+ from pathlib import Path
70+
71+ logfire ._internal .stack_info .NON_USER_CODE_PREFIXES += (str (Path (__file__ ).parent .absolute ()),)
6172
6273T = TypeVar ('T' )
6374S = TypeVar ('S' )
@@ -112,9 +123,6 @@ class Agent(Generic[AgentDepsT, ResultDataT]):
112123 The type of the result data, used to validate the result data, defaults to `str`.
113124 """
114125
115- instrument : bool
116- """Automatically instrument with OpenTelemetry. Will use Logfire if it's configured."""
117-
118126 _deps_type : type [AgentDepsT ] = dataclasses .field (repr = False )
119127 _reflect_on_tool_call : bool = dataclasses .field (repr = False )
120128 _result_tool_name : str = dataclasses .field (repr = False )
@@ -149,7 +157,6 @@ def __init__(
149157 defer_model_check : bool = False ,
150158 end_strategy : EndStrategy = 'early' ,
151159 reflect_on_tool_call : bool = True ,
152- instrument : bool = False ,
153160 ):
154161 """Create an agent.
155162
@@ -182,7 +189,6 @@ def __init__(
182189 reflect_on_tool_call: Whether to generate a final response with an LLM call after tool calls.
183190 When set to `False`, the agent will return tool call results directly without generating
184191 a final reflection response. Defaults to `True`.
185- instrument: Automatically instrument with OpenTelemetry. Will use Logfire if it's configured.
186192 """
187193 if model is None or defer_model_check :
188194 self .model = model
@@ -193,7 +199,6 @@ def __init__(
193199 self .name = name
194200 self .model_settings = model_settings
195201 self .result_type = result_type
196- self .instrument = instrument
197202
198203 self ._deps_type = deps_type
199204
@@ -397,7 +402,6 @@ async def main():
397402 if infer_name and self .name is None :
398403 self ._infer_name (inspect .currentframe ())
399404 model_used = self ._get_model (model )
400- del model
401405
402406 deps = self ._get_deps (deps )
403407 new_message_index = len (message_history ) if message_history else 0
@@ -427,18 +431,13 @@ async def main():
427431 model_settings = merge_model_settings (self .model_settings , model_settings )
428432 usage_limits = usage_limits or _usage .UsageLimits ()
429433
430- if isinstance (model_used , InstrumentedModel ):
431- tracer = model_used .tracer
432- else :
433- tracer = NoOpTracer ()
434- agent_name = self .name or 'agent'
435- run_span = tracer .start_span (
436- 'agent run' ,
437- attributes = {
438- 'model_name' : model_used .model_name if model_used else 'no-model' ,
439- 'agent_name' : agent_name ,
440- 'logfire.msg' : f'{ agent_name } run' ,
441- },
434+ # Build the deps object for the graph
435+ run_span = _logfire .span (
436+ '{agent_name} run {prompt=}' ,
437+ prompt = user_prompt ,
438+ agent = self ,
439+ model_name = model_used .model_name if model_used else 'no-model' ,
440+ agent_name = self .name or 'agent' ,
442441 )
443442 graph_deps = self ._build_graph_deps (
444443 deps ,
@@ -463,7 +462,7 @@ async def main():
463462 state = state ,
464463 deps = graph_deps ,
465464 infer_name = False ,
466- span = use_span ( run_span , end_on_exit = True ) ,
465+ span = run_span ,
467466 ) as graph_run :
468467 yield AgentRun (graph_run )
469468
@@ -1119,7 +1118,7 @@ def _get_model(self, model: models.Model | models.KnownModelName | None) -> mode
11191118 else :
11201119 raise exceptions .UserError ('`model` must be set either when creating the agent or when calling it.' )
11211120
1122- if self . instrument and not isinstance (model_ , InstrumentedModel ):
1121+ if not isinstance (model_ , InstrumentedModel ):
11231122 model_ = InstrumentedModel (model_ )
11241123
11251124 return model_
0 commit comments