@microsoft/agents-a365-observability package

Classes

Agent365ExporterOptions

Options controlling the behavior of the Agent365 OpenTelemetry span exporter.

These values tune batching, timeouts, token acquisition and endpoint shape. All properties have sensible defaults so callers can usually construct without arguments and override selectively.

ApplyGuardrailScope

Provides OpenTelemetry tracing scope for security guardrail evaluation operations.

Describes a security guardian evaluation. Multiple guardian spans MAY exist under a single operation span if multiple guardians are chained.

Guardian spans SHOULD be children of the operation span they are protecting (e.g., inference or execute_tool spans).

BaggageBuilder

Per request baggage builder for OpenTelemetry context propagation.

This class provides a fluent API for setting baggage values that will be propagated in the OpenTelemetry context.

Example

const scope = new BaggageBuilder()
  .tenantId("tenant-123")
  .agentId("agent-456")
  .build();

scope.enter();
// Baggage is set in this context
// ... do work ...
scope.exit();
// Baggage is restored after exiting the context
BaggageScope

Context manager for baggage scope.

This class manages the lifecycle of baggage values, setting them on enter and restoring the previous context on exit.

Builder

Builder for configuring Agent 365 with OpenTelemetry tracing

ExecuteToolScope

Provides OpenTelemetry tracing scope for AI tool execution operations.

InferenceScope

Provides OpenTelemetry tracing scope for generative AI inference operations.

InvokeAgentScope

Provides OpenTelemetry tracing scope for AI agent invocation operations.

ObservabilityConfiguration

Configuration for observability package. Inherits runtime settings and adds observability-specific settings.

ObservabilityManager

Main entry point for Agent 365 providing OpenTelemetry tracing for AI agents and tools

OpenTelemetryConstants

OpenTelemetry constants for Agent 365

OpenTelemetryScope

Base class for OpenTelemetry tracing scopes

OutputScope

Provides OpenTelemetry tracing scope for output message tracing with parent span linking.

PerRequestSpanProcessorConfiguration

Configuration for PerRequestSpanProcessor. Inherits runtime settings (clusterCategory, isNodeEnvDevelopment) and adds per-request processor guardrails.

This is separated from ObservabilityConfiguration because PerRequestSpanProcessor is used only in specific scenarios and these settings should not be exposed in the common ObservabilityConfiguration.

Interfaces

AgentDetails

Details about an AI agent

BlobPart

Inline binary data (base64-encoded).

BuilderOptions

Configuration options for Agent 365 Observability Builder

CallerDetails

Caller details for scope creation. Supports human callers, agent callers, or both (A2A with a human in the chain).

Migration note: In v1 the name CallerDetails referred to human caller identity (now UserDetails). In v2 it was repurposed as a wrapper that groups both human and agent caller information.

See UserDetails — human caller identity (previously CallerDetails) See CHANGELOG.md — breaking changes section for migration guidance

Channel

Represents channel for an invocation

ChatMessage

An input message sent to a model (OTEL gen-ai semantic conventions).

FilePart

Reference to a pre-uploaded file.

GenericPart

Extensible part for custom / future types.

GenericServerToolCall

Extensible server tool call details with a type discriminator.

GenericServerToolCallResponse

Extensible server tool call response with a type discriminator.

GuardrailDetails

Details of a guardrail evaluation for security operations tracing.

GuardrailFinding

Represents a single security finding detected during guardian evaluation. Multiple findings may be emitted for a single guardrail span.

ILogger

Custom logger interface for Agent 365 observability Implement this interface to support logging backends

InferenceDetails

Details for an inference call

InferenceResponse

Details for recording the response from an inference call

InputMessages
InvokeAgentScopeDetails

Details for invoking agent scope.

OutputMessage

An output message produced by a model (OTEL gen-ai semantic conventions). finish_reason defaults to "stop" per OTel spec when not provided.

OutputMessages
OutputResponse

Represents a response containing output messages from an agent. Used with OutputScope for output message tracing. Accepts plain strings, structured OTEL OutputMessage objects, or a raw dict (treated as a tool call result per OTEL spec).

ParentSpanRef

Reference to a parent span for explicit parent-child linking across async boundaries. Used when automatic context propagation fails (e.g., WebSocket callbacks, external event handlers).

ReasoningPart

Model reasoning / chain-of-thought content.

Request

Represents a request with telemetry context. Used across all scope types for channel and conversation tracking.

ServerToolCallPart

Server-side tool invocation.

ServerToolCallResponsePart

Server-side tool response.

ServiceEndpoint

Represents an endpoint for agent invocation

SpanDetails

Span configuration details for scope creation. Groups OpenTelemetry span options into a single object so the scope method signature remains stable as new options are added.

TextPart

Plain text content.

ToolCallDetails

Details of a tool call made by an agent

ToolCallRequestPart

A tool call requested by the model.

ToolCallResponsePart

Result of a tool call.

UriPart

External URI reference.

UserDetails

Details about the human user caller.

Type Aliases

EnhancedAgentDetails
HeadersCarrier

Carrier type for HTTP headers used in trace context propagation. Compatible with Node.js IncomingHttpHeaders and plain string maps.

InputMessagesParam

Accepted input for recordInputMessages. Supports a single string, an array of strings (backward compat), or the structured wrapper.

MessagePart

Union of all message part types per OTEL gen-ai semantic conventions.

Note: GenericPart acts as a catch-all for forward compatibility with custom or future part types. Because its type is string (not a literal), exhaustive switch/case on part.type will not produce compile-time errors for unhandled cases.

ObservabilityConfigurationOptions

Observability configuration options - extends runtime options. All overrides are functions called on each property access.

Inherited from RuntimeConfigurationOptions:

  • clusterCategory
  • isNodeEnvDevelopment

Note: isDevelopmentEnvironment is a derived getter on the configuration class (based on clusterCategory), not an overridable option.

OutputMessagesParam

Accepted input for recordOutputMessages. Supports a single string, an array of strings (backward compat), or the structured wrapper.

ParentContext

A parent context for span creation. Accepts either:

PerRequestSpanProcessorConfigurationOptions

Configuration options for PerRequestSpanProcessor - extends runtime options. All overrides are functions called on each property access.

Inherited from RuntimeConfigurationOptions:

  • clusterCategory, isNodeEnvDevelopment
ResponseMessagesParam

Accepted input for OutputResponse.messages. Supports plain strings, structured OutputMessages, or a raw dict (treated as a tool call result per OTEL spec and serialized directly via JSON.stringify).

TokenResolver

A function that resolves an app-only OBS token for the given agent and tenant. Delegated (scp) tokens are not accepted by the S2S service. Implementations may perform synchronous lookup (e.g., in-memory cache) or asynchronous network calls. Used in both batch and per-request modes, independently of workload token context. Return null if a token cannot be provided; export fails without sending an HTTP request.

Enums

ExporterEventNames

Event names used by Agent365Exporter for logging and monitoring. These are low-cardinality event types to ensure efficient monitoring and aggregation.

FinishReason

Reason a model stopped generating per OTEL gen-ai semantic conventions.

GuardrailDecisionType

The decision made by a security guardian during guardrail evaluation.

InferenceOperationType

Represents different operation for types for model inference

InvocationRole

Represents different roles that can invoke an agent

MessageRole

Role of a message participant per OTEL gen-ai semantic conventions.

Modality

Media modality for blob, file, and URI parts.

Functions

createContextWithParentSpanRef(Context, ParentSpanRef)

Creates a new Context with an explicit parent span reference. This allows child spans to be correctly parented even when async context is broken.

extractContextFromHeaders(HeadersCarrier, Context)

Extracts trace context from incoming HTTP headers using the globally registered W3C propagator. Returns an OTel ParentContext that can be passed to scope classes as a ParentContext.

Example

const parentCtx = extractContextFromHeaders(req.headers);
const scope = InvokeAgentScope.start(request, scopeDetails, agentDetails, undefined, { parentContext: parentCtx });
formatError(unknown)

Format error object for logging with message and stack trace

getExportToken(Context)

Retrieve the per-request export token from a given OTel Context (or the active one).

getLogger()

Get the current logger instance

injectContextToHeaders(Record<string, string>, Context)

Injects the current trace context (traceparent/tracestate headers) into the provided headers object using the globally registered W3C propagator.

Example

const headers: Record<string, string> = {};
injectContextToHeaders(headers);
await fetch('http://service-b/process', { headers });
isPerRequestExportEnabled(IConfigurationProvider<PerRequestSpanProcessorConfiguration>)

Check if per-request export is enabled. Precedence: internal overrides > configuration provider > environment variable. When enabled, the PerRequestSpanProcessor is used instead of BatchSpanProcessor. Credential selection is unchanged: Agent365Exporter uses its app-only token resolver.

normalizeInputMessages(InputMessagesParam)

Normalizes an InputMessagesParam to an InputMessages instance.

  • string / string[] → converted to ChatMessage[] and wrapped
  • InputMessages → returned as-is
normalizeOutputMessages(OutputMessagesParam)

Normalizes an OutputMessagesParam to an OutputMessages instance.

  • string / string[] → converted to OutputMessage[] and wrapped
  • OutputMessages → returned as-is
resetLogger()

Reset to the default console logger (mainly for testing)

runWithExportToken<T>(string, () => T)

Run a function within a Context that carries the per-request export token. This keeps the token only in OTel Context (ALS), never in any registry. These helpers remain available for custom export integrations. Agent365Exporter does not consume this token; configure its app-only tokenResolver in every mode.

The token can be updated later via updateExportToken() before the trace is flushed — useful when the callback is long-running and the original token may expire before export.

runWithExtractedTraceContext<T>(HeadersCarrier, () => T)

Extracts trace context from incoming HTTP headers and runs the callback within that context. Any spans created inside the callback will be parented to the extracted trace.

Example

runWithExtractedTraceContext(req.headers, () => {
  const scope = InvokeAgentScope.start(request, scopeDetails, agentDetails);
  scope.dispose();
});
runWithParentSpanRef<T>(ParentSpanRef, () => T)

Runs a callback function within a context that has an explicit parent span reference. This is useful for creating child spans in async callbacks where context propagation is broken.

safeSerializeToJson(string | Record<string, unknown>, string)

Ensures the value is always a JSON-parseable string.

  • Objects are serialized via JSON.stringify.
  • Strings that are already valid JSON objects/arrays are passed through.
  • All other strings (including bare JSON primitives) are wrapped: { [key]: value }.
serializeMessages(InputMessages | OutputMessages)

Serializes a message wrapper to JSON.

The output is a plain JSON array per OTel gen-ai semantic conventions: [{...}, ...].

The try/catch ensures telemetry recording is non-throwing even when message parts contain non-JSON-serializable values (e.g. BigInt, circular refs).

setLogger(ILogger)

Set a custom logger implementation for the observability SDK

Example with Winston:

import * as winston from 'winston';
import { setLogger } from '@microsoft/agents-a365-observability';

const winstonLogger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

setLogger({
  info: (msg, ...args) => winstonLogger.info(msg, ...args),
  warn: (msg, ...args) => winstonLogger.warn(msg, ...args),
  error: (msg, ...args) => winstonLogger.error(msg, ...args),
  event: (eventType, isSuccess, durationMs, message, details) => {
    // eventType is ExporterEventNames enum value
    winstonLogger.log({ level: isSuccess ? 'info' : 'error', eventType, isSuccess, durationMs, message, ...details });
  }
});
updateExportToken(string)

Update the export token in the active OTel Context. Call this to refresh the token before ending the root span when the original token may have expired during a long-running request.

Must be called within the same async context created by runWithExportToken.

Variables

DEFAULT_FINISH_REASON

Default finish reason applied when none is provided (per OTel spec).

GuardrailRiskSeverity

Well-known severity levels for security risks detected by guardrails.

GuardrailTargetType

Well-known values for the type of content or action a guardrail is applied to. Custom strings are also accepted.

defaultObservabilityConfigurationProvider

Shared default provider for ObservabilityConfiguration.

defaultPerRequestSpanProcessorConfigurationProvider

Shared default provider for PerRequestSpanProcessorConfiguration.

logger

Default logger instance for backward compatibility. Delegates to the global logger which can be replaced via setLogger().

Function Details

createContextWithParentSpanRef(Context, ParentSpanRef)

Creates a new Context with an explicit parent span reference. This allows child spans to be correctly parented even when async context is broken.

function createContextWithParentSpanRef(base: Context, parent: ParentSpanRef): Context

Parameters

base

Context

The base context to extend (typically context.active())

parent
ParentSpanRef

The parent span reference containing traceId and spanId

Returns

Context

A new Context with the parent span set

extractContextFromHeaders(HeadersCarrier, Context)

Extracts trace context from incoming HTTP headers using the globally registered W3C propagator. Returns an OTel ParentContext that can be passed to scope classes as a ParentContext.

Example

const parentCtx = extractContextFromHeaders(req.headers);
const scope = InvokeAgentScope.start(request, scopeDetails, agentDetails, undefined, { parentContext: parentCtx });
function extractContextFromHeaders(headers: HeadersCarrier, baseCtx?: Context): Context

Parameters

headers
HeadersCarrier

The incoming HTTP request headers containing traceparent/tracestate.

baseCtx

Context

Optional base context to extend. Defaults to the active context.

Returns

Context

An OTel Context containing the extracted trace information.

formatError(unknown)

Format error object for logging with message and stack trace

function formatError(error: unknown): string

Parameters

error

unknown

Returns

string

getExportToken(Context)

Retrieve the per-request export token from a given OTel Context (or the active one).

function getExportToken(ctx?: Context): string | undefined

Parameters

ctx

Context

Returns

string | undefined

getLogger()

Get the current logger instance

function getLogger(): ILogger

Returns

injectContextToHeaders(Record<string, string>, Context)

Injects the current trace context (traceparent/tracestate headers) into the provided headers object using the globally registered W3C propagator.

Example

const headers: Record<string, string> = {};
injectContextToHeaders(headers);
await fetch('http://service-b/process', { headers });
function injectContextToHeaders(headers: Record<string, string>, ctx?: Context): Record<string, string>

Parameters

headers

Record<string, string>

Mutable object where trace context headers will be written.

ctx

Context

Optional OTel Context to inject from. Defaults to the active context.

Returns

Record<string, string>

The same headers object, for chaining convenience.

isPerRequestExportEnabled(IConfigurationProvider<PerRequestSpanProcessorConfiguration>)

Check if per-request export is enabled. Precedence: internal overrides > configuration provider > environment variable. When enabled, the PerRequestSpanProcessor is used instead of BatchSpanProcessor. Credential selection is unchanged: Agent365Exporter uses its app-only token resolver.

function isPerRequestExportEnabled(configProvider?: IConfigurationProvider<PerRequestSpanProcessorConfiguration>): boolean

Parameters

configProvider

IConfigurationProvider<PerRequestSpanProcessorConfiguration>

Optional configuration provider. Defaults to defaultPerRequestSpanProcessorConfigurationProvider if not specified.

Returns

boolean

normalizeInputMessages(InputMessagesParam)

Normalizes an InputMessagesParam to an InputMessages instance.

  • string / string[] → converted to ChatMessage[] and wrapped
  • InputMessages → returned as-is
function normalizeInputMessages(param: InputMessagesParam): InputMessages

Parameters

Returns

normalizeOutputMessages(OutputMessagesParam)

Normalizes an OutputMessagesParam to an OutputMessages instance.

  • string / string[] → converted to OutputMessage[] and wrapped
  • OutputMessages → returned as-is
function normalizeOutputMessages(param: OutputMessagesParam): OutputMessages

Parameters

Returns

resetLogger()

Reset to the default console logger (mainly for testing)

function resetLogger()

runWithExportToken<T>(string, () => T)

Run a function within a Context that carries the per-request export token. This keeps the token only in OTel Context (ALS), never in any registry. These helpers remain available for custom export integrations. Agent365Exporter does not consume this token; configure its app-only tokenResolver in every mode.

The token can be updated later via updateExportToken() before the trace is flushed — useful when the callback is long-running and the original token may expire before export.

function runWithExportToken<T>(token: string, fn: () => T): T

Parameters

token

string

fn

() => T

Returns

T

runWithExtractedTraceContext<T>(HeadersCarrier, () => T)

Extracts trace context from incoming HTTP headers and runs the callback within that context. Any spans created inside the callback will be parented to the extracted trace.

Example

runWithExtractedTraceContext(req.headers, () => {
  const scope = InvokeAgentScope.start(request, scopeDetails, agentDetails);
  scope.dispose();
});
function runWithExtractedTraceContext<T>(headers: HeadersCarrier, callback: () => T): T

Parameters

headers
HeadersCarrier

The incoming HTTP request headers containing traceparent/tracestate.

callback

() => T

The function to execute within the extracted context.

Returns

T

The result of the callback.

runWithParentSpanRef<T>(ParentSpanRef, () => T)

Runs a callback function within a context that has an explicit parent span reference. This is useful for creating child spans in async callbacks where context propagation is broken.

function runWithParentSpanRef<T>(parent: ParentSpanRef, callback: () => T): T

Parameters

parent
ParentSpanRef

The parent span reference

callback

() => T

The function to execute with the parent context

Returns

T

The result of the callback

safeSerializeToJson(string | Record<string, unknown>, string)

Ensures the value is always a JSON-parseable string.

  • Objects are serialized via JSON.stringify.
  • Strings that are already valid JSON objects/arrays are passed through.
  • All other strings (including bare JSON primitives) are wrapped: { [key]: value }.
function safeSerializeToJson(value: string | Record<string, unknown>, key: string): string

Parameters

value

string | Record<string, unknown>

The value to serialize.

key

string

The key to use when wrapping a plain string.

Returns

string

serializeMessages(InputMessages | OutputMessages)

Serializes a message wrapper to JSON.

The output is a plain JSON array per OTel gen-ai semantic conventions: [{...}, ...].

The try/catch ensures telemetry recording is non-throwing even when message parts contain non-JSON-serializable values (e.g. BigInt, circular refs).

function serializeMessages(wrapper: InputMessages | OutputMessages): string

Parameters

Returns

string

setLogger(ILogger)

Set a custom logger implementation for the observability SDK

Example with Winston:

import * as winston from 'winston';
import { setLogger } from '@microsoft/agents-a365-observability';

const winstonLogger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

setLogger({
  info: (msg, ...args) => winstonLogger.info(msg, ...args),
  warn: (msg, ...args) => winstonLogger.warn(msg, ...args),
  error: (msg, ...args) => winstonLogger.error(msg, ...args),
  event: (eventType, isSuccess, durationMs, message, details) => {
    // eventType is ExporterEventNames enum value
    winstonLogger.log({ level: isSuccess ? 'info' : 'error', eventType, isSuccess, durationMs, message, ...details });
  }
});
function setLogger(customLogger: ILogger)

Parameters

customLogger
ILogger

The custom logger implementation

updateExportToken(string)

Update the export token in the active OTel Context. Call this to refresh the token before ending the root span when the original token may have expired during a long-running request.

Must be called within the same async context created by runWithExportToken.

function updateExportToken(token: string): boolean

Parameters

token

string

The fresh token to use for export.

Returns

boolean

true if the token was updated successfully, false if no token holder was found.

Variable Details

DEFAULT_FINISH_REASON

Default finish reason applied when none is provided (per OTel spec).

DEFAULT_FINISH_REASON: "stop"

Type

"stop"

GuardrailRiskSeverity

Well-known severity levels for security risks detected by guardrails.

GuardrailRiskSeverity: { Critical: "critical", High: "high", Low: "low", Medium: "medium", None: "none" }

Type

{ Critical: "critical", High: "high", Low: "low", Medium: "medium", None: "none" }

GuardrailTargetType

Well-known values for the type of content or action a guardrail is applied to. Custom strings are also accepted.

GuardrailTargetType: { KnowledgeQuery: "knowledge_query", KnowledgeResult: "knowledge_result", LlmInput: "llm_input", LlmOutput: "llm_output", MemoryRetrieve: "memory_retrieve", MemoryStore: "memory_store", Message: "message", ToolCall: "tool_call", ToolDefinition: "tool_definition" }

Type

{ KnowledgeQuery: "knowledge_query", KnowledgeResult: "knowledge_result", LlmInput: "llm_input", LlmOutput: "llm_output", MemoryRetrieve: "memory_retrieve", MemoryStore: "memory_store", Message: "message", ToolCall: "tool_call", ToolDefinition: "tool_definition" }

defaultObservabilityConfigurationProvider

Shared default provider for ObservabilityConfiguration.

defaultObservabilityConfigurationProvider: DefaultConfigurationProvider<ObservabilityConfiguration>

Type

defaultPerRequestSpanProcessorConfigurationProvider

Shared default provider for PerRequestSpanProcessorConfiguration.

defaultPerRequestSpanProcessorConfigurationProvider: DefaultConfigurationProvider<PerRequestSpanProcessorConfiguration>

Type

logger

Default logger instance for backward compatibility. Delegates to the global logger which can be replaced via setLogger().

logger: ILogger

Type