Observability SDK

Important

To enable observability in Agent 365, use the Microsoft OpenTelemetry Distro. This distribution provides a single observability SDK across Microsoft, powering Agent 365, Microsoft Foundry, Azure Monitor, and more. The existing approach described in this article continues to work without breaking changes. For migration guidance by language, see the following guides:

Note

Observability is one of the incremental capability tiers in Get started with Agent 365 development and applies to all agent types.

To participate in the Agent 365 ecosystem, add Agent 365 Observability capabilities to your agent. Agent 365 Observability builds on OpenTelemetry (OTel) and provides a unified framework for capturing telemetry consistently and securely across all agent platforms. By implementing this required component, you enable IT admins to monitor your agent's activity in Microsoft admin center and allow security teams to use Defender and Purview for compliance and threat detection.

Key benefits

  • End-to-end visibility: Capture comprehensive telemetry for every agent invocation, including sessions, tool calls, and exceptions, giving you full traceability across platforms.
  • Security and compliance enablement: Feed unified audit logs into Defender and Purview, enabling advanced security scenarios and compliance reporting for your agent.
  • Cross-platform flexibility: Build on OTel standards and support diverse runtimes and platforms like Copilot Studio, Foundry, and future agent frameworks.
  • Operational efficiency for admins: Provide centralized observability in Microsoft 365 admin center, reducing troubleshooting time and improving governance with role-based access controls for IT teams managing your agent.

Supported agents

The following agent types support Agent 365 observability:

Installation

Use these commands to install the observability modules for the languages supported by Agent 365.

Install the core observability and runtime packages. All agents that use Agent 365 Observability need these packages.

pip install microsoft-agents-a365-observability-core
pip install microsoft-agents-a365-runtime

If your agent uses the Microsoft Agents Hosting package, install the hosting integration package. It provides middleware that automatically populates baggage and scopes from the TurnContext, and includes token caching for the observability exporter.

pip install microsoft-agents-a365-observability-hosting

If your agent uses one of the supported AI frameworks, install the corresponding auto-instrumentation extension to automatically capture telemetry without manual instrumentation code. For configuration details, see Auto-instrumentation.

# For Semantic Kernel
pip install microsoft-agents-a365-observability-extensions-semantic-kernel

# For OpenAI Agents SDK
pip install microsoft-agents-a365-observability-extensions-openai

# For Microsoft Agent Framework
pip install microsoft-agents-a365-observability-extensions-agent-framework

# For LangChain
pip install microsoft-agents-a365-observability-extensions-langchain

Configuration

Use the following settings to enable and customize Agent 365 Observability for your agent.

Set the ENABLE_A365_OBSERVABILITY_EXPORTER environment variable to true for observability. This setting exports logs to the service and requires a token_resolver to be provided. Otherwise, the console exporter is used.

from microsoft_agents_a365.observability.core import configure

def token_resolver(agent_id: str, tenant_id: str) -> str | None:
    # Implement secure token retrieval here
    return "Bearer <token>"

configure(
    service_name="my-agent-service",
    service_namespace="my.namespace",
    token_resolver=token_resolver,
)

The token resolver is excluded from logging to the console.

You can customize the exporter behavior by passing an Agent365ExporterOptions instance to exporter_options. When exporter_options is provided, it takes precedence over the token_resolver and cluster_category parameters.

from microsoft_agents_a365.observability.core import configure, Agent365ExporterOptions

configure(
    service_name="my-agent-service",
    service_namespace="my.namespace",
    exporter_options=Agent365ExporterOptions(
        cluster_category="prod",
        token_resolver=token_resolver,
    ),
    suppress_invoke_agent_input=True,
)

The following table describes the optional parameters for configure().

Parameter Description Default
logger_name Name of the Python logger used for debugging and console log output. microsoft_agents_a365.observability.core
exporter_options An Agent365ExporterOptions instance that configures the token resolver and cluster category together. None
suppress_invoke_agent_input When True, suppresses input messages on InvokeAgent spans. False

The following table describes the optional properties for Agent365ExporterOptions.

Property Description Default
use_s2s_endpoint When True, uses the service-to-service endpoint path. False
max_queue_size Maximum queue size for the batch processor. 2048
scheduled_delay_ms Delay in milliseconds between export batches. 5000
exporter_timeout_ms Timeout in milliseconds for the export operation. 30000
max_export_batch_size Maximum batch size for export operations. 512

Baggage attributes

Use BaggageBuilder to set contextual information that flows through all spans in a request. The SDK implements a SpanProcessor that copies all nonempty baggage entries to newly started spans without overwriting existing attributes.

from microsoft_agents_a365.observability.core import BaggageBuilder

with (
    BaggageBuilder()
    .tenant_id("tenant-123")
    .agent_id("agent-456")
    .conversation_id("conv-789")
    .build()
):
    # Any spans started in this context will receive these as attributes
    pass

To auto-populate the BaggageBuilder from the TurnContext, use the populate helper in the microsoft-agents-a365-observability-hosting package. This helper automatically extracts caller, agent, tenant, channel, and conversation details from the activity.

from microsoft_agents.hosting.core.turn_context import TurnContext
from microsoft_agents_a365.observability.core import BaggageBuilder
from microsoft_agents_a365.observability.hosting.scope_helpers.populate_baggage import populate

builder = BaggageBuilder()
populate(builder, turn_context)

with builder.build():
    # Baggage is auto-populated from the TurnContext activity
    pass

Baggage middleware

If your agent uses the hosting integration package, register baggage middleware to automatically populate baggage for every incoming request. This step removes the need to call BaggageBuilder manually in each activity handler.

Register BaggageMiddleware on the adapter middleware set. It automatically extracts caller, agent, tenant, channel, and conversation details from every incoming TurnContext and wraps the request in a baggage scope.

from microsoft_agents_a365.observability.hosting import BaggageMiddleware

adapter.use(BaggageMiddleware())

Alternatively, use ObservabilityHostingManager to configure baggage middleware along with other hosting features:

from microsoft_agents_a365.observability.hosting import ObservabilityHostingManager, ObservabilityHostingOptions

options = ObservabilityHostingOptions(enable_baggage=True)
ObservabilityHostingManager.configure(adapter.middleware_set, options)

The middleware skips baggage setup for async replies (ContinueConversation events) to avoid overwriting baggage that the originating request already set.

Token resolver

When you use the Agent 365 exporter, you must provide a token resolver function that returns an authentication token. When you use the Agent 365 Observability SDK with the Agent Hosting framework, you can generate tokens by using the TurnContext from agent activities.

The following snippet shows how to generate a token by using the microsoft_agents.hosting.core SDK. The auth token generated here is used to export the spans to the A365 ingestion service. Agents can generate a token themselves, for example by using Microsoft Authentication Library (MSAL), but they need to ensure the token has the observability scope.

from microsoft_agents.activity import load_configuration_from_env
from microsoft_agents.authentication.msal import MsalConnectionManager
from microsoft_agents.hosting.aiohttp import CloudAdapter
from microsoft_agents.hosting.core import (
    AgentApplication,
    Authorization,
    MemoryStorage,
    TurnContext,
    TurnState,
)
from microsoft_agents_a365.runtime import (
    get_observability_authentication_scope,
)

agents_sdk_config = load_configuration_from_env(environ)

STORAGE = MemoryStorage()
CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config)
ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER)
ADAPTER.use(TranscriptLoggerMiddleware(ConsoleTranscriptLogger()))
AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config)

AGENT_APP = AgentApplication[TurnState](
    storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config
)

@AGENT_APP.activity("message", auth_handlers=["AGENTIC"])
async def on_message(context: TurnContext, _state: TurnState):
    aau_auth_token = await AGENT_APP.auth.exchange_token(
                        context,
                        scopes=get_observability_authentication_scope(),
                        auth_handler_id="AGENTIC",
                    )
    # cache this auth token and return via token resolver

For an agent built with the A365 CLI that uses an AI teammate and the Microsoft Agent 365 Observability Hosting Library package, use AgenticTokenCache to handle token caching automatically. Register the token once per agent and tenant during an activity handler, and pass cache.get_observability_token as the token_resolver in your observability configuration.

from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.hosting.token_cache_helpers import (
    AgenticTokenCache,
    AgenticTokenStruct,
)
from microsoft_agents_a365.runtime import get_observability_authentication_scope

# Create a shared cache instance
token_cache = AgenticTokenCache()

# Use the cache as your token resolver in configure()
configure(
    service_name="my-agent-service",
    service_namespace="my.namespace",
    token_resolver=token_cache.get_observability_token,
)

@AGENT_APP.activity("message", auth_handlers=["AGENTIC"])
async def on_message(context: TurnContext, _state: TurnState):
    token_cache.register_observability(
        agent_id="agent-456",
        tenant_id="tenant-123",
        token_generator=AgenticTokenStruct(
            authorization=AGENT_APP.auth,
            turn_context=context,
        ),
        observability_scopes=get_observability_authentication_scope(),
    )

Auto-instrumentation

Auto-instrumentation automatically listens to agentic frameworks (SDKs) existing telemetry signals for traces and forwards them to Agent 365 observability service. This feature eliminates the need for developers to write monitoring code manually, simplifies setup, and ensures consistent performance tracking.

Important

Auto-instrumentation populates standard OTel attributes only. You must add Microsoft-specific attributes through BaggageBuilder. To see which attributes are missing, validate your console span output against the store logs for the diff set.

Multiple SDKs and platforms support auto-instrumentation:

Platform Supported SDKs / Frameworks
.NET Semantic Kernel, OpenAI, Agent Framework
Python Semantic Kernel, OpenAI, Agent Framework, LangChain
Node.js OpenAI, LangChain

Note

Support for auto-instrumentation varies by platform and SDK implementation.

Semantic Kernel

Auto instrumentation requires the use of baggage builder. Set agent ID and tenant ID by using BaggageBuilder.

Install the package.

pip install microsoft-agents-a365-observability-extensions-semantic-kernel

Configure observability.

from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.semantickernel.trace_instrumentor import SemanticKernelInstrumentor

# Configure observability
configure(
    service_name="my-semantic-kernel-agent",
    service_namespace="ai.agents"
)

# Enable auto-instrumentation
instrumentor = SemanticKernelInstrumentor()
instrumentor.instrument()

# Your Semantic Kernel code is now automatically traced

OpenAI

Auto instrumentation requires the use of baggage builder. Set agent ID and tenant ID by using BaggageBuilder.

Install the package.

pip install microsoft-agents-a365-observability-extensions-openai

Configure observability.

from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.openai import OpenAIAgentsTraceInstrumentor

# Configure observability
configure(
    service_name="my-openai-agent",
    service_namespace="ai.agents"
)

# Enable auto-instrumentation
instrumentor = OpenAIAgentsTraceInstrumentor()
instrumentor.instrument()

# Your OpenAI Agents code is now automatically traced

Agent Framework

Auto instrumentation requires the use of baggage builder. Set agent ID and tenant ID by using BaggageBuilder.

Install the package.

pip install microsoft-agents-a365-observability-extensions-agent-framework

Configure observability.

from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.agentframework import (
    AgentFrameworkInstrumentor,
)

# Configure observability
configure(
    service_name="AgentFrameworkTracingWithAzureOpenAI",
    service_namespace="AgentFrameworkTesting",
)

# Enable auto-instrumentation
AgentFrameworkInstrumentor().instrument()

LangChain Framework

Auto-instrumentation requires the use of baggage builder. Set agent ID and tenant ID by using BaggageBuilder.

Install the package.

pip install microsoft-agents-a365-observability-extensions-langchain

Configure observability.

from microsoft_agents_a365.observability.core.config import configure
from microsoft_agents_a365.observability.extensions.langchain import CustomLangChainInstrumentor

# Configure observability
configure(
    service_name="my-langchain-agent",
    service_namespace="ai.agents"
)

# Enable auto-instrumentation
CustomLangChainInstrumentor()

# Your LangChain code is now automatically traced

Manual Instrumentation

Use Agent 365 observability SDK to understand the internal working of the agent. The SDK provides scopes that you can start: InvokeAgentScope, ExecuteToolScope, InferenceScope, and OutputScope.

Agent invocation

Use this scope at the start of your agent process. By using the invoke agent scope, you can capture properties like the current agent being invoked, agent user data, and more.