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:
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
Install the core observability and runtime packages. All agents that use Agent 365 Observability need these packages.
npm install @microsoft/agents-a365-observability
npm 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.
npm 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 OpenAI Agents SDK
npm install @microsoft/agents-a365-observability-extensions-openai
// For LangChain
npm install @microsoft/agents-a365-observability-extensions-langchain
Install the core observability and runtime package. All agents that use Agent 365 Observability need this package.
dotnet add package Microsoft.Agents.A365.Observability.Runtime
If your agent uses the Microsoft.Agents.A365.Observability.Hosting NuGet package, install the hosting integration package. It provides middleware that automatically populates baggage from the TurnContext, and includes token caching for the observability exporter.
dotnet add package 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
dotnet add package Microsoft.Agents.A365.Observability.Extensions.SemanticKernel
// For OpenAI
dotnet add package Microsoft.Agents.A365.Observability.Extensions.OpenAI
// For Agent Framework
dotnet add package Microsoft.Agents.A365.Observability.Extensions.AgentFramework
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 |
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.
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
// Define a token resolver to authenticate with the observability service for exporting logs
const tokenResolver = (agentId, tenantId) => {
// Your token resolution logic here
return "your-token";
};
// Advanced configuration with builder pattern
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
As an alternative to environment variables, you can configure observability programmatically by using a configuration provider through withConfigurationProvider method. If you also use individual builder methods (such as withExporterOptions or withClusterCategory), the individual builder methods take precedence over values from the configuration provider.
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { ObservabilityConfiguration } from '@microsoft/agents-a365-observability';
const configProvider = new ObservabilityConfiguration({
isObservabilityExporterEnabled: () => true,
// Set log levels as pipe-separated values (for example, 'info|warn|error')
observabilityLogLevel: () => 'info|warn|error',
});
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withConfigurationProvider(configProvider)
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
You can customize the exporter behavior by passing an Agent365ExporterOptions instance to withExporterOptions. This option allows you to control batching, timeouts, and the route mode.
import {
ObservabilityManager,
Agent365ExporterOptions,
} from '@microsoft/agents-a365-observability';
import { ClusterCategory } from '@microsoft/agents-a365-runtime';
const exporterOptions = new Agent365ExporterOptions();
exporterOptions.maxQueueSize = 10;
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withClusterCategory(ClusterCategory.prod)
.withExporterOptions(exporterOptions)
.withTokenResolver(tokenResolver)
);
builder.start();
The following table describes the optional properties for Agent365ExporterOptions.
| Property |
Description |
Default |
useS2SEndpoint |
When true, uses the service-to-service endpoint path. |
false |
maxQueueSize |
Maximum queue size for the batch processor. |
2048 |
scheduledDelayMilliseconds |
Delay in milliseconds between export batches. |
5000 |
exporterTimeoutMilliseconds |
Timeout in milliseconds for the entire export operation. |
90000 |
httpRequestTimeoutMilliseconds |
Timeout in milliseconds for each individual HTTP request to the backend. |
30000 |
maxExportBatchSize |
Maximum batch size for export operations. |
512 |
You can also provide a custom logger that implements the ILogger interface (info, warn, error, event). Pass it to the builder by using withCustomLogger.
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withCustomLogger({
info: (message, ...args) => { /* your logging logic */ },
warn: (message, ...args) => { /* your logging logic */ },
error: (message, ...args) => { /* your logging logic */ },
event: (eventName, success, durationMs, message, details) => { /* your logging logic */ }
})
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
Set EnableAgent365Exporter to true in appsettings.json.
In Program.cs, add Agent365ExporterOptions to the service collection. This change configures the delegate the trace exporter uses to retrieve the token.
Add observability related dependencies by using AddA365Tracing().
using Microsoft.Agents.A365.Observability.Runtime;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Exporters;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(sp =>
{
return new Agent365ExporterOptions
{
TokenResolver = async (agentId, tenantId) =>
{
// It's recommended to implement caching in your token provider for performance.
var token = await tokenProvider.GetObservabilityTokenAsync(agentId, tenantId);
return token;
}
};
});
builder.AddA365Tracing();
You can customize the exporter behavior by passing a configure delegate and exporter type to AddA365Tracing().
builder.AddA365Tracing(
configure: tracingBuilder =>
{
// Use the builder to add extensions (e.g., WithSemanticKernel(), WithOpenAI())
},
agent365ExporterType: Agent365ExporterType.Agent365ExporterAsync
);
The following table describes the optional properties for Agent365ExporterOptions.
| Property |
Description |
Default |
UseS2SEndpoint |
When true, uses the service-to-service endpoint path. |
false |
MaxQueueSize |
Maximum queue size for the batch processor. |
2048 |
ScheduledDelayMilliseconds |
Delay in milliseconds between export batches. |
5000 |
ExporterTimeoutMilliseconds |
Timeout in milliseconds for the export operation. |
30000 |
MaxExportBatchSize |
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
import { BaggageBuilder } from '@microsoft/agents-a365-observability';
// Create and apply baggage context
const baggageScope = new BaggageBuilder()
// Core identifiers
.tenantId('tenant-123')
.agentId('agent-456')
.conversationId('conv-789')
.build();
// Execute operations within the baggage context
baggageScope.run(() => {
// All spans created within this context will inherit the baggage values
// Invoke another agent
const agentScope = InvokeAgentScope.start(request, scopeDetails, agentDetails);
// ... agent logic
// Execute tools
const toolScope = ExecuteToolScope.start(request, toolDetails, agentDetails);
// ... tool logic
});
To auto-populate the BaggageBuilder from the TurnContext, use the fromTurnContext helper in the @microsoft/agents-a365-observability-hosting package. This helper automatically extracts caller, agent, tenant, channel, and conversation details from the activity.
import { BaggageBuilder } from '@microsoft/agents-a365-observability';
import { BaggageBuilderUtils } from '@microsoft/agents-a365-observability-hosting';
const baggageScope = BaggageBuilderUtils.fromTurnContext(new BaggageBuilder(), context)
.invokeAgentServer(context.activity.serviceUrl, 3978)
.build();
await baggageScope.run(async () => {
// Baggage is auto-populated from the TurnContext activity
});
using Microsoft.Agents.A365.Observability.Runtime.Common;
using var baggageScope = new BaggageBuilder()
.TenantId("tenant-123")
.AgentId("agent-456")
.ConversationId("conv-789")
.Build();
// Any spans started in this context will receive them as attributes.
To auto-populate the BaggageBuilder from the ITurnContext, use the FromTurnContext extension method in the Microsoft.Agents.A365.Observability.Hosting package. This method automatically extracts caller, agent, tenant, channel, and conversation details from the activity.
using Microsoft.Agents.A365.Observability.Runtime.Common;
using Microsoft.Agents.A365.Observability.Hosting.Extensions;
using var baggageScope = new BaggageBuilder()
.FromTurnContext(turnContext)
.Build();
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.
Register BaggageMiddleware on the adapter. It automatically extracts caller, agent, tenant, channel, and conversation details from every incoming TurnContext and wraps the request in a baggage scope.
import { BaggageMiddleware } from '@microsoft/agents-a365-observability-hosting';
// Option 1: Register middleware directly on the adapter
adapter.use(new BaggageMiddleware());
Alternatively, use ObservabilityHostingManager to configure baggage middleware along with other hosting features:
import { ObservabilityHostingManager } from '@microsoft/agents-a365-observability-hosting';
const manager = new ObservabilityHostingManager();
manager.configure(adapter, { enableBaggage: true });
The middleware skips baggage setup for async replies (ContinueConversation events) to avoid overwriting baggage that the originating request already set.
Register BaggageTurnMiddleware on the adapter. It automatically extracts caller, agent, tenant, channel, and conversation details from every incoming ITurnContext and wraps the request in a baggage scope.
using Microsoft.Agents.A365.Observability.Hosting.Middleware;
adapter.Use(new BaggageTurnMiddleware());
The middleware skips baggage setup for async replies (ContinueConversation events) to avoid overwriting baggage that the originating request already set.
If you need HTTP-level baggage (for example, to set tenant and agent IDs before the Bot Framework pipeline runs), register ObservabilityBaggageMiddleware in the ASP.NET Core pipeline by using the UseObservabilityRequestContext extension method. You must provide a resolver function that extracts the tenant ID and agent ID from the HTTP context.
using Microsoft.Agents.A365.Observability.Hosting.Middleware;
app.UseObservabilityRequestContext((httpContext) =>
{
// Extract tenant and agent IDs from your request context
var tenantId = GetTenantIdFromContext(httpContext);
var agentId = GetAgentIdFromContext(httpContext);
return (tenantId, agentId);
});
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(),
)
The following snippet shows how to generate a token by using the @microsoft/agents-hosting 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.
import {
TurnState,
AgentApplication,
MemoryStorage,
TurnContext,
} from '@microsoft/agents-hosting';
import { ActivityTypes } from '@microsoft/agents-activity';
import { getObservabilityAuthenticationScope } from '@microsoft/agents-a365-runtime';
interface ConversationState {
count: number;
}
type ApplicationTurnState = TurnState<ConversationState>;
const storage = new MemoryStorage();
export const agentApplication = new AgentApplication<ApplicationTurnState>({
authorization: {
agentic: {}, // We have the type and scopes set in the .env file
},
storage,
});
agentApplication.onActivity(
ActivityTypes.Message,
async (context: TurnContext, state: ApplicationTurnState) => {
const aauAuthToken = await agentApplication.authorization.exchangeToken(context, 'agentic', {
scopes: getObservabilityAuthenticationScope()
});
// 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/agents-a365-observability-hosting package, use AgenticTokenCacheInstance to handle token caching automatically. Call RefreshObservabilityToken once per agent and tenant during an activity handler, and pass AgenticTokenCacheInstance.getObservabilityToken as the tokenResolver in your observability configuration.
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { AgenticTokenCacheInstance } from '@microsoft/agents-a365-observability-hosting';
import { getObservabilityAuthenticationScope } from '@microsoft/agents-a365-runtime';
// Use the cache as your token resolver in configure()
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withTokenResolver((agentId, tenantId) =>
AgenticTokenCacheInstance.getObservabilityToken(agentId, tenantId)
)
);
builder.start();
agentApplication.onActivity(
ActivityTypes.Message,
async (context: TurnContext, state: ApplicationTurnState) => {
const agentId = context.activity.recipient?.agenticAppId || '';
const tenantId = context.activity.recipient?.tenantId || '';
await AgenticTokenCacheInstance.RefreshObservabilityToken(
agentId,
tenantId,
context,
agentApplication.authorization,
getObservabilityAuthenticationScope()
);
}
);
The following snippet shows how to generate a token by using the Microsoft.Agents hosting SDK. Use the auth token you generate 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.
Provide a token resolver by registering Agent365ExporterOptions with a TokenResolver Delegate. The delegate receives the agentId and tenantId and returns an authentication token.
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Exporters;
builder.Services.AddSingleton(sp =>
{
return new Agent365ExporterOptions
{
TokenResolver = async (agentId, tenantId) =>
{
// Implement your token retrieval logic here
return await GetTokenAsync(agentId, tenantId);
}
};
});
For an agent built with the A365 CLI that uses an AI teammate and the Microsoft.Agents.A365.Observability.Hosting NuGet package, use the AddAgenticTracingExporter() method to handle token caching automatically through dependency injection.
using Microsoft.Agents.A365.Observability.Hosting;
builder.Services.AddAgenticTracingExporter();
In the agent application, register the token.
using Microsoft.Agents.Builder;
using Microsoft.Agents.Builder.App.UserAuth;
using Microsoft.Extensions.Logging;
using Microsoft.Agents.A365.Observability.Hosting.Caching;
using Microsoft.Agents.A365.Observability.Runtime.Common;
using System;
using System.Threading.Tasks;
public class MyAgent : AgentApplication
{
private readonly IExporterTokenCache<AgenticTokenStruct> _agentTokenCache;
private readonly ILogger<MyAgent> _logger;
public MyAgent(AgentApplicationOptions options, IExporterTokenCache<AgenticTokenStruct> agentTokenCache, ILogger<MyAgent> logger)
: base(options)
{
_agentTokenCache = agentTokenCache ?? throw new ArgumentNullException(nameof(agentTokenCache));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
protected async Task MessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
using var baggageScope = new BaggageBuilder()
.TenantId(turnContext.Activity.Recipient.TenantId)
.AgentId(turnContext.Activity.Recipient.AgenticAppId)
.Build();
try
{
_agentTokenCache.RegisterObservability(
turnContext.Activity.Recipient.AgenticAppId,
turnContext.Activity.Recipient.TenantId,
new AgenticTokenStruct(
userAuthorization: UserAuthorization,
turnContext: turnContext,
authHandlerName: "AGENTIC"
),
EnvironmentUtils.GetObservabilityAuthenticationScope()
);
}
catch (Exception ex)
{
_logger.LogWarning($"Error registering for observability: {ex.Message}");
}
}
}
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:
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
Semantic Kernel isn't supported with JavaScript.
Add dependencies to the service collection.
using Microsoft.Agents.A365.Observability.Extensions.SemanticKernel;
builder.AddA365Tracing(configure: config => config.WithSemanticKernel());
Set AgentId and TenantId by using BaggageBuilder. Ensure that the ID you use when creating a ChatCompletionAgent matches the agent ID you pass to BaggageBuilder.
using Microsoft.Agents.A365.Observability.Extensions.SemanticKernel;
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent
{
public async Task<AgentResponse> ProcessUserRequest(string userInput)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
var chatCompletionAgent = new ChatCompletionAgent
{
// NOTE: This will be the agent ID with which the TokenResolver delegate is invoked. Should match above.
Id = <your-agent-id>,
...
};
}
}
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
Install the package.
npm install @microsoft/agents-a365-observability-extensions-openai
Configure observability.
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { OpenAIAgentsTraceInstrumentor } from '@microsoft/agents-a365-observability-extensions-openai';
// Configure observability first
const sdk = ObservabilityManager.configure((builder) =>
builder
.withService('My Agent Service', '1.0.0')
);
// Create and enable the instrumentor
const instrumentor = new OpenAIAgentsTraceInstrumentor({
enabled: true,
tracerName: 'openai-agents-tracer',
tracerVersion: '1.0.0'
});
sdk.start();
instrumentor.enable();
Add dependencies to the service collection.
using Microsoft.Agents.A365.Observability.Extensions.OpenAI;
builder.AddA365Tracing(configure: config => config.WithOpenAI());
Set AgentId and TenantId by using BaggageBuilder. For tool calls, start a trace by using Trace() on a ChatToolCall instance.
using Microsoft.Agents.A365.Observability.Extensions.OpenAI;
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent
{
public async Task<AgentResponse> ProcessUserRequest(string userInput)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
// NOTE: This will be the agent and tenant ID with which the TokenResolver delegate will be invoked.
using var scope = chatToolCall.Trace(agentId: <your-agent-id>, <your-tenant-id>);
}
}
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()
Agent Framework isn't supported with JavaScript.
Add dependencies to the service collection.
using Microsoft.Agents.A365.Observability.Extensions.AgentFramework;
builder.AddA365Tracing(configure: config => config.WithAgentFramework());
Set AgentId and TenantId by using BaggageBuilder.
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent : AgentApplication
{
protected async Task MessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
}
}
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
Install the package.
npm install @microsoft/agents-a365-observability-extensions-langchain
Configure observability.
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { LangChainTraceInstrumentor } from '@microsoft/agents-a365-observability-extensions-langchain';
import * as LangChainCallbacks from '@langchain/core/callbacks/manager';
// Configure observability first
const sdk = ObservabilityManager.configure((builder) =>
builder
.withService('My Agent Service', '1.0.0')
);
sdk.start();
// Enable LangChain auto-instrumentation
LangChainTraceInstrumentor.instrument(LangChainCallbacks);
// Your LangChain code is now automatically traced
LangChain isn't supported with .NET.
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.