Skip to content

Commit 11dfc97

Browse files
committed
feat(telemetry): add gen_ai.agent.version metric
1 parent dff4c44 commit 11dfc97

File tree

4 files changed

+46
-0
lines changed

4 files changed

+46
-0
lines changed

src/google/adk/agents/base_agent.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ class MyAgent(BaseAgent):
115115
Agent name cannot be "user", since it's reserved for end-user's input.
116116
"""
117117

118+
version: str = ''
119+
"""The agent's version.
120+
121+
Version of the agent being invoked. Used to identify the Agent involved in telemetry.
122+
"""
123+
118124
description: str = ''
119125
"""Description about the agent's capability.
120126
@@ -678,6 +684,7 @@ def __create_kwargs(
678684

679685
kwargs: Dict[str, Any] = {
680686
'name': config.name,
687+
'version': config.version,
681688
'description': config.description,
682689
}
683690
if config.sub_agents:

src/google/adk/agents/base_agent_config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class BaseAgentConfig(BaseModel):
5555

5656
name: str = Field(description='Required. The name of the agent.')
5757

58+
version: str = Field(
59+
default='', description='Optional. The version of the agent.'
60+
)
61+
5862
description: str = Field(
5963
default='', description='Optional. The description of the agent.'
6064
)

src/google/adk/telemetry/tracing.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282

8383
USER_CONTENT_ELIDED = '<elided>'
8484

85+
# TODO: move to semconv and remove this.
86+
GEN_AI_AGENT_VERSION = 'gen_ai.agent.version'
87+
8588
# Needed to avoid circular imports
8689
if TYPE_CHECKING:
8790
from ..agents.base_agent import BaseAgent
@@ -155,6 +158,7 @@ def trace_agent_invocation(
155158
span.set_attribute(GEN_AI_AGENT_DESCRIPTION, agent.description)
156159

157160
span.set_attribute(GEN_AI_AGENT_NAME, agent.name)
161+
span.set_attribute(GEN_AI_AGENT_VERSION, agent.version)
158162
span.set_attribute(GEN_AI_CONVERSATION_ID, ctx.session.id)
159163

160164

@@ -455,6 +459,7 @@ def use_generate_content_span(
455459
USER_ID: invocation_context.session.user_id,
456460
'gcp.vertex.agent.event_id': model_response_event.id,
457461
'gcp.vertex.agent.invocation_id': invocation_context.invocation_id,
462+
GEN_AI_AGENT_VERSION: invocation_context.agent.version,
458463
}
459464
if (
460465
_is_gemini_agent(invocation_context.agent)

tests/unittests/telemetry/test_spans.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from google.adk.models.llm_response import LlmResponse
2525
from google.adk.sessions.in_memory_session_service import InMemorySessionService
2626
from google.adk.telemetry.tracing import ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS
27+
from google.adk.telemetry.tracing import GEN_AI_AGENT_VERSION
2728
from google.adk.telemetry.tracing import trace_agent_invocation
2829
from google.adk.telemetry.tracing import trace_call_llm
2930
from google.adk.telemetry.tracing import trace_inference_result
@@ -119,6 +120,34 @@ async def test_trace_agent_invocation(mock_span_fixture):
119120
mock.call('gen_ai.operation.name', 'invoke_agent'),
120121
mock.call('gen_ai.agent.description', agent.description),
121122
mock.call('gen_ai.agent.name', agent.name),
123+
mock.call(GEN_AI_AGENT_VERSION, ''),
124+
mock.call(
125+
'gen_ai.conversation.id',
126+
invocation_context.session.id,
127+
),
128+
mock.call(USER_ID, invocation_context.session.user_id),
129+
]
130+
]
131+
mock_span_fixture.set_attribute.assert_has_calls(
132+
expected_calls, any_order=True
133+
)
134+
assert mock_span_fixture.set_attribute.call_count == len(expected_calls)
135+
136+
@pytest.mark.asyncio
137+
async def test_trace_agent_invocation_with_version(mock_span_fixture):
138+
"""Test trace_agent_invocation sets span attributes correctly when version is provided."""
139+
agent = LlmAgent(name='test_llm_agent', model='gemini-pro')
140+
agent.description = 'Test agent description'
141+
agent.version = '1.0.0'
142+
invocation_context = await _create_invocation_context(agent)
143+
144+
trace_agent_invocation(mock_span_fixture, agent, invocation_context)
145+
146+
expected_calls = [
147+
mock.call('gen_ai.operation.name', 'invoke_agent'),
148+
mock.call('gen_ai.agent.description', agent.description),
149+
mock.call('gen_ai.agent.name', agent.name),
150+
mock.call(GEN_AI_AGENT_VERSION, agent.version),
122151
mock.call(
123152
'gen_ai.conversation.id',
124153
invocation_context.session.id,
@@ -767,6 +796,7 @@ async def test_generate_content_span(
767796

768797
mock_span.set_attributes.assert_called_once_with({
769798
GEN_AI_AGENT_NAME: invocation_context.agent.name,
799+
GEN_AI_AGENT_VERSION: '',
770800
GEN_AI_CONVERSATION_ID: invocation_context.session.id,
771801
USER_ID: invocation_context.session.user_id,
772802
'gcp.vertex.agent.event_id': 'event-123',

0 commit comments

Comments
 (0)