or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-application.mdindex.mdmiddleware.mdreceivers.mdrequest-verification.md

core-application.mddocs/

0

# Core Application

1

2

The App class is the central component of Slack Bolt, providing event-driven architecture for building Slack applications with comprehensive listener registration, middleware support, and lifecycle management.

3

4

## Capabilities

5

6

### App Constructor

7

8

Creates a new Slack Bolt application instance with configuration options.

9

10

```typescript { .api }

11

/**

12

* Creates a new Slack Bolt application instance

13

* @param options - Configuration options for the app

14

*/

15

constructor(options?: AppOptions);

16

17

interface AppOptions {

18

/** Bot token starting with xoxb- */

19

token?: string;

20

/** App-level token starting with xapp- (required for Socket Mode) */

21

appToken?: string;

22

/** Signing secret for request verification */

23

signingSecret?: string;

24

/** Custom receiver for handling HTTP requests */

25

receiver?: Receiver;

26

/** Custom authorization function */

27

authorize?: Authorize;

28

/** Custom logger instance */

29

logger?: Logger;

30

/** Log level for built-in logger */

31

logLevel?: LogLevel;

32

/** Ignore events from the bot itself */

33

ignoreSelf?: boolean;

34

/** Web API client options */

35

clientOptions?: WebClientOptions;

36

/** Conversation state store */

37

convoStore?: ConversationStore;

38

/** Enable Socket Mode connection */

39

socketMode?: boolean;

40

}

41

```

42

43

**Usage Example:**

44

45

```typescript

46

import { App } from "@slack/bolt";

47

48

const app = new App({

49

token: process.env.SLACK_BOT_TOKEN,

50

signingSecret: process.env.SLACK_SIGNING_SECRET,

51

socketMode: false, // Set to true for Socket Mode

52

logLevel: "INFO"

53

});

54

```

55

56

### Event Listeners

57

58

Register listeners for Slack events with optional event type filtering.

59

60

```typescript { .api }

61

/**

62

* Register listeners for Slack events

63

* @param eventType - Event type pattern to match

64

* @param listeners - Middleware functions to handle the event

65

*/

66

event<EventType extends string>(

67

eventType: EventType,

68

...listeners: Middleware<SlackEventMiddlewareArgs<EventType>>[]

69

): void;

70

```

71

72

**Usage Examples:**

73

74

```typescript

75

// Listen for app mentions

76

app.event("app_mention", async ({ event, say }) => {

77

await say(`Hello <@${event.user}>!`);

78

});

79

80

// Listen for when users join channels

81

app.event("member_joined_channel", async ({ event, client, logger }) => {

82

logger.info(`User ${event.user} joined channel ${event.channel}`);

83

});

84

85

// Listen for file shared events

86

app.event("file_shared", async ({ event, client }) => {

87

// Handle file shared event

88

});

89

```

90

91

### Message Listeners

92

93

Register listeners for message events with optional pattern matching.

94

95

```typescript { .api }

96

/**

97

* Register listeners for message events with optional pattern matching

98

* @param pattern - Text pattern to match (string or RegExp), optional

99

* @param listeners - Middleware functions to handle the message

100

*/

101

message(

102

pattern?: string | RegExp,

103

...listeners: Middleware<SlackEventMiddlewareArgs<'message'>>[]

104

): void;

105

```

106

107

**Usage Examples:**

108

109

```typescript

110

// Listen for all messages

111

app.message(async ({ message, say }) => {

112

if (message.subtype === undefined) {

113

await say("I heard you!");

114

}

115

});

116

117

// Listen for messages containing "hello"

118

app.message("hello", async ({ message, say }) => {

119

await say(`Hey there <@${message.user}>!`);

120

});

121

122

// Listen for messages matching a pattern

123

app.message(/^ticket-(\d+)/, async ({ message, say, context }) => {

124

const ticketId = context.matches[1];

125

await say(`Looking up ticket ${ticketId}...`);

126

});

127

```

128

129

### Action Listeners

130

131

Register listeners for interactive component actions (buttons, select menus, etc.).

132

133

```typescript { .api }

134

/**

135

* Register listeners for interactive component actions

136

* @param actionId - Action ID or constraint object to match

137

* @param listeners - Middleware functions to handle the action

138

*/

139

action<ActionId extends string>(

140

actionId: ActionId | ActionConstraints,

141

...listeners: Middleware<SlackActionMiddlewareArgs>[]

142

): void;

143

```

144

145

**Usage Examples:**

146

147

```typescript

148

// Listen for button clicks

149

app.action("button_click", async ({ body, ack, say }) => {

150

await ack();

151

await say(`<@${body.user.id}> clicked the button`);

152

});

153

154

// Listen for select menu selections

155

app.action("static_select-action", async ({ body, ack, client }) => {

156

await ack();

157

// Handle select menu selection

158

});

159

160

// Listen for overflow menu actions

161

app.action("overflow_menu_action", async ({ action, ack, respond }) => {

162

await ack();

163

await respond(`You selected: ${action.selected_option.value}`);

164

});

165

```

166

167

### Command Listeners

168

169

Register listeners for slash commands.

170

171

```typescript { .api }

172

/**

173

* Register listeners for slash commands

174

* @param commandName - Slash command name (e.g., "/hello")

175

* @param listeners - Middleware functions to handle the command

176

*/

177

command(

178

commandName: string,

179

...listeners: Middleware<SlackCommandMiddlewareArgs>[]

180

): void;

181

```

182

183

**Usage Examples:**

184

185

```typescript

186

// Handle /hello command

187

app.command("/hello", async ({ command, ack, respond }) => {

188

await ack();

189

await respond(`Hey there <@${command.user_id}>!`);

190

});

191

192

// Handle /ticket command with parameters

193

app.command("/ticket", async ({ command, ack, client, respond }) => {

194

await ack();

195

196

const args = command.text.split(" ");

197

const action = args[0];

198

199

if (action === "create") {

200

await respond("Creating a new ticket...");

201

} else if (action === "list") {

202

await respond("Listing your tickets...");

203

} else {

204

await respond("Usage: /ticket create|list");

205

}

206

});

207

```

208

209

### Shortcut Listeners

210

211

Register listeners for shortcuts (global and message shortcuts).

212

213

```typescript { .api }

214

/**

215

* Register listeners for shortcuts

216

* @param callbackId - Shortcut callback ID to match

217

* @param listeners - Middleware functions to handle the shortcut

218

*/

219

shortcut<CallbackId extends string>(

220

callbackId: CallbackId | ShortcutConstraints,

221

...listeners: Middleware<SlackShortcutMiddlewareArgs>[]

222

): void;

223

```

224

225

**Usage Examples:**

226

227

```typescript

228

// Handle global shortcut

229

app.shortcut("open_modal", async ({ shortcut, ack, client, body }) => {

230

await ack();

231

232

await client.views.open({

233

trigger_id: body.trigger_id,

234

view: {

235

type: "modal",

236

callback_id: "my_modal",

237

title: { type: "plain_text", text: "My App" },

238

close: { type: "plain_text", text: "Cancel" },

239

blocks: [

240

// Modal blocks here

241

]

242

}

243

});

244

});

245

246

// Handle message shortcut

247

app.shortcut("share_message", async ({ shortcut, ack, client }) => {

248

await ack();

249

// Handle sharing the message

250

});

251

```

252

253

### View Listeners

254

255

Register listeners for modal view submissions and closures.

256

257

```typescript { .api }

258

/**

259

* Register listeners for view submissions and closures

260

* @param callbackId - View callback ID to match

261

* @param listeners - Middleware functions to handle the view action

262

*/

263

view<CallbackId extends string>(

264

callbackId: CallbackId | ViewConstraints,

265

...listeners: Middleware<SlackViewMiddlewareArgs>[]

266

): void;

267

```

268

269

**Usage Examples:**

270

271

```typescript

272

// Handle modal submission

273

app.view("modal_callback", async ({ ack, body, view, client }) => {

274

await ack();

275

276

const values = view.state.values;

277

const user = body.user.id;

278

279

// Process form data

280

});

281

282

// Handle modal closure

283

app.view({ callback_id: "modal_callback", type: "view_closed" },

284

async ({ ack, body, view }) => {

285

await ack();

286

// Handle modal being closed

287

}

288

);

289

```

290

291

### Global Middleware

292

293

Add middleware that runs for all incoming requests.

294

295

```typescript { .api }

296

/**

297

* Add global middleware that runs for all requests

298

* @param middlewares - Middleware functions to add

299

*/

300

use(...middlewares: Middleware<AnyMiddlewareArgs>[]): void;

301

```

302

303

**Usage Examples:**

304

305

```typescript

306

// Add custom logging middleware

307

app.use(async ({ logger, body, next }) => {

308

logger.info("Incoming request", body);

309

await next();

310

});

311

312

// Add authorization middleware

313

app.use(async ({ context, client, next }) => {

314

// Add custom context properties

315

context.customData = await loadUserData(context.userId);

316

await next();

317

});

318

319

// Add built-in middleware

320

import { ignoreSelf } from "@slack/bolt";

321

app.use(ignoreSelf);

322

```

323

324

### Error Handling

325

326

Register global error handler for unhandled errors.

327

328

```typescript { .api }

329

/**

330

* Register global error handler

331

* @param errorHandler - Function to handle errors

332

*/

333

error(errorHandler: (error: CodedError) => Promise<void>): void;

334

```

335

336

**Usage Example:**

337

338

```typescript

339

app.error(async (error) => {

340

console.error("An error occurred:", error);

341

342

// Send error to monitoring service

343

if (error.code === "slack_bolt_authorization_error") {

344

// Handle authorization errors

345

}

346

});

347

```

348

349

### Application Lifecycle

350

351

Start and stop the Slack application.

352

353

```typescript { .api }

354

/**

355

* Start the Slack application

356

* @param port - Port number for HTTP server (optional)

357

* @returns Promise that resolves when the app starts

358

*/

359

start(port?: number): Promise<unknown>;

360

361

/**

362

* Stop the Slack application

363

* @returns Promise that resolves when the app stops

364

*/

365

stop(): Promise<unknown>;

366

```

367

368

**Usage Examples:**

369

370

```typescript

371

// Start the app

372

(async () => {

373

await app.start(3000);

374

console.log("⚡️ Bolt app is running on port 3000!");

375

})();

376

377

// Graceful shutdown

378

process.on("SIGINT", async () => {

379

await app.stop();

380

process.exit(0);

381

});

382

```

383

384

### Options and Function Listeners

385

386

Register listeners for select menu options and custom functions.

387

388

```typescript { .api }

389

/**

390

* Register listeners for external select menu options

391

* @param actionId - Action ID or constraints to match

392

* @param listeners - Middleware functions to handle options request

393

*/

394

options<ActionId extends string>(

395

actionId: ActionId | OptionsConstraints,

396

...listeners: Middleware<SlackOptionsMiddlewareArgs>[]

397

): void;

398

399

/**

400

* Register listeners for custom functions

401

* @param callbackId - Function callback ID to match

402

* @param listeners - Middleware functions to handle function execution

403

*/

404

function<CallbackId extends string>(

405

callbackId: CallbackId,

406

...listeners: Middleware<SlackCustomFunctionMiddlewareArgs>[]

407

): void;

408

```

409

410

**Usage Examples:**

411

412

```typescript

413

// Handle external select menu options

414

app.options("external_select", async ({ options, ack }) => {

415

await ack({

416

options: [

417

{ text: { type: "plain_text", text: "Option 1" }, value: "opt1" },

418

{ text: { type: "plain_text", text: "Option 2" }, value: "opt2" }

419

]

420

});

421

});

422

423

// Handle custom function execution

424

app.function("my_function", async ({ inputs, complete, fail }) => {

425

try {

426

const result = await processInputs(inputs);

427

await complete({ outputs: result });

428

} catch (error) {

429

await fail({ error: "Processing failed" });

430

}

431

});

432

```

433

434

## Authorization Types

435

436

```typescript { .api }

437

type Authorize = (

438

source: AuthorizeSourceData

439

) => Promise<AuthorizeResult>;

440

441

interface AuthorizeSourceData {

442

teamId: string;

443

enterpriseId?: string;

444

userId?: string;

445

conversationId?: string;

446

isEnterpriseInstall?: boolean;

447

}

448

449

interface AuthorizeResult {

450

botToken?: string;

451

userToken?: string;

452

botId?: string;

453

botUserId?: string;

454

userId?: string;

455

teamId?: string;

456

enterpriseId?: string;

457

}

458

```