Activity processing

APPLIES TO: SDK v4

The bot and user interact and exchange information via activities. Each activity received by your bot application is passed to a bot adapter, which passes activity information to your bot logic and ultimately sends any responses to the user. Receiving an activity, and subsequently processing it through your bot, is called a turn; this represents one complete cycle of your bot. A turn ends when all execution is done, the activity is fully processed and all the layers of the bot have completed.

Activities, particularly those that are sent from a bot during a bot turn, are handled asynchronously. It's a necessary part of building a bot; if you need to brush up on how that all works, check out async for .NET or async for JavaScript depending on your language choice.

The bot adapter

The bot adapter encapsulates authentication processes and sends activities to and receives activities from the Bot Connector Service. When your bot receives an activity, the adapter wraps up everything about that activity, creates a context object for the turn, passes it to your bot's application logic, and sends responses generated by your bot back to the user's channel.

Authentication

The adapter authenticates each incoming activity the application receives, using information from the activity and the Authentication header from the REST request. The adapter uses a connector object and your application's credentials to authenticate the outbound activities to the user.

Bot Connector Service authentication uses JWT (JSON Web Token) Bearer tokens and the Microsoft app ID and Microsoft app password that Azure creates for you when you create a bot service or register your bot. Your application will need these credentials at initialization time, to allow the adapter to authenticate traffic.

Note

If you are running or testing your bot locally, for example, using the Bot Framework Emulator, you can do so without configuring the adapter to authenticate traffic to and from your bot.

Turn context

When an adapter receives an activity, it generates a turn context object, which provides information about the incoming activity, the sender and receiver, the channel, the conversation, and other data needed to process the activity. The adapter then passes this context object to the bot. The context object persists for the length of a turn, and provides information on the following:

  • Conversation - Identifies the conversation and includes information about the bot and the user participating in the conversation.
  • Activity - The requests and replies in a conversation are all types of activities. This context provides information about the incoming activity, including routing information, information about the channel, the conversation, the sender, and the receiver.
  • Custom information – If you extend your bot either by implementing middleware or within your bot logic, you can make additional information available in each turn.

The context object can also be used to send a response to the user, and get a reference to the adapter.

Note

Your application and the adapter will handle requests asynchronously; however, your business logic does not need to be request-response driven.

Middleware

You can add middleware to the adapter. The middleware and the bot logic use the context object to retrieve information about the activity and act accordingly. The middleware and the bot can also update or add information to the context object, such as to track state for a turn, a conversation, or other scope. For more in depth information about middleware, see the middleware article.

Generating responses

The context object provides activity response methods to allow code to respond to an activity:

  • The send activity and send activities methods send one or more activities to the conversation.
  • If supported by the channel, the update activity method updates an activity within the conversation.
  • If supported by the channel, the delete activity method removes an activity from the conversation.

Each response method runs in an asynchronous process. When it is called, the activity response method clones the associated event handler list before starting to call the handlers, which means it will contain every handler added up to this point but will not contain anything added after the process starts.

This also means the order of your responses is not guaranteed, particularly when one task is more complex than another. If your bot can generate multiple responses to an incoming activity, make sure that they make sense in whatever order they are received by the user.

Important

The thread handling the primary bot turn deals with disposing of the context object when it is done. If a response (including its handlers) take any significant amount of time and try to act on the context object, they may get a Context was disposed error. Be sure to await any activity calls so the primary thread will wait on the generated activity before finishing it's processing and disposing of the turn context.

Response event handlers

In addition to the bot and middleware logic, response handlers (also sometimes referred to as event handlers, or activity event handlers) can be added to the context object. These handlers are called when the associated response happens on the current context object, before executing the actual response. These handlers are useful when you know you'll want to do something, either before or after the actual event, for every activity of that type for the rest of the current response.

Warning

Be careful to not call an activity response method from within it's respective response event handler, for example, calling the send activity method from within an on send activity handler. Doing so can generate an infinite loop.

Each new activity gets a new thread to execute on. When the thread to process the activity is created, the list of handlers for that activity is copied to that new thread. No handlers added after that point will be executed for that specific activity event.

The handlers registered on a context object are handled very similarly to how the adapter manages the middleware pipeline. Namely, handlers get called in the order they're added, and calling the next delegate passes control to the next registered event handler. If a handler doesn't call the next delegate, none of the subsequent event handlers are called, the event short circuits, and the adapter does not send the response to the channel.

Next steps