2727
2828from . import _metrics
2929from . import tracing
30- from ..events import event as event_lib
3130
3231if TYPE_CHECKING :
3332 from ..agents .base_agent import BaseAgent
3433 from ..agents .invocation_context import InvocationContext
34+ from ..events import event as event_lib
3535 from ..models .llm_request import LlmRequest
3636 from ..models .llm_response import LlmResponse
3737 from ..tools .base_tool import BaseTool
@@ -78,11 +78,31 @@ class TelemetryContext:
7878 error_type : str | None = None
7979 span : tracing .GenerateContentSpan | trace .Span | None = None
8080 _llm_responses : list [LlmResponse ] = dataclasses .field (default_factory = list )
81+ _inference_call_count : int = 0
82+ _tool_call_count : int = 0
8183
8284 @property
8385 def llm_responses (self ) -> list [LlmResponse ]:
8486 return self ._llm_responses
8587
88+ @property
89+ def inference_call_count (self ) -> int :
90+ """Number of model calls counted against this invoke_agent span."""
91+ return self ._inference_call_count
92+
93+ def increment_inference_calls (self ) -> None :
94+ """Counts one model call against this span (including calls that raised)."""
95+ self ._inference_call_count += 1
96+
97+ def increment_tool_calls (self ) -> None :
98+ """Counts one tool call against this invoke_agent span."""
99+ self ._tool_call_count += 1
100+
101+ @property
102+ def tool_call_count (self ) -> int :
103+ """Number of tool calls counted against this invoke_agent span."""
104+ return self ._tool_call_count
105+
86106 def record_llm_response (
87107 self , invocation_context : InvocationContext , response : LlmResponse
88108 ) -> None :
@@ -110,6 +130,30 @@ def _record_agent_metrics(
110130 logger .exception ("Failed to record agent metrics for agent %s" , agent_name )
111131
112132
133+ def _flush_invoke_agent_metrics (
134+ tel_ctx : TelemetryContext , agent_name : str
135+ ) -> None :
136+ """Flushes this span's accumulated inference/tool-call metrics."""
137+ _metrics .record_invoke_agent_inference_calls (
138+ agent_name , tel_ctx .inference_call_count
139+ )
140+ _metrics .record_invoke_agent_tool_calls (agent_name , tel_ctx .tool_call_count )
141+
142+
143+ def _accumulate_invoke_agent_tool_call (ctx : InvocationContext ) -> None :
144+ """Counts one tool call against the active invoke_agent span."""
145+ span_tel_ctx = ctx ._invoke_agent_telemetry_context # pylint: disable=protected-access
146+ if span_tel_ctx is not None :
147+ span_tel_ctx .increment_tool_calls ()
148+
149+
150+ def _accumulate_invoke_agent_inference_call (ctx : InvocationContext ) -> None :
151+ """Counts one model call against the active invoke_agent span."""
152+ span_tel_ctx = ctx ._invoke_agent_telemetry_context # pylint: disable=protected-access
153+ if span_tel_ctx is not None :
154+ span_tel_ctx .increment_inference_calls ()
155+
156+
113157@contextlib .asynccontextmanager
114158async def record_agent_invocation (
115159 ctx : InvocationContext , agent : BaseAgent
@@ -119,11 +163,13 @@ async def record_agent_invocation(
119163 caught_error : Exception | None = None
120164 span : trace .Span | None = None
121165 span_name = f"invoke_agent { agent .name } "
166+ tel_ctx = TelemetryContext ()
122167 try :
123168 with tracing .tracer .start_as_current_span (span_name ) as s :
124169 span = s
125170 tracing .trace_agent_invocation (span , agent , ctx )
126- tel_ctx = TelemetryContext (otel_context = context_api .get_current ())
171+ tel_ctx .otel_context = context_api .get_current ()
172+ ctx ._invoke_agent_telemetry_context = tel_ctx # pylint: disable=protected-access
127173 yield tel_ctx
128174 except Exception as e :
129175 caught_error = e
@@ -136,14 +182,15 @@ async def record_agent_invocation(
136182 getattr (getattr (ctx , "session" , None ), "events" , []),
137183 caught_error ,
138184 )
185+ _flush_invoke_agent_metrics (tel_ctx , agent .name )
139186
140187
141188@contextlib .asynccontextmanager
142189async def record_tool_execution (
143190 tool : BaseTool ,
144191 agent : BaseAgent ,
145192 function_args : dict [str , object ],
146- invocation_context : InvocationContext | None = None ,
193+ invocation_context : InvocationContext ,
147194) -> AsyncIterator [TelemetryContext ]:
148195 """Unified context manager for consolidated tool execution telemetry."""
149196 start_time = time .monotonic ()
@@ -171,6 +218,7 @@ async def record_tool_execution(
171218 invocation_context = invocation_context ,
172219 error_type = tel_ctx .error_type ,
173220 )
221+ _accumulate_invoke_agent_tool_call (invocation_context )
174222 finally :
175223 try :
176224 _metrics .record_tool_execution_duration (
@@ -205,6 +253,7 @@ async def record_inference_telemetry(
205253 yield tel_ctx
206254 finally :
207255 inference_error = sys .exc_info ()[1 ]
256+ _accumulate_invoke_agent_inference_call (invocation_context )
208257 agent = invocation_context .agent
209258 elapsed_s = _get_elapsed_s (tel_ctx .span , start_time )
210259 try :
0 commit comments