Skip to content

Commit 7c4a92f

Browse files
add missing methods and attributes
1 parent 41c5263 commit 7c4a92f

13 files changed

Lines changed: 543 additions & 53 deletions

File tree

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,42 @@
1-
# Copyright (c) Microsoft. All rights reserved.
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
23

3-
# Agent details class.
44
from dataclasses import dataclass
5+
from typing import Optional
6+
7+
from .models.agent_type import AgentType
58

69

710
@dataclass
811
class AgentDetails:
9-
"""Details about an AI agent."""
12+
"""Details about an AI agent in the system."""
1013

1114
agent_id: str
12-
conversation_id: str | None = None
13-
agent_name: str | None = None
14-
agent_description: str | None = None
15-
icon_uri: str | None = None
15+
"""The unique identifier for the AI agent."""
16+
17+
agent_name: Optional[str] = None
18+
"""The human-readable name of the AI agent."""
19+
20+
agent_description: Optional[str] = None
21+
"""A description of the AI agent's purpose or capabilities."""
22+
23+
agent_auid: Optional[str] = None
24+
"""Optional Agent User ID for the agent."""
25+
26+
agent_upn: Optional[str] = None
27+
"""Optional User Principal Name (UPN) for the agent."""
28+
29+
agent_blueprint_id: Optional[str] = None
30+
"""Optional Blueprint/Application ID for the agent."""
31+
32+
agent_type: Optional[AgentType] = None
33+
"""The agent type."""
34+
35+
tenant_id: Optional[str] = None
36+
"""Optional Tenant ID for the agent."""
37+
38+
conversation_id: Optional[str] = None
39+
"""Optional conversation ID for compatibility."""
40+
41+
icon_uri: Optional[str] = None
42+
"""Optional icon URI for the agent."""

libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
GEN_AI_RESPONSE_MODEL_KEY = "gen_ai.response.model"
3636
GEN_AI_SYSTEM_KEY = "gen_ai.system"
3737
GEN_AI_SYSTEM_VALUE = "az.ai.agent365"
38+
GEN_AI_THOUGHT_PROCESS_KEY = "gen_ai.agent.thought.process"
3839

3940
GEN_AI_AGENT_ID_KEY = "gen_ai.agent.id"
4041
GEN_AI_AGENT_NAME_KEY = "gen_ai.agent.name"
@@ -46,6 +47,7 @@
4647
GEN_AI_USAGE_OUTPUT_TOKENS_KEY = "gen_ai.usage.output_tokens"
4748
GEN_AI_CHOICE = "gen_ai.choice"
4849
GEN_AI_PROVIDER_NAME_KEY = "gen_ai.provider.name"
50+
GEN_AI_AGENT_TYPE_KEY = "gen_ai.agent.type"
4951

5052
GEN_AI_SYSTEM_INSTRUCTIONS_KEY = "gen_ai.system_instructions"
5153
GEN_AI_INPUT_MESSAGES_KEY = "gen_ai.input.messages"
@@ -75,6 +77,7 @@
7577
GEN_AI_CALLER_AGENT_NAME_KEY = "gen_ai.caller.agent.name"
7678
GEN_AI_CALLER_AGENT_ID_KEY = "gen_ai.caller.agent.id"
7779
GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = "gen_ai.caller.agent.applicationid"
80+
GEN_AI_CALLER_AGENT_TYPE_KEY = "gen_ai.caller.agent.type"
7881

7982
# Agent-specific dimensions
8083
AGENT_ID_KEY = "gen_ai.agent.id"

libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/execute_tool_scope.py

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# Copyright (c) Microsoft. All rights reserved.
2-
3-
# Execute tool scope for tracing tool execution.
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
43

54
from .agent_details import AgentDetails
65
from .constants import (
76
EXECUTE_TOOL_OPERATION_NAME,
7+
GEN_AI_EVENT_CONTENT,
8+
GEN_AI_TOOL_ARGS_KEY,
89
GEN_AI_TOOL_CALL_ID_KEY,
910
GEN_AI_TOOL_DESCRIPTION_KEY,
1011
GEN_AI_TOOL_NAME_KEY,
@@ -26,7 +27,7 @@ def start(
2627
agent_details: AgentDetails,
2728
tenant_details: TenantDetails,
2829
) -> "ExecuteToolScope":
29-
"""Create and start a new scope for tool execution tracing.
30+
"""Creates and starts a new scope for tool execution tracing.
3031
3132
Args:
3233
details: The details of the tool call
@@ -54,18 +55,34 @@ def __init__(
5455
super().__init__(
5556
kind="Internal",
5657
operation_name=EXECUTE_TOOL_OPERATION_NAME,
57-
activity_name=f"execute_tool {details.tool_name}",
58+
activity_name=f"{EXECUTE_TOOL_OPERATION_NAME} {details.tool_name}",
5859
agent_details=agent_details,
5960
tenant_details=tenant_details,
6061
)
6162

62-
self.set_tag_maybe(GEN_AI_TOOL_NAME_KEY, details.tool_name)
63-
self.set_tag_maybe("gen_ai.tool.arguments", details.arguments)
64-
self.set_tag_maybe(GEN_AI_TOOL_TYPE_KEY, details.tool_type)
65-
self.set_tag_maybe(GEN_AI_TOOL_CALL_ID_KEY, details.tool_call_id)
66-
self.set_tag_maybe(GEN_AI_TOOL_DESCRIPTION_KEY, details.description)
63+
# Extract details using deconstruction-like approach
64+
tool_name = details.tool_name
65+
arguments = details.arguments
66+
tool_call_id = details.tool_call_id
67+
description = details.description
68+
tool_type = details.tool_type
69+
endpoint = details.endpoint
70+
71+
self.set_tag_maybe(GEN_AI_TOOL_NAME_KEY, tool_name)
72+
self.set_tag_maybe(GEN_AI_TOOL_ARGS_KEY, arguments)
73+
self.set_tag_maybe(GEN_AI_TOOL_TYPE_KEY, tool_type)
74+
self.set_tag_maybe(GEN_AI_TOOL_CALL_ID_KEY, tool_call_id)
75+
self.set_tag_maybe(GEN_AI_TOOL_DESCRIPTION_KEY, description)
76+
77+
if endpoint:
78+
self.set_tag_maybe(SERVER_ADDRESS_KEY, endpoint.hostname)
79+
if endpoint.port and endpoint.port != 443:
80+
self.set_tag_maybe(SERVER_PORT_KEY, endpoint.port)
6781

68-
if details.endpoint:
69-
self.set_tag_maybe(SERVER_ADDRESS_KEY, details.endpoint.hostname)
70-
if details.endpoint.port and details.endpoint.port != 443:
71-
self.set_tag_maybe(SERVER_PORT_KEY, details.endpoint.port)
82+
def record_response(self, response: str) -> None:
83+
"""Records response information for telemetry tracking.
84+
85+
Args:
86+
response: The response to record
87+
"""
88+
self.set_tag_maybe(GEN_AI_EVENT_CONTENT, response)
Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
# Copyright (c) Microsoft. All rights reserved.
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
from typing import List
25

36
from .agent_details import AgentDetails
47
from .constants import (
58
GEN_AI_INPUT_MESSAGES_KEY,
9+
GEN_AI_OPERATION_NAME_KEY,
10+
GEN_AI_OUTPUT_MESSAGES_KEY,
611
GEN_AI_PROVIDER_NAME_KEY,
712
GEN_AI_REQUEST_MODEL_KEY,
813
GEN_AI_RESPONSE_FINISH_REASONS_KEY,
914
GEN_AI_RESPONSE_ID_KEY,
15+
GEN_AI_THOUGHT_PROCESS_KEY,
1016
GEN_AI_USAGE_INPUT_TOKENS_KEY,
1117
GEN_AI_USAGE_OUTPUT_TOKENS_KEY,
1218
)
@@ -17,7 +23,7 @@
1723

1824

1925
class InferenceScope(OpenTelemetryScope):
20-
"""Provides OpenTelemetry tracing scope for inference call."""
26+
"""Provides OpenTelemetry tracing scope for generative AI inference operations."""
2127

2228
@staticmethod
2329
def start(
@@ -26,7 +32,7 @@ def start(
2632
tenant_details: TenantDetails,
2733
request: Request | None = None,
2834
) -> "InferenceScope":
29-
"""Create and start a new scope for inference call.
35+
"""Creates and starts a new scope for inference tracing.
3036
3137
Args:
3238
details: The details of the inference call
@@ -41,40 +47,102 @@ def start(
4147

4248
def __init__(
4349
self,
44-
inference_call_details: InferenceCallDetails,
50+
details: InferenceCallDetails,
4551
agent_details: AgentDetails,
4652
tenant_details: TenantDetails,
4753
request: Request | None = None,
4854
):
49-
"""Initialize the agent invocation scope.
55+
"""Initialize the inference scope.
5056
5157
Args:
52-
inference_call_details: The details of the inference call
58+
details: The details of the inference call
5359
agent_details: The details of the agent making the call
5460
tenant_details: The details of the tenant
5561
request: Optional request details for additional context
5662
"""
5763

5864
super().__init__(
5965
kind="Client",
60-
operation_name=inference_call_details.operationName.value,
61-
activity_name=f"{inference_call_details.operationName.value} {inference_call_details.model}",
66+
operation_name=details.operationName.value,
67+
activity_name=f"{details.operationName.value} {details.model}",
6268
agent_details=agent_details,
6369
tenant_details=tenant_details,
6470
)
6571

66-
# Set request content if provided
6772
if request:
6873
self.set_tag_maybe(GEN_AI_INPUT_MESSAGES_KEY, request.content)
6974

70-
self.set_tag_maybe(GEN_AI_REQUEST_MODEL_KEY, inference_call_details.model)
71-
self.set_tag_maybe(GEN_AI_PROVIDER_NAME_KEY, inference_call_details.providerName)
72-
self.set_tag_maybe(GEN_AI_USAGE_INPUT_TOKENS_KEY, inference_call_details.inputTokens)
73-
self.set_tag_maybe(GEN_AI_USAGE_OUTPUT_TOKENS_KEY, inference_call_details.outputTokens)
75+
self.set_tag_maybe(GEN_AI_OPERATION_NAME_KEY, details.operationName.value)
76+
self.set_tag_maybe(GEN_AI_REQUEST_MODEL_KEY, details.model)
77+
self.set_tag_maybe(GEN_AI_PROVIDER_NAME_KEY, details.providerName)
78+
self.set_tag_maybe(
79+
GEN_AI_USAGE_INPUT_TOKENS_KEY,
80+
str(details.inputTokens) if details.inputTokens is not None else None,
81+
)
82+
self.set_tag_maybe(
83+
GEN_AI_USAGE_OUTPUT_TOKENS_KEY,
84+
str(details.outputTokens) if details.outputTokens is not None else None,
85+
)
7486
self.set_tag_maybe(
7587
GEN_AI_RESPONSE_FINISH_REASONS_KEY,
76-
",".join(inference_call_details.finishReasons)
77-
if inference_call_details.finishReasons
78-
else None,
88+
",".join(details.finishReasons) if details.finishReasons else None,
7989
)
80-
self.set_tag_maybe(GEN_AI_RESPONSE_ID_KEY, inference_call_details.responseId)
90+
self.set_tag_maybe(GEN_AI_RESPONSE_ID_KEY, details.responseId)
91+
92+
def record_input_messages(self, messages: List[str]) -> None:
93+
"""Records the input messages for telemetry tracking.
94+
95+
Args:
96+
messages: List of input messages
97+
"""
98+
self.set_tag_maybe(GEN_AI_INPUT_MESSAGES_KEY, ",".join(messages))
99+
100+
def record_output_messages(self, messages: List[str]) -> None:
101+
"""Records the output messages for telemetry tracking.
102+
103+
Args:
104+
messages: List of output messages
105+
"""
106+
self.set_tag_maybe(GEN_AI_OUTPUT_MESSAGES_KEY, ",".join(messages))
107+
108+
def record_input_tokens(self, input_tokens: int) -> None:
109+
"""Records the number of input tokens for telemetry tracking.
110+
111+
Args:
112+
input_tokens: Number of input tokens
113+
"""
114+
self.set_tag_maybe(GEN_AI_USAGE_INPUT_TOKENS_KEY, str(input_tokens))
115+
116+
def record_output_tokens(self, output_tokens: int) -> None:
117+
"""Records the number of output tokens for telemetry tracking.
118+
119+
Args:
120+
output_tokens: Number of output tokens
121+
"""
122+
self.set_tag_maybe(GEN_AI_USAGE_OUTPUT_TOKENS_KEY, str(output_tokens))
123+
124+
def record_response_id(self, response_id: str) -> None:
125+
"""Records the response id for telemetry tracking.
126+
127+
Args:
128+
response_id: Response ID to record
129+
"""
130+
if response_id:
131+
self.set_tag_maybe(GEN_AI_RESPONSE_ID_KEY, response_id)
132+
133+
def record_finish_reasons(self, finish_reasons: List[str]) -> None:
134+
"""Records the finish reasons for telemetry tracking.
135+
136+
Args:
137+
finish_reasons: List of finish reasons
138+
"""
139+
if finish_reasons:
140+
self.set_tag_maybe(GEN_AI_RESPONSE_FINISH_REASONS_KEY, ",".join(finish_reasons))
141+
142+
def record_thought_process(self, thought_process: str) -> None:
143+
"""Records the thought process.
144+
145+
Args:
146+
thought_process: The thought process to record
147+
"""
148+
self.set_tag_maybe(GEN_AI_THOUGHT_PROCESS_KEY, thought_process)

0 commit comments

Comments
 (0)