Individual bot instances that handle message sending, dialog management, and context switching. Each worker represents a bot's interaction with a specific user or conversation.
Creates a new BotWorker instance. Typically created through controller.spawn() rather than directly.
/**
* Create a new BotWorker instance
* @param controller A pointer to the main Botkit controller
* @param config An object typically containing { dialogContext, reference, context, activity }
*/
constructor(controller: Botkit, config: any);Access bot worker configuration and controller reference.
/**
* Get a reference to the main Botkit controller
*/
get controller(): Botkit;
/**
* Get a value from the BotWorker's configuration
* @param key The name of a value stored in the configuration
* @returns The value stored in the configuration (or null if absent)
*/
getConfig(key?: string): any;Usage Examples:
// Access controller from bot worker
const version = bot.controller.version;
// Get configuration values
const context = bot.getConfig("context");
const dialogContext = bot.getConfig("dialogContext");Send messages using the bot worker's current context.
/**
* Send a message using current context
* @param message A string containing the text of a reply, or more fully formed message object
* @returns Return value will contain the results of the send action
*/
say(message: Partial<BotkitMessage> | string): Promise<any>;
/**
* Reply to an incoming message
* @param src An incoming message, usually passed in to a handler function
* @param resp A string containing the text of a reply, or more fully formed message object
* @returns Return value will contain the results of the send action
*/
reply(src: Partial<BotkitMessage>, resp: Partial<BotkitMessage> | string): Promise<any>;Usage Examples:
// Simple text message
await bot.say("Hello there!");
// Rich message object
await bot.say({
text: "Here's a rich message",
attachments: [{
title: "Attachment Title",
text: "Attachment content"
}]
});
// Reply to incoming message
controller.on("message", async (bot, message) => {
await bot.reply(message, "I received your message!");
});
// Reply with rich content
await bot.reply(message, {
text: "Choose an option:",
quick_replies: [
{ title: "Option 1", payload: "opt1" },
{ title: "Option 2", payload: "opt2" }
]
});Start, manage, and control multi-turn conversations.
/**
* Begin a pre-defined dialog by specifying its id
* @param id id of dialog
* @param options object containing options to be passed into the dialog
*/
beginDialog(id: string, options?: any): Promise<void>;
/**
* Replace any active dialogs with a new pre-defined dialog
* @param id id of dialog
* @param options object containing options to be passed into the dialog
*/
replaceDialog(id: string, options?: any): Promise<void>;
/**
* Cancel any and all active dialogs for the current user/context
*/
cancelAllDialogs(): Promise<DialogTurnResult>;
/**
* Get a reference to the active dialog
* @returns a reference to the active dialog or undefined if no dialog is active
*/
getActiveDialog(): Dialog | undefined;
/**
* Check if any dialog is active or not
* @returns true if there is an active dialog, otherwise false
*/
hasActiveDialog(): boolean;
/**
* Check to see if a given dialog is currently active in the stack
* @param id The id of a dialog to look for in the dialog stack
* @returns true if dialog with id is located anywhere in the dialog stack
*/
isDialogActive(id: string): boolean;Usage Examples:
// Start a dialog
controller.hears("start survey", "message", async (bot, message) => {
await bot.beginDialog("survey_dialog", { topic: "satisfaction" });
});
// Replace current dialog
await bot.replaceDialog("emergency_dialog");
// Cancel all dialogs
controller.interrupts("cancel", "message", async (bot, message) => {
await bot.cancelAllDialogs();
await bot.reply(message, "All conversations cancelled.");
});
// Check dialog status
if (bot.hasActiveDialog()) {
console.log("Active dialog:", bot.getActiveDialog().id);
}
if (bot.isDialogActive("survey_dialog")) {
console.log("Survey is currently active");
}Change the bot's conversation context for proactive messaging.
/**
* Alter the context in which a bot instance will send messages
* @param reference A ConversationReference for proactive messaging scenarios
*/
changeContext(reference: Partial<ConversationReference>): Promise<BotWorker>;
/**
* Start a new conversation with a user
* @param reference Reference object containing user and conversation details
*/
startConversationWithUser(reference: any): Promise<void>;Usage Examples:
// Proactive messaging
const savedReference = message.reference; // Save reference from earlier message
// Later, send proactive message
const bot = await controller.spawn();
await bot.changeContext(savedReference);
await bot.say("This is a proactive message!");
// Start new conversation
await bot.startConversationWithUser({
serviceUrl: "https://service.url",
user: { id: "user123" },
bot: { id: "bot456" }
});Convert messages to proper Activity format for the Bot Framework.
/**
* Convert message to BotFramework Activity format
* @param message a string or partial outgoing message object
* @returns a properly formed Activity object
*/
ensureMessageFormat(message: Partial<BotkitMessage> | string): Partial<Activity>;Usage Examples:
// Typically used internally, but available for custom formatting
const activity = bot.ensureMessageFormat({
text: "Hello",
channelData: { custom: "data" }
});Control HTTP response status and body for webhook scenarios.
/**
* Set the http response status code for this turn
* @param status a valid http status code like 200 202 301 500 etc
*/
httpStatus(status: number): void;
/**
* Set the http response body for this turn
* @param body a value that will be returned as the http response body
*/
httpBody(body: any): void;Usage Examples:
// Handle slash commands with custom response
controller.on("slash_command", async (bot, message) => {
if (message.text === "/invalid") {
bot.httpStatus(400);
bot.httpBody("Invalid command");
} else {
bot.httpBody("Command processed successfully");
}
});
// Return custom status codes
controller.on("message", async (bot, message) => {
if (message.text.includes("error")) {
bot.httpStatus(500);
await bot.reply(message, "An error occurred");
}
});Bot workers handle messages in the standard Botkit message format:
interface BotkitMessage {
type: string;
text?: string;
value?: string;
user: string;
channel: string;
reference: ConversationReference;
incoming_message: Activity;
[key: string]: any;
}Bot workers can be extended by adapters for platform-specific functionality:
// Example: Teams-specific bot worker
class TeamsBotWorker extends BotWorker {
teams: TeamsInfo;
replyWithTaskInfo(message: BotkitMessage, taskInfo: any): Promise<any>;
}Usage Examples:
// Platform-specific functionality is available when using specialized adapters
// Teams example
controller.on("task/fetch", async (bot, message) => {
await bot.replyWithTaskInfo(message, {
type: "continue",
value: { title: "Task", url: "https://example.com" }
});
});
// Slack example (with Slack adapter)
await bot.api.chat.postMessage({
channel: message.channel,
text: "Posted via Slack API"
});Bot workers integrate with Botkit's error handling system:
// Handle errors in message sending
try {
await bot.say("This might fail");
} catch (error) {
console.error("Failed to send message:", error);
await bot.say("Sorry, something went wrong");
}
// Handle errors in dialog operations
try {
await bot.beginDialog("nonexistent_dialog");
} catch (error) {
console.error("Dialog error:", error);
await bot.reply(message, "Unable to start conversation");
}