Skip to content

Commit 77fc5d8

Browse files
committed
Add x-ms-correlation-id header to gateway requests
Propagates the inbound activity ID (turn_context.activity.id) as the x-ms-correlation-id header on all tooling gateway requests, falling back to a freshly generated UUID4 when no TurnContext is available.
1 parent 8b08ac2 commit 77fc5d8

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import logging
2424
import os
2525
import sys
26+
import uuid
2627
from pathlib import Path
2728
from typing import Any, Awaitable, Callable, Dict, List, Optional
2829
from urllib.parse import urlparse
@@ -150,7 +151,9 @@ async def list_tool_servers(
150151
# BEARER_TOKEN_<MCPSERVERNAME_UPPER> takes precedence; BEARER_TOKEN is the fallback.
151152
acquire: TokenAcquirer = self._create_dev_token_acquirer()
152153
else:
153-
servers = await self._load_servers_from_gateway(agentic_app_id, auth_token, options)
154+
servers = await self._load_servers_from_gateway(
155+
agentic_app_id, auth_token, options, turn_context
156+
)
154157
if (
155158
authorization is not None
156159
and auth_handler_name is not None
@@ -475,7 +478,11 @@ def _log_manifest_search_failure(self) -> None:
475478
# --------------------------------------------------------------------------
476479

477480
async def _load_servers_from_gateway(
478-
self, agentic_app_id: str, auth_token: str, options: ToolOptions
481+
self,
482+
agentic_app_id: str,
483+
auth_token: str,
484+
options: ToolOptions,
485+
turn_context: Optional[TurnContext] = None,
479486
) -> List[MCPServerConfig]:
480487
"""
481488
Reads MCP server configurations from tooling gateway endpoint for production scenario.
@@ -484,6 +491,8 @@ async def _load_servers_from_gateway(
484491
agentic_app_id: Agentic App ID for the agent.
485492
auth_token: Authentication token to access the tooling gateway.
486493
options: ToolOptions instance containing optional parameters.
494+
turn_context: Optional TurnContext used to derive the correlation ID from
495+
``activity.id``. A new UUID is generated when not provided.
487496
488497
Returns:
489498
List[MCPServerConfig]: List of MCP server configurations from tooling gateway.
@@ -495,7 +504,7 @@ async def _load_servers_from_gateway(
495504

496505
try:
497506
config_endpoint = get_tooling_gateway_for_digital_worker(agentic_app_id)
498-
headers = self._prepare_gateway_headers(auth_token, options)
507+
headers = self._prepare_gateway_headers(auth_token, options, turn_context)
499508

500509
self._logger.info(f"Calling tooling gateway endpoint: {config_endpoint}")
501510

@@ -533,7 +542,8 @@ def _prepare_gateway_headers(
533542
Args:
534543
auth_token: Authentication token.
535544
options: ToolOptions instance containing optional parameters.
536-
turn_context: Optional TurnContext for extracting agent blueprint ID for request headers.
545+
turn_context: Optional TurnContext for extracting agent blueprint ID and
546+
correlation ID from ``activity.id``.
537547
538548
Returns:
539549
Dictionary of HTTP headers.
@@ -550,8 +560,39 @@ def _prepare_gateway_headers(
550560
if agent_id:
551561
headers[Constants.Headers.AGENT_ID] = agent_id
552562

563+
# Add x-ms-correlation-id: prefer activity.id from TurnContext, fall back to a new UUID
564+
correlation_id = self._resolve_correlation_id(turn_context)
565+
headers[Constants.Headers.CORRELATION_ID] = correlation_id
566+
self._logger.debug(f"Gateway request correlation ID: {correlation_id}")
567+
553568
return headers
554569

570+
def _resolve_correlation_id(self, turn_context: Optional[TurnContext] = None) -> str:
571+
"""
572+
Resolves the correlation ID to attach to outbound gateway requests.
573+
574+
Uses ``turn_context.activity.id`` when available so the gateway log entry can be
575+
correlated with the inbound activity. Falls back to a newly generated UUID4 when
576+
no context is provided.
577+
578+
Args:
579+
turn_context: Optional TurnContext to extract the activity ID from.
580+
581+
Returns:
582+
str: Correlation ID string (non-empty).
583+
"""
584+
try:
585+
if (
586+
turn_context is not None
587+
and turn_context.activity is not None
588+
and turn_context.activity.id
589+
):
590+
return turn_context.activity.id
591+
except (AttributeError, TypeError):
592+
pass
593+
594+
return str(uuid.uuid4())
595+
555596
def _resolve_agent_id_for_header(
556597
self, auth_token: str, turn_context: Optional[TurnContext] = None
557598
) -> Optional[str]:

libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/utils/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ class Headers:
3333

3434
#: Header name for the subchannel ID.
3535
SUBCHANNEL_ID = "x-ms-subchannel-id"
36+
37+
#: Header name for the correlation ID used to trace a request across services.
38+
CORRELATION_ID = "x-ms-correlation-id"

0 commit comments

Comments
 (0)