A framework for building Slack apps, fast.
npx @tessl/cli install tessl/npm-slack--bolt@4.4.0Slack Bolt is a comprehensive JavaScript/TypeScript framework specifically designed for building Slack applications with modern platform features. It offers a high-level abstraction for handling Slack's Events API, interactive components, slash commands, shortcuts, and OAuth flows through an intuitive event-driven architecture.
npm install @slack/boltimport { App } from "@slack/bolt";For CommonJS:
const { App } = require("@slack/bolt");import { App } from "@slack/bolt";
// Initialize your app with your bot token and signing secret
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
});
// Listen for a slash command invocation
app.command("/hello", async ({ command, ack, respond }) => {
// Acknowledge the command request
await ack();
await respond(`Hey there <@${command.user_id}>!`);
});
// Listen for a message containing "hello"
app.message("hello", async ({ message, say }) => {
await say(`Hey there <@${message.user}>!`);
});
// Start your app
(async () => {
await app.start(3000);
console.log("⚡️ Bolt app is running!");
})();Slack Bolt is built around several key components:
Main App class for building Slack applications with comprehensive event handling, middleware support, and flexible deployment options.
class App {
constructor(options?: AppOptions);
// Properties
readonly client: WebClient;
readonly logger: Logger;
get webClientOptions(): WebClientOptions;
// Initialization
init(): Promise<void>;
// Event listeners
event<EventType extends string>(
eventType: EventType,
...listeners: Middleware<SlackEventMiddlewareArgs<EventType>>[]
): void;
message(
pattern?: string | RegExp,
...listeners: Middleware<SlackEventMiddlewareArgs<'message'>>[]
): void;
action<ActionId extends string>(
actionId: ActionId,
...listeners: Middleware<SlackActionMiddlewareArgs>[]
): void;
command(
commandName: string,
...listeners: Middleware<SlackCommandMiddlewareArgs>[]
): void;
shortcut<CallbackId extends string>(
callbackId: CallbackId,
...listeners: Middleware<SlackShortcutMiddlewareArgs>[]
): void;
view<CallbackId extends string>(
callbackId: CallbackId,
...listeners: Middleware<SlackViewMiddlewareArgs>[]
): void;
options<Source extends OptionsSource>(
actionId: string | RegExp | OptionsConstraints<Source>,
...listeners: Middleware<SlackOptionsMiddlewareArgs<Source>>[]
): void;
// Advanced features
assistant(assistant: Assistant): this;
step(workflowStep: WorkflowStep): this;
function(
callbackId: string,
...listeners: Middleware<SlackCustomFunctionMiddlewareArgs>[]
): this;
// Global middleware and error handling
use(...middlewares: Middleware<AnyMiddlewareArgs>[]): void;
error(errorHandler: (error: CodedError) => Promise<void>): void;
// Application lifecycle
start(port?: number | (() => void), ...args: any[]): Promise<unknown>;
stop(): Promise<unknown>;
}
interface AppOptions {
/** Bot token starting with xoxb- */
token?: string;
/** App-level token starting with xapp- (required for Socket Mode) */
appToken?: string;
/** Signing secret for request verification */
signingSecret?: string | (() => PromiseLike<string>);
/** Custom receiver for handling HTTP requests */
receiver?: Receiver;
/** Custom authorization function */
authorize?: Authorize<boolean>;
/** Custom logger instance */
logger?: Logger;
/** Log level for built-in logger */
logLevel?: LogLevel;
/** Ignore events from the bot itself */
ignoreSelf?: boolean;
/** Web API client options */
clientOptions?: WebClientOptions;
/** Conversation state store */
convoStore?: ConversationStore | false;
/** Enable Socket Mode connection */
socketMode?: boolean;
/** Enable developer mode with additional logging */
developerMode?: boolean;
/** Enable token verification */
tokenVerificationEnabled?: boolean;
/** Defer app initialization until init() is called */
deferInitialization?: boolean;
/** Enable extended error handler format */
extendedErrorHandler?: boolean;
/** Attach function execution token to context */
attachFunctionToken?: boolean;
/** HTTP server port */
port?: number;
/** HTTP server endpoints configuration */
endpoints?: string | { [endpointType: string]: string };
/** Process events before sending HTTP response */
processBeforeResponse?: boolean;
/** Enable request signature verification */
signatureVerification?: boolean;
/** OAuth client ID */
clientId?: string;
/** OAuth client secret */
clientSecret?: string;
/** State parameter secret for OAuth */
stateSecret?: string;
/** OAuth redirect URI */
redirectUri?: string;
/** Installation store for OAuth */
installationStore?: InstallationStore;
/** OAuth permission scopes */
scopes?: InstallURLOptions['scopes'];
/** Installation provider options */
installerOptions?: InstallerOptions;
/** Custom HTTP routes */
customRoutes?: CustomRoute[];
/** HTTP agent for outgoing requests */
agent?: Agent;
/** TLS options for HTTPS */
clientTls?: Pick<SecureContextOptions, 'pfx' | 'key' | 'passphrase' | 'cert' | 'ca'>;
/** Bot ID for the application */
botId?: string;
/** Bot user ID for the application */
botUserId?: string;
/** Custom properties extractor function */
customPropertiesExtractor?: (request: any) => StringIndexed;
}HTTP and WebSocket receivers for different deployment scenarios including traditional servers, serverless functions, and Socket Mode connections.
class ExpressReceiver {
constructor(options: ExpressReceiverOptions);
}
class SocketModeReceiver {
constructor(options: SocketModeReceiverOptions);
}
class HTTPReceiver {
constructor(options: HTTPReceiverOptions);
}
class AwsLambdaReceiver {
constructor(options: AwsLambdaReceiverOptions);
}
interface ExpressReceiverOptions {
signingSecret: string;
logger?: Logger;
logLevel?: LogLevel;
endpoints?: string | { [key: string]: string };
processBeforeResponse?: boolean;
clientId?: string;
clientSecret?: string;
stateSecret?: string;
scopes?: string[];
installerOptions?: InstallProviderOptions;
}Filtering and matching middleware for event processing, message patterns, and request routing.
// Event filtering middleware
const onlyActions: Middleware<AnyMiddlewareArgs>;
const onlyCommands: Middleware<AnyMiddlewareArgs>;
const onlyEvents: Middleware<AnyMiddlewareArgs>;
const onlyShortcuts: Middleware<AnyMiddlewareArgs>;
// Matching middleware
function matchMessage(pattern: string | RegExp): Middleware<SlackEventMiddlewareArgs<'message'>>;
function matchCommandName(pattern: string | RegExp): Middleware<SlackCommandMiddlewareArgs>;
function matchConstraints<T>(constraints: ActionConstraints): Middleware<SlackActionMiddlewareArgs>;
// Utility middleware
const ignoreSelf: Middleware<AnyMiddlewareArgs>;AI Assistant integration and workflow step handling for complex Slack application scenarios.
class Assistant {
constructor(config: AssistantConfig);
}
interface AssistantConfig {
threadContextStore?: AssistantThreadContextStore;
threadStarted: AssistantThreadStartedMiddleware | AssistantThreadStartedMiddleware[];
threadContextChanged?: AssistantThreadContextChangedMiddleware | AssistantThreadContextChangedMiddleware[];
userMessage: AssistantUserMessageMiddleware | AssistantUserMessageMiddleware[];
}
class WorkflowStep {
constructor(config: WorkflowStepConfig);
}Slack custom functions for workflow and automation scenarios.
class CustomFunction {
constructor(
callbackId: string,
listeners: Middleware<SlackCustomFunctionMiddlewareArgs>[]
);
getListeners(): Middleware<AnyMiddlewareArgs>[];
}
type FunctionCompleteFn = (
params?: FunctionCompleteArguments
) => Promise<FunctionsCompleteSuccessResponse>;
type FunctionFailFn = (
params: FunctionFailArguments
) => Promise<FunctionsCompleteErrorResponse>;
function createFunctionComplete(
context: Context,
client: WebClient
): FunctionCompleteFn;
function createFunctionFail(
context: Context,
client: WebClient
): FunctionFailFn;
interface SlackCustomFunctionMiddlewareArgs extends AllMiddlewareArgs {
complete: FunctionCompleteFn;
fail: FunctionFailFn;
inputs: FunctionInputs;
}State management for multi-turn conversations and workflow tracking.
interface ConversationStore<ConversationState = any> {
set(
conversationId: string,
value: ConversationState,
expiresAt?: number
): Promise<unknown>;
get(conversationId: string): Promise<ConversationState>;
}
class MemoryStore<ConversationState = any>
implements ConversationStore<ConversationState> {
set(
conversationId: string,
value: ConversationState,
expiresAt?: number
): Promise<void>;
get(conversationId: string): Promise<ConversationState>;
}
function conversationContext<ConversationState = any>(
store: ConversationStore<ConversationState>
): Middleware<AnyMiddlewareArgs>;Request signature verification and authentication utilities for secure Slack app development.
function verifySlackRequest(options: RequestVerificationOptions): boolean;
function isValidSlackRequest(options: RequestVerificationOptions): boolean;
interface RequestVerificationOptions {
signingSecret: string;
body: string;
headers: { [key: string]: string | string[] | undefined };
}OAuth and authorization interfaces for app installation and token management.
type Authorize<IsEnterpriseInstall extends boolean = false> = (
source: AuthorizeSourceData<IsEnterpriseInstall>,
body?: AnyMiddlewareArgs['body']
) => Promise<AuthorizeResult>;
interface AuthorizeSourceData<IsEnterpriseInstall extends boolean = false> {
teamId: IsEnterpriseInstall extends true ? string | undefined : string;
enterpriseId: IsEnterpriseInstall extends true ? string : string | undefined;
userId?: string;
conversationId?: string;
isEnterpriseInstall: IsEnterpriseInstall;
}
interface AuthorizeResult {
botToken?: string;
userToken?: string;
botId?: string;
botUserId?: string;
userId?: string;
teamId?: string;
enterpriseId?: string;
[key: string]: any;
}// Middleware system
type Middleware<Args, CustomContext = StringIndexed> = (
args: Args & AllMiddlewareArgs<CustomContext>
) => Promise<void>;
interface AllMiddlewareArgs<CustomContext = StringIndexed> {
context: Context & CustomContext;
logger: Logger;
client: WebClient;
next: NextFn;
}
// Request context
interface Context extends StringIndexed {
botToken?: string;
userToken?: string;
botId?: string;
botUserId?: string;
userId?: string;
teamId?: string;
enterpriseId?: string;
isEnterpriseInstall: boolean;
functionBotAccessToken?: string;
functionExecutionId?: string;
functionInputs?: FunctionInputs;
retryNum?: number;
retryReason?: string;
}
// Utility functions
type AckFn = () => Promise<void>;
type SayFn = (message: string | SayArguments) => Promise<SayResult>;
type RespondFn = (response: string | RespondArguments) => Promise<void>;
type NextFn = () => Promise<void>;// Event middleware arguments
type SlackEventMiddlewareArgs<EventType extends string = string> = {
event: KnownEventFromType<EventType>;
body: EnvelopedEvent<KnownEventFromType<EventType>>;
payload: EnvelopedEvent<KnownEventFromType<EventType>>;
message: EventType extends 'message' ? GenericMessageEvent : never;
} & AllMiddlewareArgs;
// Action middleware arguments
type SlackActionMiddlewareArgs = {
action: SlackAction;
body: SlackActionBody;
payload: SlackAction;
} & AllMiddlewareArgs;
// Command middleware arguments
type SlackCommandMiddlewareArgs = {
command: SlashCommand;
body: SlashCommand;
payload: SlashCommand;
} & AllMiddlewareArgs;
// View middleware arguments
type SlackViewMiddlewareArgs = {
view: SlackViewAction;
body: SlackViewBody;
payload: SlackViewAction;
} & AllMiddlewareArgs;
// Options middleware arguments
type SlackOptionsMiddlewareArgs<Source extends OptionsSource = OptionsSource> = {
options: KnownOptionsPayloadFromType<Source>;
body: KnownOptionsPayloadFromType<Source>;
payload: KnownOptionsPayloadFromType<Source>;
} & AllMiddlewareArgs;
// Shortcut middleware arguments
type SlackShortcutMiddlewareArgs = {
shortcut: SlackShortcut;
body: SlackShortcut;
payload: SlackShortcut;
} & AllMiddlewareArgs;interface CodedError extends Error {
code: string;
original?: Error;
originals?: Error[];
missingProperty?: string;
}
enum ErrorCode {
AppInitializationError = 'slack_bolt_app_initialization_error',
AssistantInitializationError = 'slack_bolt_assistant_initialization_error',
AssistantMissingPropertyError = 'slack_bolt_assistant_missing_property_error',
AuthorizationError = 'slack_bolt_authorization_error',
ContextMissingPropertyError = 'slack_bolt_context_missing_property_error',
InvalidCustomPropertyError = 'slack_bolt_context_invalid_custom_property_error',
CustomRouteInitializationError = 'slack_bolt_custom_route_initialization_error',
ReceiverMultipleAckError = 'slack_bolt_receiver_ack_multiple_error',
ReceiverAuthenticityError = 'slack_bolt_receiver_authenticity_error',
ReceiverInconsistentStateError = 'slack_bolt_receiver_inconsistent_state_error',
MultipleListenerError = 'slack_bolt_multiple_listener_error',
HTTPReceiverDeferredRequestError = 'slack_bolt_http_receiver_deferred_request_error',
UnknownError = 'slack_bolt_unknown_error',
WorkflowStepInitializationError = 'slack_bolt_workflow_step_initialization_error',
CustomFunctionInitializationError = 'slack_bolt_custom_function_initialization_error',
CustomFunctionCompleteSuccessError = 'slack_bolt_custom_function_complete_success_error',
CustomFunctionCompleteFailError = 'slack_bolt_custom_function_complete_fail_error'
}
// Error Classes
class AppInitializationError extends Error implements CodedError {
code: ErrorCode.AppInitializationError;
original?: Error;
}
class AssistantInitializationError extends Error implements CodedError {
code: ErrorCode.AssistantInitializationError;
original?: Error;
}
class AssistantMissingPropertyError extends Error implements CodedError {
code: ErrorCode.AssistantMissingPropertyError;
missingProperty?: string;
}
class AuthorizationError extends Error implements CodedError {
code: ErrorCode.AuthorizationError;
original?: Error;
}
class ContextMissingPropertyError extends Error implements CodedError {
code: ErrorCode.ContextMissingPropertyError;
missingProperty?: string;
}
class InvalidCustomPropertyError extends Error implements CodedError {
code: ErrorCode.InvalidCustomPropertyError;
missingProperty?: string;
}
class CustomRouteInitializationError extends Error implements CodedError {
code: ErrorCode.CustomRouteInitializationError;
original?: Error;
}
class ReceiverMultipleAckError extends Error implements CodedError {
code: ErrorCode.ReceiverMultipleAckError;
}
class ReceiverAuthenticityError extends Error implements CodedError {
code: ErrorCode.ReceiverAuthenticityError;
}
class ReceiverInconsistentStateError extends Error implements CodedError {
code: ErrorCode.ReceiverInconsistentStateError;
}
class HTTPReceiverDeferredRequestError extends Error implements CodedError {
code: ErrorCode.HTTPReceiverDeferredRequestError;
}
class MultipleListenerError extends Error implements CodedError {
code: ErrorCode.MultipleListenerError;
originals?: Error[];
}
class UnknownError extends Error implements CodedError {
code: ErrorCode.UnknownError;
original?: Error;
}
class WorkflowStepInitializationError extends Error implements CodedError {
code: ErrorCode.WorkflowStepInitializationError;
original?: Error;
}
class CustomFunctionInitializationError extends Error implements CodedError {
code: ErrorCode.CustomFunctionInitializationError;
original?: Error;
}
class CustomFunctionCompleteSuccessError extends Error implements CodedError {
code: ErrorCode.CustomFunctionCompleteSuccessError;
original?: Error;
}
class CustomFunctionCompleteFailError extends Error implements CodedError {
code: ErrorCode.CustomFunctionCompleteFailError;
original?: Error;
}