Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Important
You need to be part of the Frontier preview program to get early access to Microsoft Agent 365. Frontier connects you directly with Microsoft’s latest AI innovations. Frontier previews are subject to the existing preview terms of your customer agreements. As these features are still in development, their availability and capabilities may change over time.
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.
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.
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 the digital worker scenario, if your agent uses 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.
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.
from microsoft_agents_a365.observability.core import (
InvokeAgentScope,
InvokeAgentScopeDetails,
AgentDetails,
CallerDetails,
UserDetails,
Channel,
Request,
ServiceEndpoint,
)
agent_details = AgentDetails(
agent_id="agent-456",
agent_name="My Agent",
agent_description="An AI agent powered by Azure OpenAI",
agentic_user_id="auid-123",
agentic_user_email="agent@contoso.com",
agent_blueprint_id="blueprint-789",
tenant_id="tenant-123",
)
scope_details = InvokeAgentScopeDetails(
endpoint=ServiceEndpoint(hostname="myagent.contoso.com", port=443),
)
request = Request(
content="User asks a question",
session_id="session-42",
conversation_id="conv-xyz",
channel=Channel(name="msteams"),
)
caller_details = CallerDetails(
user_details=UserDetails(
user_id="user-123",
user_email="jane.doe@contoso.com",
user_name="Jane Doe",
),
)
with InvokeAgentScope.start(request, scope_details, agent_details, caller_details):
# Perform agent invocation logic
response = call_agent(...)
Tool execution
The following examples show how to add observability tracking to your agent's tool execution. This tracking captures telemetry for monitoring and auditing purposes.
from microsoft_agents_a365.observability.core import (
ExecuteToolScope,
ToolCallDetails,
Request,
ServiceEndpoint,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
tool_details = ToolCallDetails(
tool_name="summarize",
tool_type="function",
tool_call_id="tc-001",
arguments="{'text': '...'}",
description="Summarize provided text",
endpoint=ServiceEndpoint(hostname="tools.contoso.com", port=8080),
)
with ExecuteToolScope.start(request, tool_details, agent_details) as scope:
result = run_tool(tool_details)
scope.record_response(result)
Inference
The following examples show how to instrument AI model inference calls with observability tracking to capture token usage, model details, and response metadata.
from microsoft_agents_a365.observability.core import (
InferenceScope,
InferenceCallDetails,
InferenceOperationType,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
inference_details = InferenceCallDetails(
operationName=InferenceOperationType.CHAT,
model="gpt-4o-mini",
providerName="azure-openai",
inputTokens=123,
outputTokens=456,
finishReasons=["stop"],
)
with InferenceScope.start(request, inference_details, agent_details) as scope:
completion = call_llm(...)
scope.record_output_messages([completion.text])
scope.record_input_tokens(completion.usage.input_tokens)
scope.record_output_tokens(completion.usage.output_tokens)
Output
Use this scope for asynchronous scenarios where InvokeAgentScope, ExecuteToolScope, or InferenceScope can't capture output data synchronously. Start OutputScope as a child span to record the final output messages after the parent scope finishes.
from microsoft_agents_a365.observability.core import (
OutputScope,
Response,
SpanDetails,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
# Get the parent context from the originating scope
parent_context = invoke_scope.get_context()
response = Response(messages=["Here is your organized inbox with 15 urgent emails."])
with OutputScope.start(
request,
response,
agent_details,
span_details=SpanDetails(parent_context=parent_context),
):
# Output messages are recorded automatically from the response
pass
Validate locally
To verify that you successfully integrated with the observability SDK, examine the console logs generated by your agent and logs from observability SDK.
Set the environment variable ENABLE_A365_OBSERVABILITY_EXPORTER to false. This setting exports spans (traces) to the console.
To investigate export failures, enable verbose logging by setting ENABLE_A365_OBSERVABILITY_EXPORTER to true and configuring debug logging in your application startup:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("microsoft_agents_a365.observability.core").setLevel(logging.DEBUG)
# Or target only the exporter:
logging.getLogger(
"microsoft_agents_a365.observability.core.exporters.agent365_exporter"
).setLevel(logging.DEBUG)
Key log messages:
DEBUG Token resolved for agent {agentId} tenant {tenantId}
DEBUG Exporting {n} spans to {url}
DEBUG HTTP 200 - correlation ID: abc-123
ERROR Token resolution failed: {error}
ERROR HTTP 401 exporting spans - correlation ID: abc-123
INFO No spans with tenant/agent identity found; nothing exported.
Viewing exported logs
To view agent telemetry in Microsoft Purview or Microsoft Defender, make sure the following requirements are met:
- Microsoft Purview: Auditing must be turned on for your organization. For instructions, see Turn auditing on or off.
- Microsoft Defender: Advanced hunting must be configured to access the
CloudAppEventstable. For details, see CloudAppEvents table in the advanced hunting schema.
Validate for store publishing
Before publishing, use console logs to validate your observability integration for the agent by implementing the required invoke agent, execute tool, inference, and output scopes. Then compare your agent's logs against the following attribute lists to verify all required attributes are present. Capture attributes on each scope or through the baggage builder, and include optional attributes at your discretion.
For more information about store publishing requirements, see store validation guidelines.
InvokeAgentScope attributes
The following list summarizes the required and optional telemetry attributes recorded when you start an InvokeAgentScope.
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"microsoft.a365.caller.agent.blueprint.id": "Optional",
"microsoft.a365.caller.agent.id": "Optional",
"microsoft.a365.caller.agent.name": "Optional",
"microsoft.a365.caller.agent.platform.id": "Optional",
"microsoft.a365.caller.agent.user.email": "Optional",
"microsoft.a365.caller.agent.user.id": "Optional",
"microsoft.a365.caller.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.input.messages": "Required",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"server.address": "Required",
"server.port": "Required",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
ExecuteToolScope attributes
The following list summarizes the required and optional telemetry attributes recorded when you start an ExecuteToolScope.
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.operation.name": "Required",
"gen_ai.tool.call.arguments": "Required",
"gen_ai.tool.call.id": "Required",
"gen_ai.tool.call.result": "Required",
"gen_ai.tool.description": "Optional",
"gen_ai.tool.name": "Required",
"gen_ai.tool.type": "Required",
"server.address": "Optional",
"server.port": "Optional",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
InferenceScope attributes
The following list summarizes the required and optional telemetry attributes recorded when you start an InferenceScope.
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.a365.agent.thought.process": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.input.messages": "Required",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"gen_ai.provider.name": "Required",
"gen_ai.request.model": "Required",
"gen_ai.response.finish_reasons": "Optional",
"gen_ai.usage.input_tokens": "Optional",
"gen_ai.usage.output_tokens": "Optional",
"server.address": "Optional",
"server.port": "Optional",
"microsoft.session.description": "Optional",
"microsoft.session.id": "Optional",
"microsoft.tenant.id": "Required"
}
OutputScope attributes
The following list summarizes the required and optional telemetry attributes recorded when you start an OutputScope. Use this scope for asynchronous scenarios where the parent scope can't capture output data synchronously.
"attributes": {
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
Test your agent with observability
After you implement observability in your agent, test it to make sure it captures telemetry correctly. Follow the testing guide to set up your environment. Then, focus primarily on the View observability logs section to validate your observability implementation is working as expected.
Verification:
- Go to:
https://admin.cloud.microsoft/#/agents/all - Select your agent > Activity
- You see sessions and tool calls
Troubleshooting
This section describes common problems when implementing and using observability.
Tip
Agent 365 Troubleshooting Guide contains high-level troubleshooting recommendations, best practices, and links to troubleshooting content for each part of the Agent 365 development lifecycle.
Observability data doesn't appear
Symptoms:
- Agent is running
- No telemetry in admin center
- Can't see agent activity
Root cause:
- Observability isn't enabled
- Configuration errors
- Token resolver problems
Solutions: Try the following steps to resolve the problem:
Verify observability exporter is enabled
You must explicitly enable the Agent 365 exporter. When disabled, the SDK falls back to a console exporter and telemetry isn't sent to the service. For configuration details, see Configuration.
Check token resolver configuration
The exporter requires a valid token resolver that returns a Bearer token for each export request. If the token resolver is missing or returns
null, the export is silently skipped. Make sure your code properly implements the token resolver. For details, see Token resolver.Check for errors in logs
Enable verbose logging and use the
az webapp log tailcommand to search logs for observability-related errors. For details on how to enable logging per platform, see Validate locally.# Look for observability-related errors az webapp log tail --name <your-app-name> --resource-group <your-resource-group> | Select-String "observability"Verify telemetry export
Confirm telemetry is generated and exported as expected.
- Add a console exporter and check if telemetry is generated locally. For details on how to use the console exporter and validate output, see Validate locally.
Missing tenant ID or agent ID — spans skipped
Symptoms: The system silently drops spans and never exports them. Some SDKs log a count of skipped spans or a message such as "No spans with tenant/agent identity found." Others drop them without logging.
Resolution:
- Before export, the SDK partitions spans by tenant and agent identity. The system drops spans that lack either a tenant ID or agent ID and never sends them to the service.
- Ensure
BaggageBuilderis set up with the tenant ID and agent ID before creating spans. These values propagate through the OpenTelemetry context and attach to all spans created within the baggage scope. For the platform-specific API, see Baggage attributes. - Confirm the
TurnContextactivity has a valid recipient with agent identity if you use the baggage middleware or turn context helper from the hosting integration package to populate those IDs.
Token resolution failure — export skipped or unauthorized
Symptoms: The token resolver returns null or throws an error. Depending on the SDK, the export is either skipped entirely or the request is sent without an authorization header and fails with HTTP 401.
Resolution:
- The token resolver is required at initialization. If it's missing, the exporter throws an error on startup. Verify that a token resolver is provided and returns a valid Bearer token.
- Make sure the correct tenant ID and agent ID are used for
BaggageBuilder, because these values are passed to the token resolver. - For Azure-hosted agents, verify the Managed Identity has the required API permission for the observability scope.
HTTP 401 Unauthorized
Symptoms: Export fails with HTTP 401. The exporter doesn't retry this error.
Resolution:
- Verify the token audience matches the observability endpoint scope. The default scope is
https://api.powerplatform.com/.defaultfor an agentic agent. - Ensure the identity (Managed Identity or app registration) has Agent 365 observability permissions.
- Check that the token resolver isn't returning a delegated user token, a token for an incorrect audience, or an expired token.
Important
Existing agents upgrading to these package versions require an extra step
This step applies only if you're upgrading an existing agent. New agent installations don't require this step. If you're upgrading to the following package versions or newer, you must grant the new Agent365.Observability.OtelWrite permission to your identity (Managed Identity or app registration). Without this permission, telemetry export fails with HTTP 401.
| Platform | Minimum version requiring this step |
|---|---|
| .NET | 0.3-beta |
| Node.js | 0.2.0-preview.1 |
| Python | 0.3.0 |
For the required steps, see the changelog in the package you're upgrading.
HTTP 403 Forbidden
Symptoms: Export fails with HTTP 403. The exporter doesn't retry this error.
Resolution:
- Verify whether the Tenant ID is added to the Agent 365 allowed tenant list for trace ingestion.
- Confirm the agent identity has the required role or permission for the target tenant.
HTTP 429 / 5xx — Transient errors
Symptoms: Export fails with a transient HTTP status code such as 429 or 5xx.
Resolution:
- These errors are usually transient and resolve on their own. The Python and JavaScript SDKs automatically retry on HTTP 408, 429, and 5xx status codes up to three times with exponential backoff. The .NET SDK doesn't retry automatically.
- If errors persist, check the service health dashboard.
- Consider reducing export frequency by increasing the scheduled delay between batches or increasing the max export batch size. For configuration options per platform, see the
Agent365ExporterOptionstable in Configuration.
Export timeout
Symptoms: Export attempts time out.
Resolution:
- Check network connectivity to the observability endpoint.
- Timeout defaults vary by platform. The default HTTP request timeout is 30 seconds. Some SDKs also have a separate overall exporter timeout that covers the entire export cycle including retries. For the exact properties and defaults per platform, see the
Agent365ExporterOptionstable in Configuration. - If timeouts occur frequently, increase the relevant timeout value in your exporter options.
Export succeeds but telemetry doesn't appear in Defender or Purview
Symptoms: Logs show a successful export but telemetry isn't visible in Microsoft Defender or Microsoft Purview.
Resolution:
- Verify that you meet the prerequisites for viewing exported logs. For Purview, auditing must be turned on. For Defender, you must configure advanced hunting. For more information, see Viewing exported logs.
- Telemetry can take several minutes to populate after a successful export. Wait for the data to appear before investigating further.
To learn more about testing observability, see: