Skip to content

v1.5

Choose a tag to compare

@benbrown benbrown released this 29 Apr 17:31
· 2 commits to release/v1.5 since this release

Major updates in this version:

  • OpenTelemetry support — the SDK has been fully instrumented for oTel
  • Proactive messaging improvements — new methods and helpers for sending proactive messages
  • Improvements to "typing" behavior
  • New format for oAuth environment variable names

New: OpenTelemetry Support (@microsoft/agents-telemetry)

Version 1.5 introduces @microsoft/agents-telemetry — a new package providing distributed tracing, structured log emission, and metric recording across the entire SDK.

All major SDK components are now instrumented out of the box: turn processing, HTTP connector calls, storage reads/writes, authentication flows, dialog execution, and Copilot Studio client operations.
Telemetry is zero-overhead by default — if you don't install the OpenTelemetry API packages, all instrumentation paths are safe no-ops.

Getting started

Install the peer dependencies in your agent project:

npm install @opentelemetry/api @opentelemetry/api-logs

Set up a provider early in your application entry point (before any SDK code runs):

import { NodeSDK } from '@opentelemetry/sdk-node'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
  }),
  serviceName: 'my-agent-service',
})

sdk.start()

See the full README for the complete span/metric catalog and advanced usage (custom spans, metrics, log bridging).

New: Proactive Messaging via AgentApplication

The proactive messaging subsystem is now a first-class part of AgentApplication, accessible via app.proactive. It is initialized automatically when your app has a storage configured — no extra setup required.

Store a conversation reference during a live turn

Call storeConversation inside any activity handler. It saves the conversation reference to storage and returns its ID for later use.

app.onActivity('message', async (ctx, state) => {
    const convId = await app.proactive.storeConversation(ctx)
    await ctx.sendActivity(`Conversation stored. ID: ${convId}`)
})

Send a proactive message by stored ID

From a webhook, scheduled job, or any out-of-turn code:

await app.proactive.sendActivity(adapter, convId, { text: 'Your report is ready.' })

Continue a full conversation turn (with state)

Use continueConversation when you need access to TurnState, the full handler pipeline, or want to send more than one activity:

await app.proactive.continueConversation(adapter, convId, async (ctx, state) => {
   const count = state.getValue<number>('conversation.notificationCount') ?? 0
   state.setValue('conversation.notificationCount', count + 1)
   await ctx.sendActivity(`Notification #${count + 1}: threshold exceeded.`)
})

Create a brand-new conversation

Use createConversation to initiate a 1:1 conversation with a Teams user who has never messaged your agent. Build the options with CreateConversationOptionsBuilder:

import { CreateConversationOptionsBuilder } from '@microsoft/agents-hosting'

const opts = CreateConversationOptionsBuilder
   .create(process.env.CLIENT_ID!, 'msteams')
   .withUser('user-aad-object-id')
   .withTenantId('tenant-id')
   .storeConversation(true)   // auto-store so you can retrieve it later
   .build()

const conv = await app.proactive.createConversation(adapter, opts, async (ctx, state) => {
   await ctx.sendActivity('Hi! I have an update for you.')
})

Build a ConversationReference from scratch

When you need to construct a reference from external data (e.g. from a database record) rather than from a live turn, use ConversationReferenceBuilder:

import { ConversationReferenceBuilder, TeamsServiceEndpoints } from '@microsoft/agents-hosting'

const ref = ConversationReferenceBuilder
   .create(process.env.CLIENT_ID!, 'msteams')
   .withUser('user-aad-object-id')
   .withConversationId('19:existing-thread-id@thread.tacv2')
   .withServiceUrl(TeamsServiceEndpoints.publicGlobal)
   .build()

See the proactive-agent test agent for more examples, including a sample RESTful API for triggering proactive messages externally.

Fix: Typing indicator timer scoped per turn context (#1016)

The startTypingTimer in AgentApplication previously used a single shared timer variable at the class level, which could cause typing indicators to interfere across concurrent turns. The timer state is now stored on the TurnContext so each turn manages its own independent typing loop.

A new typing option is available on AgentApplicationOptions to configure timing behavior:

new AgentApplicationBuilder()
   .withTyping({
        initialDelayMs: 0,       // delay before first typing indicator (default: 0ms)
        intervalMs: 4000,         // interval between subsequent indicators (default: 4s)
        channelStrategies: {
          'webchat': { intervalMs: 3000 }  // per-channel overrides
        }
      }
    })
    .build()

Change: Auth handler environment variable naming aligned with .NET/Python** (#872)

The environment variable format for configuring OAuth authorization handlers has been updated to match the conventions used in the .NET and Python SDKs.

Format Example
Legacy <handlerId>_<property> graph_connectionName
New AgentApplication__UserAuthorization__Handlers__<handlerId>__Settings__<property> AgentApplication__UserAuthorization__Handlers__graph__Settings__azureBotOAuthConnectionName

The legacy format is still supported for backward compatibility, and matching is case-insensitive for handler IDs. Legacy property names are also remapped to their new equivalents (e.g. connectionNameazureBotOAuthConnectionName, maxAttemptsinvalidSignInRetryMax).

Legacy name New name
connectionName azureBotOAuthConnectionName
connectionTitle title
connectionText text
messages_invalidCode invalidSignInRetryMessage
messages_invalidCodeFormat invalidSignInRetryMessageFormat
messages_maxAttemptsExceeded invalidSignInRetryMaxExceededMessage
maxAttempts invalidSignInRetryMax
enableSso enableSso
obo_connection oboConnectionName
obo_scopes oboScopes

If you are configuring auth handlers via environment variables, update your .env files to use the new format. The legacy format may be removed in a future release.

Full list of changes

Full Changelog: v1.4...v1.5