Share via


AgentApplication class

Main application class for handling agent conversations and routing.

Remarks

The AgentApplication class provides a framework for building conversational agents. It handles routing activities to appropriate handlers, manages conversation state, supports authentication flows, and provides various event handling capabilities.

Key features:

  • Activity routing based on type, content, or custom selectors - State management with automatic load/save - OAuth authentication support - Typing indicators and long-running message support - Extensible architecture with custom extensions - Event handlers for before/after turn processing Example
  storage: new MemoryStorage(),
  adapter: myAdapter
});
app.onMessage('hello', async (context, state) => {
  await context.sendActivity('Hello there!');
});
await app.run(turnContext); ```

Constructors

AgentApplication<TState>(Partial<AgentApplicationOptions<TState>>)

Example

const app = new AgentApplication({
  storage: new MemoryStorage(),
  adapter: myAdapter,
  startTypingTimer: true,
  authorization: { connectionName: 'oauth' },
  transcriptLogger: myTranscriptLogger,
});

Properties

adapter
adaptiveCards

Example

app.adaptiveCards.actionSubmit('doStuff', async (context, state, data) => {
  await context.sendActivity(`Received data: ${JSON.stringify(data)}`);
});
authorization
options

Methods

addRoute(Selector, RouteHandler<TState>, boolean, number, string[])

Adds a new route to the application for handling activities.

Example

app.addRoute(
  async (context) => context.activity.type === ActivityTypes.Message,
  async (context, state) => {
    await context.sendActivity('I received your message');
  },
  false, // isInvokeRoute
  RouteRank.First // rank
);
onActivity(string | RegExp | Selector | (string | RegExp | Selector)[], (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for specific activity types.

Example

app.onActivity(ActivityTypes.Message, async (context, state) => {
  await context.sendActivity('I received your message');
});
onConversationUpdate(ConversationUpdateEvents, (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for conversation update events.

Example

app.onConversationUpdate('membersAdded', async (context, state) => {
  const membersAdded = context.activity.membersAdded;
  for (const member of membersAdded) {
    if (member.id !== context.activity.recipient.id) {
      await context.sendActivity('Hello and welcome!');
    }
  }
});
onError((context: TurnContext, error: Error) => Promise<void>)

Sets an error handler for the application.

Example

app.onError(async (context, error) => {
  console.error(`An error occurred: ${error.message}`);
  await context.sendActivity('Sorry, something went wrong!');
});
onMessage(string | RegExp | Selector | (string | RegExp | Selector)[], (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for message activities that match the specified keyword or pattern.

Example

app.onMessage('hello', async (context, state) => {
  await context.sendActivity('Hello there!');
});

app.onMessage(/help/i, async (context, state) => {
  await context.sendActivity('How can I help you?');
});
onMessageReactionAdded((context: TurnContext, state: TState) => Promise<void>, RouteRank)

Adds a handler for message reaction added events.

Example

app.onMessageReactionAdded(async (context, state) => {
  const reactionsAdded = context.activity.reactionsAdded;
  if (reactionsAdded && reactionsAdded.length > 0) {
    await context.sendActivity(`Thanks for your ${reactionsAdded[0].type} reaction!`);
  }
});
onMessageReactionRemoved((context: TurnContext, state: TState) => Promise<void>, RouteRank)

Adds a handler for message reaction removed events.

Example

app.onMessageReactionRemoved(async (context, state) => {
  const reactionsRemoved = context.activity.reactionsRemoved;
  if (reactionsRemoved && reactionsRemoved.length > 0) {
    await context.sendActivity(`You removed your ${reactionsRemoved[0].type} reaction.`);
  }
});
onSignInFailure((context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>)

Sets a handler to be called when a sign-in attempt fails.

Example

app.onSignInFailure(async (context, state) => {
  await context.sendActivity('Sign-in failed. Please try again.');
});
onSignInSuccess((context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>)

Sets a handler to be called when a user successfully signs in.

Example

app.onSignInSuccess(async (context, state) => {
  await context.sendActivity('You have successfully signed in!');
});
onTurn(TurnEvents | TurnEvents[], (context: TurnContext, state: TState) => Promise<boolean>)

Adds an event handler for specified turn events.

Example

app.onTurn('beforeTurn', async (context, state) => {
  console.log('Processing before turn');
  return true; // Continue execution
});
registerExtension<T>(T, (ext: T) => void)

Registers an extension with the application.

Example

const myExtension = new MyCustomExtension();
app.registerExtension(myExtension, (ext) => {
  console.log('Extension registered:', ext.name);
});
run(TurnContext)

Executes the application logic for a given turn context.

Example

const app = new AgentApplication();
await app.run(turnContext);
runInternal(TurnContext)

Executes the application logic for a given turn context.

Example

const handled = await app.runInternal(turnContext);
if (!handled) {
  console.log('No handler matched the activity');
}
sendProactiveActivity(TurnContext | ConversationReference, string | Activity, string, string)

Sends a proactive message to a conversation.

Example

// With conversation reference
await app.sendProactiveActivity(conversationReference, 'Important notification!');

// From an existing context
await app.sendProactiveActivity(turnContext, 'Important notification!');
startTypingTimer(TurnContext)

Starts a typing indicator timer for the current turn context.

Example

app.startTypingTimer(turnContext);
// Do some processing...
await turnContext.sendActivity('Response after processing');
// Typing timer automatically stops when sending a message
stopTypingTimer()

Stops the typing indicator timer if it's currently running.

Example

app.startTypingTimer(turnContext);
// Do some processing...
app.stopTypingTimer(); // Manually stop the typing indicator

Constructor Details

AgentApplication<TState>(Partial<AgentApplicationOptions<TState>>)

Example

const app = new AgentApplication({
  storage: new MemoryStorage(),
  adapter: myAdapter,
  startTypingTimer: true,
  authorization: { connectionName: 'oauth' },
  transcriptLogger: myTranscriptLogger,
});
new AgentApplication(options?: Partial<AgentApplicationOptions<TState>>)

Parameters

options

Partial<AgentApplicationOptions<TState>>

Optional configuration options for the application.

Remarks

The constructor initializes the application with default settings and applies any provided options. It sets up the adapter, authorization, and other core components based on the configuration.

Default options:

  • startTypingTimer: false
  • longRunningMessages: false
  • removeRecipientMention: true
  • turnStateFactory: Creates a new TurnState instance

Property Details

adapter

BaseAdapter adapter

Property Value

The adapter instance.

adaptiveCards

Example

app.adaptiveCards.actionSubmit('doStuff', async (context, state, data) => {
  await context.sendActivity(`Received data: ${JSON.stringify(data)}`);
});
AdaptiveCardsActions<TState> adaptiveCards

Property Value

The adaptive cards actions instance.

authorization

Authorization authorization

Property Value

The authorization instance.

options

AgentApplicationOptions<TState> options

Property Value

The application options.

Method Details

addRoute(Selector, RouteHandler<TState>, boolean, number, string[])

Adds a new route to the application for handling activities.

Example

app.addRoute(
  async (context) => context.activity.type === ActivityTypes.Message,
  async (context, state) => {
    await context.sendActivity('I received your message');
  },
  false, // isInvokeRoute
  RouteRank.First // rank
);
function addRoute(selector: Selector, handler: RouteHandler<TState>, isInvokeRoute?: boolean, rank?: number, authHandlers?: string[]): AgentApplication<TState>

Parameters

selector
Selector

The selector function that determines if a route should handle the current activity.

handler

RouteHandler<TState>

The handler function that will be called if the selector returns true.

isInvokeRoute

boolean

Whether this route is for invoke activities. Defaults to false.

rank

number

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

authHandlers

string[]

Array of authentication handler names for this route. Defaults to empty array.

Returns

The current instance of the application.

Remarks

Routes are evaluated by rank order (if provided), otherwise, in the order they are added. Invoke-based activities receive special treatment and are matched separately as they typically have shorter execution timeouts.

onActivity(string | RegExp | Selector | (string | RegExp | Selector)[], (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for specific activity types.

Example

app.onActivity(ActivityTypes.Message, async (context, state) => {
  await context.sendActivity('I received your message');
});
function onActivity(type: string | RegExp | Selector | (string | RegExp | Selector)[], handler: (context: TurnContext, state: TState) => Promise<void>, authHandlers?: string[], rank?: RouteRank): AgentApplication<TState>

Parameters

type

string | RegExp | Selector | (string | RegExp | Selector)[]

The activity type(s) to handle. Can be a string, RegExp, RouteSelector, or array of these types.

handler

(context: TurnContext, state: TState) => Promise<void>

The handler function that will be called when the specified activity type is received.

authHandlers

string[]

Array of authentication handler names for this activity. Defaults to empty array.

rank
RouteRank

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

Returns

The current instance of the application.

Remarks

This method allows you to register handlers for specific activity types such as 'message', 'conversationUpdate', etc. You can specify multiple activity types by passing an array.

onConversationUpdate(ConversationUpdateEvents, (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for conversation update events.

Example

app.onConversationUpdate('membersAdded', async (context, state) => {
  const membersAdded = context.activity.membersAdded;
  for (const member of membersAdded) {
    if (member.id !== context.activity.recipient.id) {
      await context.sendActivity('Hello and welcome!');
    }
  }
});
function onConversationUpdate(event: ConversationUpdateEvents, handler: (context: TurnContext, state: TState) => Promise<void>, authHandlers?: string[], rank?: RouteRank): AgentApplication<TState>

Parameters

event
ConversationUpdateEvents

The conversation update event to handle (e.g., 'membersAdded', 'membersRemoved').

handler

(context: TurnContext, state: TState) => Promise<void>

The handler function that will be called when the specified event occurs.

authHandlers

string[]

Array of authentication handler names for this event. Defaults to empty array.

rank
RouteRank

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

Returns

The current instance of the application.

Remarks

Conversation update events occur when the state of a conversation changes, such as when members join or leave.

onError((context: TurnContext, error: Error) => Promise<void>)

Sets an error handler for the application.

Example

app.onError(async (context, error) => {
  console.error(`An error occurred: ${error.message}`);
  await context.sendActivity('Sorry, something went wrong!');
});
function onError(handler: (context: TurnContext, error: Error) => Promise<void>): AgentApplication<TState>

Parameters

handler

(context: TurnContext, error: Error) => Promise<void>

The error handler function to be called when an error occurs.

Returns

The current instance of the application.

Remarks

This method allows you to handle any errors that occur during turn processing. The handler will receive the turn context and the error that occurred.

onMessage(string | RegExp | Selector | (string | RegExp | Selector)[], (context: TurnContext, state: TState) => Promise<void>, string[], RouteRank)

Adds a handler for message activities that match the specified keyword or pattern.

Example

app.onMessage('hello', async (context, state) => {
  await context.sendActivity('Hello there!');
});

app.onMessage(/help/i, async (context, state) => {
  await context.sendActivity('How can I help you?');
});
function onMessage(keyword: string | RegExp | Selector | (string | RegExp | Selector)[], handler: (context: TurnContext, state: TState) => Promise<void>, authHandlers?: string[], rank?: RouteRank): AgentApplication<TState>

Parameters

keyword

string | RegExp | Selector | (string | RegExp | Selector)[]

The keyword, pattern, or selector function to match against message text. Can be a string, RegExp, RouteSelector, or array of these types.

handler

(context: TurnContext, state: TState) => Promise<void>

The handler function that will be called when a matching message is received.

authHandlers

string[]

Array of authentication handler names for this message handler. Defaults to empty array.

rank
RouteRank

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

Returns

The current instance of the application.

Remarks

This method allows you to register handlers for specific message patterns. If keyword is a string, it matches messages containing that string. If keyword is a RegExp, it tests the message text against the regular expression. If keyword is a function, it calls the function with the context to determine if the message matches.

onMessageReactionAdded((context: TurnContext, state: TState) => Promise<void>, RouteRank)

Adds a handler for message reaction added events.

Example

app.onMessageReactionAdded(async (context, state) => {
  const reactionsAdded = context.activity.reactionsAdded;
  if (reactionsAdded && reactionsAdded.length > 0) {
    await context.sendActivity(`Thanks for your ${reactionsAdded[0].type} reaction!`);
  }
});
function onMessageReactionAdded(handler: (context: TurnContext, state: TState) => Promise<void>, rank?: RouteRank): AgentApplication<TState>

Parameters

handler

(context: TurnContext, state: TState) => Promise<void>

The handler function that will be called when a message reaction is added.

rank
RouteRank

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

Returns

The current instance of the application.

Remarks

This method registers a handler that will be invoked when a user adds a reaction to a message, such as a like, heart, or other emoji reaction.

onMessageReactionRemoved((context: TurnContext, state: TState) => Promise<void>, RouteRank)

Adds a handler for message reaction removed events.

Example

app.onMessageReactionRemoved(async (context, state) => {
  const reactionsRemoved = context.activity.reactionsRemoved;
  if (reactionsRemoved && reactionsRemoved.length > 0) {
    await context.sendActivity(`You removed your ${reactionsRemoved[0].type} reaction.`);
  }
});
function onMessageReactionRemoved(handler: (context: TurnContext, state: TState) => Promise<void>, rank?: RouteRank): AgentApplication<TState>

Parameters

handler

(context: TurnContext, state: TState) => Promise<void>

The handler function that will be called when a message reaction is removed.

rank
RouteRank

The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.

Returns

The current instance of the application.

Remarks

This method registers a handler that will be invoked when a user removes a reaction from a message, such as unliking or removing an emoji reaction.

onSignInFailure((context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>)

Sets a handler to be called when a sign-in attempt fails.

Example

app.onSignInFailure(async (context, state) => {
  await context.sendActivity('Sign-in failed. Please try again.');
});
function onSignInFailure(handler: (context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>): AgentApplication<TState>

Parameters

handler

(context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>

The handler function to be called after a failed sign-in attempt.

Returns

The current instance of the application.

Remarks

This method allows you to handle cases where a user fails to authenticate, such as when they cancel the sign-in process or an error occurs.

onSignInSuccess((context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>)

Sets a handler to be called when a user successfully signs in.

Example

app.onSignInSuccess(async (context, state) => {
  await context.sendActivity('You have successfully signed in!');
});
function onSignInSuccess(handler: (context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>): AgentApplication<TState>

Parameters

handler

(context: TurnContext, state: TurnState<DefaultConversationState, DefaultUserState, DefaultTempState>, id?: string) => Promise<void>

The handler function to be called after successful sign-in.

Returns

The current instance of the application.

Remarks

This method allows you to perform actions after a user has successfully authenticated. The handler will receive the turn context and state.

onTurn(TurnEvents | TurnEvents[], (context: TurnContext, state: TState) => Promise<boolean>)

Adds an event handler for specified turn events.

Example

app.onTurn('beforeTurn', async (context, state) => {
  console.log('Processing before turn');
  return true; // Continue execution
});
function onTurn(event: TurnEvents | TurnEvents[], handler: (context: TurnContext, state: TState) => Promise<boolean>): AgentApplication<TState>

Parameters

event

TurnEvents | TurnEvents[]

The turn event(s) to handle. Can be 'beforeTurn', 'afterTurn', or other custom events.

handler

(context: TurnContext, state: TState) => Promise<boolean>

The handler function that will be called when the event occurs.

Returns

The current instance of the application.

Remarks

Turn events allow you to execute logic before or after the main turn processing. Handlers added for 'beforeTurn' are executed before routing logic. Handlers added for 'afterTurn' are executed after routing logic.

registerExtension<T>(T, (ext: T) => void)

Registers an extension with the application.

Example

const myExtension = new MyCustomExtension();
app.registerExtension(myExtension, (ext) => {
  console.log('Extension registered:', ext.name);
});
function registerExtension<T>(extension: T, regcb: (ext: T) => void)

Parameters

extension

T

The extension instance to register.

regcb

(ext: T) => void

Callback function called after successful registration.

Remarks

Extensions provide a way to add custom functionality to the application. Each extension can only be registered once to prevent conflicts.

run(TurnContext)

Executes the application logic for a given turn context.

Example

const app = new AgentApplication();
await app.run(turnContext);
function run(turnContext: TurnContext): Promise<void>

Parameters

turnContext
TurnContext

The context for the current turn of the conversation.

Returns

Promise<void>

A promise that resolves when the application logic has completed.

Remarks

This method is the entry point for processing a turn in the conversation. It delegates the actual processing to the runInternal method, which handles the core logic for routing and executing handlers.

runInternal(TurnContext)

Executes the application logic for a given turn context.

Example

const handled = await app.runInternal(turnContext);
if (!handled) {
  console.log('No handler matched the activity');
}
function runInternal(turnContext: TurnContext): Promise<boolean>

Parameters

turnContext
TurnContext

The context for the current turn of the conversation.

Returns

Promise<boolean>

A promise that resolves to true if a handler was executed, false otherwise.

Remarks

This is the core internal method that processes a turn in the conversation. It handles routing and executing handlers based on the activity type and content. While this method is public, it's typically called internally by the run method.

The method performs the following operations:

  1. Starts typing timer if configured
  2. Processes mentions if configured
  3. Loads turn state
  4. Handles authentication flows
  5. Executes before-turn event handlers
  6. Downloads files if file downloaders are configured
  7. Routes to appropriate handlers
  8. Executes after-turn event handlers
  9. Saves turn state

sendProactiveActivity(TurnContext | ConversationReference, string | Activity, string, string)

Sends a proactive message to a conversation.

Example

// With conversation reference
await app.sendProactiveActivity(conversationReference, 'Important notification!');

// From an existing context
await app.sendProactiveActivity(turnContext, 'Important notification!');
function sendProactiveActivity(context: TurnContext | ConversationReference, activityOrText: string | Activity, speak?: string, inputHint?: string): Promise<undefined | ResourceResponse>

Parameters

context

TurnContext | ConversationReference

The turn context or conversation reference to use.

activityOrText

string | Activity

The activity or text to send.

speak

string

Optional text to be spoken by the bot on a speech-enabled channel.

inputHint

string

Optional input hint for the activity.

Returns

Promise<undefined | ResourceResponse>

A promise that resolves to the resource response from sending the activity.

Remarks

This method allows you to send messages proactively to a conversation, outside the normal turn flow.

startTypingTimer(TurnContext)

Starts a typing indicator timer for the current turn context.

Example

app.startTypingTimer(turnContext);
// Do some processing...
await turnContext.sendActivity('Response after processing');
// Typing timer automatically stops when sending a message
function startTypingTimer(context: TurnContext)

Parameters

context
TurnContext

The turn context for the current conversation.

Remarks

This method starts a timer that sends typing activity indicators to the user at regular intervals. The typing indicator continues until a message is sent or the timer is explicitly stopped.

The typing indicator helps provide feedback to users that the agent is processing their message, especially when responses might take time to generate.

stopTypingTimer()

Stops the typing indicator timer if it's currently running.

Example

app.startTypingTimer(turnContext);
// Do some processing...
app.stopTypingTimer(); // Manually stop the typing indicator
function stopTypingTimer()

Remarks

This method clears the typing indicator timer to prevent further typing indicators from being sent. It's typically called automatically when a message is sent, but can also be called manually to stop the typing indicator.