Using the BotBuilder Plugin
Adapters
A BotBuilder CloudAdapter is responsible for managing communication between a bot and its users.
It serves as the entry point for incoming activities and forwards them to the registered ActivityHandler for processing.
You can customize the adapter to add middleware for logging, authentication, and define error handling.
The BotBuilderPlugin provided within the Teams SDK, connects the SDK with the BotBuilder framework.
It can either use an existing CloudAdapter or create a new default one, allowing activities to be processed through BotBuilder
while still handling events via the Teams SDK App framework.
Activity Handlers
The BotBuilder ActivityHandler contains the actual bot logic for processing messages or events
similar to how the Teams SDK App routes messages and events. You can override any number of methods,
such as
on_members_added_activity
or
on_message_activity ,
to handle different activity types.
Turn Context
Each incoming activity is wrapped in a TurnContext, which represents the context of a single turn in the conversation.
TurnContext provides access to:
- The incoming activity (message, event).
- Services for sending responses back to the user.
- Conversation, user, and channel metadata.
Teams SDK has
ActivityContext for the same purpose.
How it all comes together
The CloudAdapter creates the TurnContext, and the ActivityHandler uses it to read the activity and send responses.
With the BotBuilderPlugin, when a message or activity is received:
- The BotBuilder ActivityHandler runs first, handling the activity according to standard Bot Framework logic.
- The Teams SDK app based activity handlers execute afterward, allowing Teams SDK logic to execute.
This snippet shows how to use the BotBuilderPlugin to send and receive activities using botbuilder instead of the default Teams SDK http plugin.
- app.py
- adapter.py
- activity_handler.py
import asyncio
from adapter import adapter
from activity_handler import MyActivityHandler
from microsoft.teams.api import MessageActivity
from microsoft.teams.apps import ActivityContext, App
from microsoft.teams.botbuilder import BotBuilderPlugin
app = App(plugins=[BotBuilderPlugin(adapter=adapter, handler=MyActivityHandler())])
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
print("Handling message in app...")
await ctx.send("hi from teams...")
if __name__ == "__main__":
asyncio.run(app.start())
from botbuilder.core import TurnContext
from botbuilder.integration.aiohttp import (
CloudAdapter,
ConfigurationBotFrameworkAuthentication,
)
from botbuilder.schema import Activity, ActivityTypes
from types import SimpleNamespace
config = SimpleNamespace(
APP_TYPE="SingleTenant" if tenant_id else "MultiTenant",
APP_ID=client_id,
APP_PASSWORD=client_secret,
APP_TENANTID=tenant_id,
)
# replace with your Adapter
adapter = CloudAdapter(ConfigurationBotFrameworkAuthentication(config))
async def on_error(context: TurnContext, error: Exception):
# Send a message to the user
await context.send_activity("The bot encountered an error or bug.")
adapter.on_turn_error = on_error
from botbuilder.core import ActivityHandler, TurnContext
# replace with your ActivityHandler
class MyActivityHandler(ActivityHandler):
async def on_message_activity(self, turn_context: TurnContext):
await turn_context.send_activity("hi from botbuilder...")
In this example:
-
adapter.pydefines aCloudAdapterto handle incoming activities, and can include middleware support or error handling. -
activity_handler.pydefines theActivityHandlerand contains the core bot logic, handling incoming messages and sending responses via theTurnContext. -
app.pysets up a Teams SDKappand registers theBotBuilderPluginwith your adapter and activity handler. It also defines a native Teams SDK activity handler that responds to messages.
In the ouptut below, The first line comes from the BotBuilder ActivityHandler. The second line comes from the Teams SDK message activity handler. This shows that both handlers can process the same message sequentially when using the BotBuilder Plugin. This strategy can now be used to incrementally migrate from BotBuilder to the Teams SDK.
hi from botbuilder...
hi from teams...