diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/__init__.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/__init__.py index 036f60e1..95cc4737 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/__init__.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/__init__.py @@ -28,7 +28,7 @@ from .middleware.baggage_builder import BaggageBuilder from .opentelemetry_scope import OpenTelemetryScope from .request import Request -from .source_metadata import SourceMetadata +from .channel import Channel from .tenant_details import TenantDetails from .tool_call_details import ToolCallDetails from .tool_type import ToolType @@ -64,7 +64,7 @@ "AgentDetails", "TenantDetails", "ToolCallDetails", - "SourceMetadata", + "Channel", "Request", "InferenceCallDetails", "ServiceEndpoint", diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/channel.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/channel.py new file mode 100644 index 00000000..2278292b --- /dev/null +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/channel.py @@ -0,0 +1,14 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# Channel class. + +from dataclasses import dataclass + + +@dataclass +class Channel: + """Channel information for agent execution context.""" + + name: str | None = None + link: str | None = None diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/constants.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/constants.py index 8eadc2dc..f4730427 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/constants.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/constants.py @@ -60,15 +60,15 @@ GEN_AI_TOOL_CALL_RESULT_KEY = "gen_ai.tool.call.result" GEN_AI_TOOL_TYPE_KEY = "gen_ai.tool.type" -# Agent user (user tied to agent instance during creation) or caller dimensions -GEN_AI_CALLER_ID_KEY = "microsoft.caller.id" -GEN_AI_CALLER_NAME_KEY = "microsoft.caller.name" -GEN_AI_CALLER_UPN_KEY = "microsoft.caller.upn" +# Human caller dimensions (OTel user.* namespace) +USER_ID_KEY = "user.id" +USER_NAME_KEY = "user.name" +USER_EMAIL_KEY = "user.email" GEN_AI_CALLER_CLIENT_IP_KEY = "client.address" # Agent to Agent caller agent dimensions GEN_AI_CALLER_AGENT_USER_ID_KEY = "microsoft.a365.caller.agent.user.id" -GEN_AI_CALLER_AGENT_UPN_KEY = "microsoft.a365.caller.agent.user.upn" +GEN_AI_CALLER_AGENT_EMAIL_KEY = "microsoft.a365.caller.agent.user.email" GEN_AI_CALLER_AGENT_NAME_KEY = "microsoft.a365.caller.agent.name" GEN_AI_CALLER_AGENT_ID_KEY = "microsoft.a365.caller.agent.id" GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = "microsoft.a365.caller.agent.blueprint.id" @@ -84,7 +84,7 @@ # Baggage keys GEN_AI_AGENT_AUID_KEY = "microsoft.agent.user.id" -GEN_AI_AGENT_UPN_KEY = "microsoft.agent.user.upn" +GEN_AI_AGENT_EMAIL_KEY = "microsoft.agent.user.email" GEN_AI_AGENT_BLUEPRINT_ID_KEY = "microsoft.a365.agent.blueprint.id" # Execution context dimensions diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/execute_tool_scope.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/execute_tool_scope.py index 073fe9c8..e21f412c 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/execute_tool_scope.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/execute_tool_scope.py @@ -131,9 +131,9 @@ def __init__( self.set_tag_maybe(SERVER_PORT_KEY, endpoint.port) # Set request metadata if provided - if request and request.source_metadata: - self.set_tag_maybe(CHANNEL_NAME_KEY, request.source_metadata.name) - self.set_tag_maybe(CHANNEL_LINK_KEY, request.source_metadata.description) + if request and request.channel: + self.set_tag_maybe(CHANNEL_NAME_KEY, request.channel.name) + self.set_tag_maybe(CHANNEL_LINK_KEY, request.channel.link) def record_response(self, response: str) -> None: """Records response information for telemetry tracking. diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/inference_scope.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/inference_scope.py index 7015253b..10774a0a 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/inference_scope.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/inference_scope.py @@ -124,9 +124,9 @@ def __init__( self.set_tag_maybe(SERVER_PORT_KEY, str(details.endpoint.port)) # Set request metadata if provided - if request and request.source_metadata: - self.set_tag_maybe(CHANNEL_NAME_KEY, request.source_metadata.name) - self.set_tag_maybe(CHANNEL_LINK_KEY, request.source_metadata.description) + if request and request.channel: + self.set_tag_maybe(CHANNEL_NAME_KEY, request.channel.name) + self.set_tag_maybe(CHANNEL_LINK_KEY, request.channel.link) def record_input_messages(self, messages: List[str]) -> None: """Records the input messages for telemetry tracking. diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/invoke_agent_scope.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/invoke_agent_scope.py index 0a005f03..2620c412 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/invoke_agent_scope.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/invoke_agent_scope.py @@ -14,15 +14,12 @@ CHANNEL_LINK_KEY, CHANNEL_NAME_KEY, GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, + GEN_AI_CALLER_AGENT_EMAIL_KEY, GEN_AI_CALLER_AGENT_ID_KEY, GEN_AI_CALLER_AGENT_NAME_KEY, GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, - GEN_AI_CALLER_AGENT_UPN_KEY, GEN_AI_CALLER_AGENT_USER_ID_KEY, GEN_AI_CALLER_CLIENT_IP_KEY, - GEN_AI_CALLER_ID_KEY, - GEN_AI_CALLER_NAME_KEY, - GEN_AI_CALLER_UPN_KEY, GEN_AI_EXECUTION_TYPE_KEY, GEN_AI_INPUT_MESSAGES_KEY, GEN_AI_OUTPUT_MESSAGES_KEY, @@ -30,6 +27,9 @@ SERVER_ADDRESS_KEY, SERVER_PORT_KEY, SESSION_ID_KEY, + USER_EMAIL_KEY, + USER_ID_KEY, + USER_NAME_KEY, ) from .invoke_agent_details import InvokeAgentDetails from .models.caller_details import CallerDetails @@ -149,9 +149,9 @@ def __init__( # Set request metadata if provided if request: - if request.source_metadata: - self.set_tag_maybe(CHANNEL_NAME_KEY, request.source_metadata.name) - self.set_tag_maybe(CHANNEL_LINK_KEY, request.source_metadata.description) + if request.channel: + self.set_tag_maybe(CHANNEL_NAME_KEY, request.channel.name) + self.set_tag_maybe(CHANNEL_LINK_KEY, request.channel.link) self.set_tag_maybe( GEN_AI_EXECUTION_TYPE_KEY, @@ -161,9 +161,9 @@ def __init__( # Set caller details tags if caller_details: - self.set_tag_maybe(GEN_AI_CALLER_ID_KEY, caller_details.caller_id) - self.set_tag_maybe(GEN_AI_CALLER_UPN_KEY, caller_details.caller_upn) - self.set_tag_maybe(GEN_AI_CALLER_NAME_KEY, caller_details.caller_name) + self.set_tag_maybe(USER_ID_KEY, caller_details.caller_id) + self.set_tag_maybe(USER_EMAIL_KEY, caller_details.caller_upn) + self.set_tag_maybe(USER_NAME_KEY, caller_details.caller_name) # Validate and set caller client IP self.set_tag_maybe( GEN_AI_CALLER_CLIENT_IP_KEY, @@ -178,7 +178,7 @@ def __init__( GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, caller_agent_details.agent_blueprint_id ) self.set_tag_maybe(GEN_AI_CALLER_AGENT_USER_ID_KEY, caller_agent_details.agent_auid) - self.set_tag_maybe(GEN_AI_CALLER_AGENT_UPN_KEY, caller_agent_details.agent_upn) + self.set_tag_maybe(GEN_AI_CALLER_AGENT_EMAIL_KEY, caller_agent_details.agent_upn) self.set_tag_maybe( GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, caller_agent_details.agent_platform_id ) diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/middleware/baggage_builder.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/middleware/baggage_builder.py index 8c5478db..f788e539 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/middleware/baggage_builder.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/middleware/baggage_builder.py @@ -14,21 +14,21 @@ GEN_AI_AGENT_AUID_KEY, GEN_AI_AGENT_BLUEPRINT_ID_KEY, GEN_AI_AGENT_DESCRIPTION_KEY, + GEN_AI_AGENT_EMAIL_KEY, GEN_AI_AGENT_ID_KEY, GEN_AI_AGENT_NAME_KEY, - GEN_AI_AGENT_UPN_KEY, GEN_AI_CALLER_CLIENT_IP_KEY, - GEN_AI_CALLER_ID_KEY, - GEN_AI_CALLER_NAME_KEY, - GEN_AI_CALLER_UPN_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_CONVERSATION_ITEM_LINK_KEY, SERVICE_NAME_KEY, SESSION_DESCRIPTION_KEY, SESSION_ID_KEY, TENANT_ID_KEY, + USER_EMAIL_KEY, + USER_ID_KEY, + USER_NAME_KEY, ) -from ..utils import deprecated, validate_and_normalize_ip +from ..utils import validate_and_normalize_ip logger = logging.getLogger(__name__) @@ -115,7 +115,7 @@ def agent_upn(self, value: str | None) -> "BaggageBuilder": Returns: Self for method chaining """ - self._set(GEN_AI_AGENT_UPN_KEY, value) + self._set(GEN_AI_AGENT_EMAIL_KEY, value) return self def agent_blueprint_id(self, value: str | None) -> "BaggageBuilder": @@ -139,7 +139,7 @@ def caller_id(self, value: str | None) -> "BaggageBuilder": Returns: Self for method chaining """ - self._set(GEN_AI_CALLER_ID_KEY, value) + self._set(USER_ID_KEY, value) return self def agent_name(self, value: str | None) -> "BaggageBuilder": @@ -154,12 +154,12 @@ def agent_description(self, value: str | None) -> "BaggageBuilder": def caller_name(self, value: str | None) -> "BaggageBuilder": """Set the caller name baggage value.""" - self._set(GEN_AI_CALLER_NAME_KEY, value) + self._set(USER_NAME_KEY, value) return self def caller_upn(self, value: str | None) -> "BaggageBuilder": """Set the caller UPN baggage value.""" - self._set(GEN_AI_CALLER_UPN_KEY, value) + self._set(USER_EMAIL_KEY, value) return self def caller_client_ip(self, value: str | None) -> "BaggageBuilder": @@ -177,16 +177,6 @@ def conversation_item_link(self, value: str | None) -> "BaggageBuilder": self._set(GEN_AI_CONVERSATION_ITEM_LINK_KEY, value) return self - @deprecated("Use channel_name() instead") - def source_metadata_name(self, value: str | None) -> "BaggageBuilder": - """Set the execution source metadata name (e.g., channel name).""" - return self.channel_name(value) - - @deprecated("Use channel_links() instead") - def source_metadata_description(self, value: str | None) -> "BaggageBuilder": - """Set the execution source metadata description (e.g., channel description).""" - return self.channel_links(value) - def session_id(self, value: str | None) -> "BaggageBuilder": """Set the session ID baggage value.""" self._set(SESSION_ID_KEY, value) @@ -203,7 +193,7 @@ def channel_name(self, value: str | None) -> "BaggageBuilder": return self def channel_links(self, value: str | None) -> "BaggageBuilder": - """Sets the channel link baggage value. (e.g., channel links or description).""" + """Sets the channel link baggage value.""" self._set(CHANNEL_LINK_KEY, value) return self diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/opentelemetry_scope.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/opentelemetry_scope.py index 2fc6b6f2..5839982d 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/opentelemetry_scope.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/opentelemetry_scope.py @@ -28,10 +28,10 @@ GEN_AI_AGENT_AUID_KEY, GEN_AI_AGENT_BLUEPRINT_ID_KEY, GEN_AI_AGENT_DESCRIPTION_KEY, + GEN_AI_AGENT_EMAIL_KEY, GEN_AI_AGENT_ID_KEY, GEN_AI_AGENT_NAME_KEY, GEN_AI_AGENT_PLATFORM_ID_KEY, - GEN_AI_AGENT_UPN_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_ICON_URI_KEY, GEN_AI_OPERATION_NAME_KEY, @@ -187,7 +187,7 @@ def __init__( GEN_AI_AGENT_DESCRIPTION_KEY, agent_details.agent_description ) self.set_tag_maybe(GEN_AI_AGENT_AUID_KEY, agent_details.agent_auid) - self.set_tag_maybe(GEN_AI_AGENT_UPN_KEY, agent_details.agent_upn) + self.set_tag_maybe(GEN_AI_AGENT_EMAIL_KEY, agent_details.agent_upn) self.set_tag_maybe( GEN_AI_AGENT_BLUEPRINT_ID_KEY, agent_details.agent_blueprint_id ) diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/request.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/request.py index 40f61a96..5201cf0f 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/request.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/request.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from .execution_type import ExecutionType -from .source_metadata import SourceMetadata +from .channel import Channel @dataclass @@ -16,4 +16,4 @@ class Request: content: str execution_type: ExecutionType session_id: str | None = None - source_metadata: SourceMetadata | None = None + channel: Channel | None = None diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/source_metadata.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/source_metadata.py deleted file mode 100644 index 74581b0a..00000000 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/source_metadata.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# Source metadata class. - -from dataclasses import dataclass - - -@dataclass -class SourceMetadata: - """Source metadata for agent execution context.""" - - id: str | None = None - name: str | None = None - icon_uri: str | None = None - description: str | None = None diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/trace_processor/util.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/trace_processor/util.py index e6eb2ff9..8e5a9472 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/trace_processor/util.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/trace_processor/util.py @@ -14,7 +14,7 @@ consts.GEN_AI_AGENT_ID_KEY, # gen_ai.agent.id consts.GEN_AI_AGENT_NAME_KEY, # gen_ai.agent.name consts.GEN_AI_AGENT_DESCRIPTION_KEY, # gen_ai.agent.description - consts.GEN_AI_AGENT_UPN_KEY, # microsoft.agent.user.upn + consts.GEN_AI_AGENT_EMAIL_KEY, # microsoft.agent.user.email consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, # microsoft.a365.agent.blueprint.id consts.GEN_AI_AGENT_AUID_KEY, # microsoft.agent.user.id consts.GEN_AI_AGENT_PLATFORM_ID_KEY, # microsoft.a365.agent.platform.id @@ -29,14 +29,14 @@ # Invoke Agent–specific attributes INVOKE_AGENT_ATTRIBUTES = [ # Caller / Invoker attributes - consts.GEN_AI_CALLER_ID_KEY, # microsoft.caller.id - consts.GEN_AI_CALLER_NAME_KEY, # microsoft.caller.name - consts.GEN_AI_CALLER_UPN_KEY, # microsoft.caller.upn + consts.USER_ID_KEY, # user.id + consts.USER_NAME_KEY, # user.name + consts.USER_EMAIL_KEY, # user.email # Caller Agent (A2A) attributes consts.GEN_AI_CALLER_AGENT_ID_KEY, # microsoft.a365.caller.agent.id consts.GEN_AI_CALLER_AGENT_NAME_KEY, # microsoft.a365.caller.agent.name consts.GEN_AI_CALLER_AGENT_USER_ID_KEY, # microsoft.a365.caller.agent.user.id - consts.GEN_AI_CALLER_AGENT_UPN_KEY, # microsoft.a365.caller.agent.user.upn + consts.GEN_AI_CALLER_AGENT_EMAIL_KEY, # microsoft.a365.caller.agent.user.email consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, # microsoft.a365.caller.agent.blueprint.id consts.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, # microsoft.a365.caller.agent.platform.id consts.GEN_AI_EXECUTION_TYPE_KEY, # gen_ai.execution.type diff --git a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/middleware/output_logging_middleware.py b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/middleware/output_logging_middleware.py index 4e58d0c1..1820e3e8 100644 --- a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/middleware/output_logging_middleware.py +++ b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/middleware/output_logging_middleware.py @@ -14,11 +14,11 @@ from microsoft_agents_a365.observability.core.constants import ( CHANNEL_LINK_KEY, CHANNEL_NAME_KEY, - GEN_AI_CALLER_ID_KEY, - GEN_AI_CALLER_NAME_KEY, - GEN_AI_CALLER_UPN_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_EXECUTION_TYPE_KEY, + USER_EMAIL_KEY, + USER_ID_KEY, + USER_NAME_KEY, ) from microsoft_agents_a365.observability.core.models.caller_details import CallerDetails from microsoft_agents_a365.observability.core.models.response import Response @@ -83,10 +83,10 @@ def _derive_conversation_id(context: TurnContext) -> str | None: return conv.id if conv else None -def _derive_source_metadata( +def _derive_channel( context: TurnContext, ) -> dict[str, str | None]: - """Derive source metadata (channel name and description) from TurnContext.""" + """Derive channel (name and link) from TurnContext.""" channel_id = getattr(context.activity, "channel_id", None) channel_name: str | None = None sub_channel: str | None = None @@ -96,7 +96,7 @@ def _derive_source_metadata( elif hasattr(channel_id, "channel"): channel_name = channel_id.channel sub_channel = channel_id.sub_channel - return {"name": channel_name, "description": sub_channel} + return {"name": channel_name, "link": sub_channel} def _derive_execution_type(context: TurnContext) -> str | None: @@ -131,7 +131,7 @@ async def on_turn( caller_details = _derive_caller_details(context) conversation_id = _derive_conversation_id(context) - source_metadata = _derive_source_metadata(context) + channel = _derive_channel(context) execution_type = _derive_execution_type(context) context.on_send_activities( @@ -141,7 +141,7 @@ async def on_turn( tenant_details, caller_details, conversation_id, - source_metadata, + channel, execution_type, ) ) @@ -155,7 +155,7 @@ def _create_send_handler( tenant_details: TenantDetails, caller_details: CallerDetails | None, conversation_id: str | None, - source_metadata: dict[str, str | None], + channel: dict[str, str | None], execution_type: str | None, ) -> Callable: """Create a send handler that wraps outgoing messages in OutputScope spans. @@ -197,13 +197,13 @@ async def handler( # Set additional attributes on the scope output_scope.set_tag_maybe(GEN_AI_CONVERSATION_ID_KEY, conversation_id) output_scope.set_tag_maybe(GEN_AI_EXECUTION_TYPE_KEY, execution_type) - output_scope.set_tag_maybe(CHANNEL_NAME_KEY, source_metadata.get("name")) - output_scope.set_tag_maybe(CHANNEL_LINK_KEY, source_metadata.get("description")) + output_scope.set_tag_maybe(CHANNEL_NAME_KEY, channel.get("name")) + output_scope.set_tag_maybe(CHANNEL_LINK_KEY, channel.get("link")) if caller_details: - output_scope.set_tag_maybe(GEN_AI_CALLER_ID_KEY, caller_details.caller_id) - output_scope.set_tag_maybe(GEN_AI_CALLER_UPN_KEY, caller_details.caller_upn) - output_scope.set_tag_maybe(GEN_AI_CALLER_NAME_KEY, caller_details.caller_name) + output_scope.set_tag_maybe(USER_ID_KEY, caller_details.caller_id) + output_scope.set_tag_maybe(USER_EMAIL_KEY, caller_details.caller_upn) + output_scope.set_tag_maybe(USER_NAME_KEY, caller_details.caller_name) try: await send_next() diff --git a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_baggage.py b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_baggage.py index c1e36341..3fe3ecc1 100644 --- a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_baggage.py +++ b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_baggage.py @@ -11,9 +11,9 @@ from .utils import ( get_caller_pairs, + get_channel_pairs, get_conversation_pairs, get_execution_type_pair, - get_source_metadata_pairs, get_target_agent_pairs, get_tenant_id_pair, ) @@ -27,7 +27,7 @@ def _iter_all_pairs(turn_context: TurnContext) -> Iterator[tuple[str, Any]]: yield from get_execution_type_pair(activity) yield from get_target_agent_pairs(activity) yield from get_tenant_id_pair(activity) - yield from get_source_metadata_pairs(activity) + yield from get_channel_pairs(activity) yield from get_conversation_pairs(activity) diff --git a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_invoke_agent_scope.py b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_invoke_agent_scope.py index f0f990d6..e6fc6ac6 100644 --- a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_invoke_agent_scope.py +++ b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/populate_invoke_agent_scope.py @@ -9,9 +9,9 @@ from .utils import ( get_caller_pairs, + get_channel_pairs, get_conversation_pairs, get_execution_type_pair, - get_source_metadata_pairs, get_target_agent_pairs, get_tenant_id_pair, ) @@ -39,7 +39,7 @@ def populate(scope: InvokeAgentScope, turn_context: TurnContext) -> InvokeAgentS scope.record_attributes(get_execution_type_pair(activity)) scope.record_attributes(get_target_agent_pairs(activity)) scope.record_attributes(get_tenant_id_pair(activity)) - scope.record_attributes(get_source_metadata_pairs(activity)) + scope.record_attributes(get_channel_pairs(activity)) scope.record_attributes(get_conversation_pairs(activity)) if activity.text: diff --git a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/utils.py b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/utils.py index a875bd06..570e8572 100644 --- a/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/utils.py +++ b/libraries/microsoft-agents-a365-observability-hosting/microsoft_agents_a365/observability/hosting/scope_helpers/utils.py @@ -9,16 +9,16 @@ CHANNEL_NAME_KEY, GEN_AI_AGENT_AUID_KEY, GEN_AI_AGENT_DESCRIPTION_KEY, + GEN_AI_AGENT_EMAIL_KEY, GEN_AI_AGENT_ID_KEY, GEN_AI_AGENT_NAME_KEY, - GEN_AI_AGENT_UPN_KEY, - GEN_AI_CALLER_ID_KEY, - GEN_AI_CALLER_NAME_KEY, - GEN_AI_CALLER_UPN_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_CONVERSATION_ITEM_LINK_KEY, GEN_AI_EXECUTION_TYPE_KEY, TENANT_ID_KEY, + USER_EMAIL_KEY, + USER_ID_KEY, + USER_NAME_KEY, ) from microsoft_agents_a365.observability.core.execution_type import ExecutionType @@ -38,9 +38,9 @@ def get_caller_pairs(activity: Activity) -> Iterator[tuple[str, Any]]: frm = activity.from_property if not frm: return - yield GEN_AI_CALLER_ID_KEY, frm.aad_object_id - yield GEN_AI_CALLER_NAME_KEY, frm.name - yield GEN_AI_CALLER_UPN_KEY, frm.agentic_user_id + yield USER_ID_KEY, frm.aad_object_id + yield USER_NAME_KEY, frm.name + yield USER_EMAIL_KEY, frm.agentic_user_id def get_execution_type_pair(activity: Activity) -> Iterator[tuple[str, Any]]: @@ -63,7 +63,7 @@ def get_target_agent_pairs(activity: Activity) -> Iterator[tuple[str, Any]]: yield GEN_AI_AGENT_ID_KEY, activity.get_agentic_instance_id() yield GEN_AI_AGENT_NAME_KEY, rec.name yield GEN_AI_AGENT_AUID_KEY, rec.aad_object_id - yield GEN_AI_AGENT_UPN_KEY, activity.get_agentic_user() + yield GEN_AI_AGENT_EMAIL_KEY, activity.get_agentic_user() yield ( GEN_AI_AGENT_DESCRIPTION_KEY, rec.role, @@ -74,12 +74,12 @@ def get_tenant_id_pair(activity: Activity) -> Iterator[tuple[str, Any]]: yield TENANT_ID_KEY, activity.recipient.tenant_id -def get_source_metadata_pairs(activity: Activity) -> Iterator[tuple[str, Any]]: +def get_channel_pairs(activity: Activity) -> Iterator[tuple[str, Any]]: """ - Generate source metadata pairs from activity, handling both string and ChannelId object cases. + Generate channel pairs from activity, handling both string and ChannelId object cases. :param activity: The activity object (Activity instance or dict) - :return: Iterator of (key, value) tuples for source metadata + :return: Iterator of (key, value) tuples for channel information """ # Handle channel_id (can be string or ChannelId object) channel_id = activity.channel_id diff --git a/tests/observability/core/test_baggage_builder.py b/tests/observability/core/test_baggage_builder.py index 162555cd..1e5dd2b3 100644 --- a/tests/observability/core/test_baggage_builder.py +++ b/tests/observability/core/test_baggage_builder.py @@ -9,14 +9,14 @@ CHANNEL_NAME_KEY, GEN_AI_AGENT_AUID_KEY, GEN_AI_AGENT_BLUEPRINT_ID_KEY, + GEN_AI_AGENT_EMAIL_KEY, GEN_AI_AGENT_ID_KEY, - GEN_AI_AGENT_UPN_KEY, GEN_AI_CALLER_CLIENT_IP_KEY, - GEN_AI_CALLER_ID_KEY, SERVICE_NAME_KEY, SESSION_DESCRIPTION_KEY, SESSION_ID_KEY, TENANT_ID_KEY, + USER_ID_KEY, ) from microsoft_agents_a365.observability.core.middleware.baggage_builder import BaggageBuilder from opentelemetry import baggage, context, trace @@ -94,9 +94,9 @@ def test_all_baggage_keys(self): self.assertEqual(current_baggage.get(TENANT_ID_KEY), "tenant-1") self.assertEqual(current_baggage.get(GEN_AI_AGENT_ID_KEY), "agent-1") self.assertEqual(current_baggage.get(GEN_AI_AGENT_AUID_KEY), "auid-1") - self.assertEqual(current_baggage.get(GEN_AI_AGENT_UPN_KEY), "upn-1") + self.assertEqual(current_baggage.get(GEN_AI_AGENT_EMAIL_KEY), "upn-1") self.assertEqual(current_baggage.get(GEN_AI_AGENT_BLUEPRINT_ID_KEY), "blueprint-1") - self.assertEqual(current_baggage.get(GEN_AI_CALLER_ID_KEY), "caller-1") + self.assertEqual(current_baggage.get(USER_ID_KEY), "caller-1") self.assertEqual(current_baggage.get(GEN_AI_CALLER_CLIENT_IP_KEY), "192.168.1.100") print("✅ All baggage keys work correctly!") @@ -164,9 +164,9 @@ def test_baggage_reset_after_scope_exit(self): self.assertEqual(scoped_baggage.get(TENANT_ID_KEY), "test-tenant") self.assertEqual(scoped_baggage.get(GEN_AI_AGENT_ID_KEY), "test-agent") self.assertEqual(scoped_baggage.get(GEN_AI_AGENT_AUID_KEY), "test-auid") - self.assertEqual(scoped_baggage.get(GEN_AI_AGENT_UPN_KEY), "test-upn") + self.assertEqual(scoped_baggage.get(GEN_AI_AGENT_EMAIL_KEY), "test-upn") self.assertEqual(scoped_baggage.get(GEN_AI_AGENT_BLUEPRINT_ID_KEY), "test-blueprint") - self.assertEqual(scoped_baggage.get(GEN_AI_CALLER_ID_KEY), "test-caller") + self.assertEqual(scoped_baggage.get(USER_ID_KEY), "test-caller") # Original baggage should still exist self.assertEqual(scoped_baggage.get("existing_key"), "existing_value") @@ -177,9 +177,9 @@ def test_baggage_reset_after_scope_exit(self): self.assertIsNone(final_baggage.get(TENANT_ID_KEY)) self.assertIsNone(final_baggage.get(GEN_AI_AGENT_ID_KEY)) self.assertIsNone(final_baggage.get(GEN_AI_AGENT_AUID_KEY)) - self.assertIsNone(final_baggage.get(GEN_AI_AGENT_UPN_KEY)) + self.assertIsNone(final_baggage.get(GEN_AI_AGENT_EMAIL_KEY)) self.assertIsNone(final_baggage.get(GEN_AI_AGENT_BLUEPRINT_ID_KEY)) - self.assertIsNone(final_baggage.get(GEN_AI_CALLER_ID_KEY)) + self.assertIsNone(final_baggage.get(USER_ID_KEY)) # Original baggage should be restored self.assertEqual(final_baggage.get("existing_key"), "existing_value") @@ -194,12 +194,12 @@ def test_set_pairs_accepts_dict_and_iterable(self): } iter_pairs = [ (GEN_AI_AGENT_AUID_KEY, "auid-x"), - (GEN_AI_AGENT_UPN_KEY, "upn-x"), + (GEN_AI_AGENT_EMAIL_KEY, "upn-x"), ] # Also verify that None / whitespace values are ignored dict_pairs_with_ignored = { - GEN_AI_CALLER_ID_KEY: None, # ignored + USER_ID_KEY: None, # ignored } iter_pairs_with_ignored = [ (SESSION_ID_KEY, " "), # ignored (whitespace) @@ -217,33 +217,11 @@ def test_set_pairs_accepts_dict_and_iterable(self): self.assertEqual(baggage_contents.get(TENANT_ID_KEY), "tenant-x") self.assertEqual(baggage_contents.get(GEN_AI_AGENT_ID_KEY), "agent-x") self.assertEqual(baggage_contents.get(GEN_AI_AGENT_AUID_KEY), "auid-x") - self.assertEqual(baggage_contents.get(GEN_AI_AGENT_UPN_KEY), "upn-x") + self.assertEqual(baggage_contents.get(GEN_AI_AGENT_EMAIL_KEY), "upn-x") # Ignored values should not be present - self.assertIsNone(baggage_contents.get(GEN_AI_CALLER_ID_KEY)) + self.assertIsNone(baggage_contents.get(USER_ID_KEY)) self.assertIsNone(baggage_contents.get(SESSION_ID_KEY)) - def test_source_metadata_name_method(self): - """Test deprecated source_metadata_name method - should delegate to channel_name.""" - # Should exist and be callable - self.assertTrue(hasattr(self.builder, "source_metadata_name")) - self.assertTrue(callable(self.builder.source_metadata_name)) - - # Should set channel name baggage through delegation - with self.builder.source_metadata_name("test-channel").build(): - current_baggage = baggage.get_all() - self.assertEqual(current_baggage.get(CHANNEL_NAME_KEY), "test-channel") - - def test_source_metadata_description_method(self): - """Test deprecated source_metadata_description method - should delegate to channel_links.""" - # Should exist and be callable - self.assertTrue(hasattr(self.builder, "source_metadata_description")) - self.assertTrue(callable(self.builder.source_metadata_description)) - - # Should set channel description baggage through delegation - with self.builder.source_metadata_description("test-description").build(): - current_baggage = baggage.get_all() - self.assertEqual(current_baggage.get(CHANNEL_LINK_KEY), "test-description") - def test_session_id_method(self): """Test session_id method sets session ID baggage.""" # Should exist and be callable diff --git a/tests/observability/core/test_execute_tool_scope.py b/tests/observability/core/test_execute_tool_scope.py index 20744252..f857299b 100644 --- a/tests/observability/core/test_execute_tool_scope.py +++ b/tests/observability/core/test_execute_tool_scope.py @@ -9,10 +9,10 @@ import pytest from microsoft_agents_a365.observability.core import ( AgentDetails, + Channel, ExecuteToolScope, ExecutionType, Request, - SourceMetadata, TenantDetails, ToolCallDetails, configure, @@ -97,7 +97,7 @@ def test_request_metadata_set_on_span(self): content="Execute tool with request metadata", execution_type=ExecutionType.AGENT_TO_AGENT, session_id="session-xyz", - source_metadata=SourceMetadata(name="Channel 1", description="Link to channel"), + channel=Channel(name="Channel 1", link="Link to channel"), ) scope = ExecuteToolScope.start( @@ -120,7 +120,7 @@ def test_request_metadata_set_on_span(self): ) self.assertEqual( span_attributes[CHANNEL_NAME_KEY], - request.source_metadata.name, + request.channel.name, ) self.assertIn( @@ -130,7 +130,7 @@ def test_request_metadata_set_on_span(self): ) self.assertEqual( span_attributes[CHANNEL_LINK_KEY], - request.source_metadata.description, + request.channel.link, ) def test_execute_tool_scope_with_parent_context(self): diff --git a/tests/observability/core/test_inference_scope.py b/tests/observability/core/test_inference_scope.py index f67b3785..0ff414ca 100644 --- a/tests/observability/core/test_inference_scope.py +++ b/tests/observability/core/test_inference_scope.py @@ -8,12 +8,12 @@ import pytest from microsoft_agents_a365.observability.core import ( + Channel, ExecutionType, InferenceCallDetails, InferenceOperationType, InferenceScope, Request, - SourceMetadata, TenantDetails, configure, extract_context_from_headers, @@ -161,7 +161,7 @@ def test_request_metadata_set_on_span(self): content="Inference request with source metadata", execution_type=ExecutionType.AGENT_TO_AGENT, session_id="session-meta", - source_metadata=SourceMetadata(name="Channel 1", description="Link to channel"), + channel=Channel(name="Channel 1", link="Link to channel"), ) scope = InferenceScope.start(details, self.agent_details, self.tenant_details, request) @@ -182,7 +182,7 @@ def test_request_metadata_set_on_span(self): ) self.assertEqual( span_attributes[CHANNEL_NAME_KEY], - request.source_metadata.name, + request.channel.name, ) self.assertIn( @@ -192,7 +192,7 @@ def test_request_metadata_set_on_span(self): ) self.assertEqual( span_attributes[CHANNEL_LINK_KEY], - request.source_metadata.description, + request.channel.link, ) def test_inference_scope_context_manager(self): diff --git a/tests/observability/core/test_invoke_agent_scope.py b/tests/observability/core/test_invoke_agent_scope.py index 5fa55c5a..dcd34a33 100644 --- a/tests/observability/core/test_invoke_agent_scope.py +++ b/tests/observability/core/test_invoke_agent_scope.py @@ -10,11 +10,11 @@ import pytest from microsoft_agents_a365.observability.core import ( AgentDetails, + Channel, ExecutionType, InvokeAgentDetails, InvokeAgentScope, Request, - SourceMetadata, TenantDetails, configure, get_tracer_provider, @@ -59,12 +59,10 @@ def setUpClass(cls): session_id="session-123", ) - # Create source metadata for requests - cls.source_metadata = SourceMetadata( - id="source-agent-456", + # Create channel for requests + cls.channel = Channel( name="Source Channel", - icon_uri="https://example.com/source-icon.png", - description="Source channel description", + link="Source channel link", ) # Create a comprehensive request object @@ -72,7 +70,7 @@ def setUpClass(cls): content="Process customer inquiry about order status", execution_type=ExecutionType.AGENT_TO_AGENT, session_id="session-abc123", - source_metadata=cls.source_metadata, + channel=cls.channel, ) # Create caller details (non-agentic caller) @@ -175,14 +173,14 @@ def test_request_attributes_set_on_span(self): if CHANNEL_NAME_KEY in span_attributes: self.assertEqual( span_attributes[CHANNEL_NAME_KEY], - self.source_metadata.name, # From cls.source_metadata.name + self.channel.name, # From cls.channel.name ) - # Check source channel description from mock data + # Check source channel link from mock data if CHANNEL_LINK_KEY in span_attributes: self.assertEqual( span_attributes[CHANNEL_LINK_KEY], - self.source_metadata.description, # From cls.source_metadata.description + self.channel.link, # From cls.channel.link ) # Check execution type from mock data diff --git a/tests/observability/hosting/middleware/test_baggage_middleware.py b/tests/observability/hosting/middleware/test_baggage_middleware.py index ddc00e00..4263e898 100644 --- a/tests/observability/hosting/middleware/test_baggage_middleware.py +++ b/tests/observability/hosting/middleware/test_baggage_middleware.py @@ -13,8 +13,8 @@ ) from microsoft_agents.hosting.core import TurnContext from microsoft_agents_a365.observability.core.constants import ( - GEN_AI_CALLER_ID_KEY, TENANT_ID_KEY, + USER_ID_KEY, ) from microsoft_agents_a365.observability.hosting.middleware.baggage_middleware import ( BaggageMiddleware, @@ -64,7 +64,7 @@ async def test_baggage_middleware_propagates_baggage(): async def logic(): nonlocal captured_caller_id, captured_tenant_id - captured_caller_id = baggage.get_baggage(GEN_AI_CALLER_ID_KEY) + captured_caller_id = baggage.get_baggage(USER_ID_KEY) captured_tenant_id = baggage.get_baggage(TENANT_ID_KEY) await middleware.on_turn(ctx, logic) @@ -88,7 +88,7 @@ async def test_baggage_middleware_skips_async_reply(): async def logic(): nonlocal logic_called, captured_caller_id logic_called = True - captured_caller_id = baggage.get_baggage(GEN_AI_CALLER_ID_KEY) + captured_caller_id = baggage.get_baggage(USER_ID_KEY) await middleware.on_turn(ctx, logic) diff --git a/tests/observability/hosting/scope_helpers/test_populate_baggage.py b/tests/observability/hosting/scope_helpers/test_populate_baggage.py index b6cc7492..58f9f80a 100644 --- a/tests/observability/hosting/scope_helpers/test_populate_baggage.py +++ b/tests/observability/hosting/scope_helpers/test_populate_baggage.py @@ -5,7 +5,7 @@ from microsoft_agents.activity import Activity, ChannelAccount, ConversationAccount from microsoft_agents.hosting.core import TurnContext -from microsoft_agents_a365.observability.core.constants import GEN_AI_CALLER_ID_KEY +from microsoft_agents_a365.observability.core.constants import USER_ID_KEY from microsoft_agents_a365.observability.core.middleware.baggage_builder import BaggageBuilder from microsoft_agents_a365.observability.hosting.scope_helpers.populate_baggage import populate @@ -37,5 +37,5 @@ def test_populate(): # Verify builder was populated by checking its internal _pairs dict assert len(builder._pairs) > 0 # Verify specific expected baggage keys were set - assert GEN_AI_CALLER_ID_KEY in builder._pairs - assert builder._pairs[GEN_AI_CALLER_ID_KEY] == "caller-id" + assert USER_ID_KEY in builder._pairs + assert builder._pairs[USER_ID_KEY] == "caller-id" diff --git a/tests/observability/hosting/scope_helpers/test_populate_invoke_agent_scope.py b/tests/observability/hosting/scope_helpers/test_populate_invoke_agent_scope.py index 805a119c..bc38cde0 100644 --- a/tests/observability/hosting/scope_helpers/test_populate_invoke_agent_scope.py +++ b/tests/observability/hosting/scope_helpers/test_populate_invoke_agent_scope.py @@ -10,10 +10,10 @@ from microsoft_agents_a365.observability.core.agent_details import AgentDetails from microsoft_agents_a365.observability.core.constants import ( CHANNEL_NAME_KEY, - GEN_AI_CALLER_ID_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_EXECUTION_TYPE_KEY, GEN_AI_INPUT_MESSAGES_KEY, + USER_ID_KEY, ) from microsoft_agents_a365.observability.core.invoke_agent_details import InvokeAgentDetails from microsoft_agents_a365.observability.core.invoke_agent_scope import InvokeAgentScope @@ -73,8 +73,8 @@ def test_populate(): attributes = scope._span._attributes # Check caller attributes - assert GEN_AI_CALLER_ID_KEY in attributes - assert attributes[GEN_AI_CALLER_ID_KEY] == "caller-aad-id" + assert USER_ID_KEY in attributes + assert attributes[USER_ID_KEY] == "caller-aad-id" # Check execution type assert GEN_AI_EXECUTION_TYPE_KEY in attributes diff --git a/tests/observability/hosting/scope_helpers/test_scope_helper_utils.py b/tests/observability/hosting/scope_helpers/test_scope_helper_utils.py index e6f5199b..bedaf497 100644 --- a/tests/observability/hosting/scope_helpers/test_scope_helper_utils.py +++ b/tests/observability/hosting/scope_helpers/test_scope_helper_utils.py @@ -7,23 +7,23 @@ CHANNEL_NAME_KEY, GEN_AI_AGENT_AUID_KEY, GEN_AI_AGENT_DESCRIPTION_KEY, + GEN_AI_AGENT_EMAIL_KEY, GEN_AI_AGENT_ID_KEY, GEN_AI_AGENT_NAME_KEY, - GEN_AI_AGENT_UPN_KEY, - GEN_AI_CALLER_ID_KEY, - GEN_AI_CALLER_NAME_KEY, - GEN_AI_CALLER_UPN_KEY, GEN_AI_CONVERSATION_ID_KEY, GEN_AI_CONVERSATION_ITEM_LINK_KEY, GEN_AI_EXECUTION_TYPE_KEY, TENANT_ID_KEY, + USER_EMAIL_KEY, + USER_ID_KEY, + USER_NAME_KEY, ) from microsoft_agents_a365.observability.core.execution_type import ExecutionType from microsoft_agents_a365.observability.hosting.scope_helpers.utils import ( get_caller_pairs, + get_channel_pairs, get_conversation_pairs, get_execution_type_pair, - get_source_metadata_pairs, get_target_agent_pairs, get_tenant_id_pair, ) @@ -41,9 +41,9 @@ def test_get_caller_pairs(): result = list(get_caller_pairs(activity)) - assert (GEN_AI_CALLER_ID_KEY, "caller-aad-id") in result - assert (GEN_AI_CALLER_NAME_KEY, "Test Caller") in result - assert (GEN_AI_CALLER_UPN_KEY, "caller-upn") in result + assert (USER_ID_KEY, "caller-aad-id") in result + assert (USER_NAME_KEY, "Test Caller") in result + assert (USER_EMAIL_KEY, "caller-upn") in result def test_get_execution_type_pair(): @@ -73,7 +73,7 @@ def test_get_target_agent_pairs(): assert (GEN_AI_AGENT_ID_KEY, "agent-app-id") in result assert (GEN_AI_AGENT_NAME_KEY, "Test Agent") in result assert (GEN_AI_AGENT_AUID_KEY, "agent-auid") in result - assert (GEN_AI_AGENT_UPN_KEY, "agent-upn") in result + assert (GEN_AI_AGENT_EMAIL_KEY, "agent-upn") in result assert (GEN_AI_AGENT_DESCRIPTION_KEY, "agenticAppInstance") in result @@ -87,11 +87,11 @@ def test_get_tenant_id_pair(): assert (TENANT_ID_KEY, "test-tenant-id") in result -def test_get_source_metadata_pairs(): - """Test get_source_metadata_pairs extracts channel metadata.""" +def test_get_channel_pairs(): + """Test get_channel_pairs extracts channel metadata.""" activity = Activity(type="message", channel_id="test-channel") - result = list(get_source_metadata_pairs(activity)) + result = list(get_channel_pairs(activity)) assert (CHANNEL_NAME_KEY, "test-channel") in result assert (CHANNEL_LINK_KEY, None) in result diff --git a/tests/usage_example.py b/tests/usage_example.py index e42e9259..34e21072 100644 --- a/tests/usage_example.py +++ b/tests/usage_example.py @@ -16,11 +16,11 @@ def main(): # Import the updated SDK classes from microsoft_agents_a365.observability.core import ( AgentDetails, + Channel, ExecutionType, InvokeAgentDetails, InvokeAgentScope, Request, - SourceMetadata, configure, ) @@ -31,15 +31,13 @@ def main(): configure("my-service", "my-namespace") print("✅ Telemetry configured") - # Example 1: Enhanced Agent Execution with Session and Source Metadata + # Example 1: Enhanced Agent Execution with Session and Channel print("\n📋 Example 1: Enhanced Agent Execution") - # Create source metadata (from calling agent) - source_metadata = SourceMetadata( - id="calling-agent-456", + # Create channel (from calling agent) + channel = Channel( name="Calling Agent", - icon_uri="https://example.com/calling-agent-icon.png", - description="The agent that initiated this request", + link="The agent that initiated this request", ) # Create a rich request object @@ -47,7 +45,7 @@ def main(): content="Process customer inquiry about order status", execution_type=ExecutionType.AGENT_TO_AGENT, session_id="session-abc123", - source_metadata=source_metadata, + channel=channel, payload="Customer ID: 12345, Order ID: 67890", ) @@ -86,7 +84,7 @@ def main(): content="Check inventory for product SKU: ABC-123", execution_type=ExecutionType.AGENT_TO_AGENT, session_id="session-abc123", - source_metadata=source_metadata, + channel=channel, ) # Use InvokeAgentScope with enhanced details (like .NET SDK) @@ -113,7 +111,7 @@ def main(): print(" ✅ InvokeAgentDetails now includes session_id") print(" ✅ ExecuteAgentScope has been removed from Python SDK") print(" ✅ Constants aligned: gen_ai.agent.id, session.id, gen_ai.agent365.icon_uri") - print(" ✅ New classes: SourceMetadata, Request, ExecutionType") + print(" ✅ New classes: Channel, Request, ExecutionType") print(" ✅ Baggage propagation from parent to child spans") print(" ✅ Backward compatibility maintained")