or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-configuration.mdcontext-and-utilities.mdevent-listeners.mdframework-integration.mdindex.mdoauth-and-installation.md

context-and-utilities.mddocs/

0

# Context Objects & Utilities

1

2

Rich context objects providing utilities for acknowledging requests, sending messages, making API calls, and accessing request data. Includes the argument injection system for clean listener functions.

3

4

## Capabilities

5

6

### Core Context Object

7

8

The BoltContext provides access to all utilities and request data within listeners.

9

10

```python { .api }

11

class BoltContext:

12

"""

13

Context object containing utilities and request data.

14

15

Properties:

16

client (WebClient): Slack API client instance

17

ack (Ack): Function to acknowledge requests

18

say (Say): Function to send messages to channel

19

respond (Respond): Function to respond to interactions

20

complete (Complete): Function to complete workflow steps

21

fail (Fail): Function to fail workflow steps

22

logger (Logger): App logger instance

23

listener_runner: Thread listener runner

24

25

# AI Assistant utilities

26

set_status (SetStatus): Set assistant conversation status

27

set_title (SetTitle): Set assistant conversation title

28

set_suggested_prompts (SetSuggestedPrompts): Set suggested prompts

29

save_thread_context (SaveThreadContext): Save conversation context

30

get_thread_context: Get conversation context (async only)

31

"""

32

33

def to_copyable(self):

34

"""

35

Create a copyable version of the context.

36

37

Returns:

38

BoltContext: Copyable context instance

39

"""

40

```

41

42

### Request and Response Objects

43

44

Core objects representing incoming requests and outgoing responses.

45

46

```python { .api }

47

class BoltRequest:

48

"""

49

Incoming request wrapper.

50

51

Properties:

52

raw_body (str): Raw request body string

53

query (dict): Query parameters

54

headers (dict): Request headers

55

content_type (str): HTTP content type

56

body (dict): Parsed request body

57

context (BoltContext): Associated context

58

lazy_only (bool): Lazy execution mode flag

59

lazy_function_name (str): Lazy function name

60

mode (str): Request mode ("http" or "socket_mode")

61

"""

62

63

def to_copyable(self):

64

"""Create copyable request instance."""

65

66

class BoltResponse:

67

"""

68

Outgoing response object.

69

70

Properties:

71

status (int): HTTP status code

72

headers (dict): Response headers

73

body (str): Response body

74

"""

75

```

76

77

### Acknowledgment Functions

78

79

Functions for acknowledging Slack interactions (required within 3 seconds).

80

81

```python { .api }

82

class Ack:

83

"""Acknowledge function for responding to Slack interactions."""

84

85

def __call__(self, response=None):

86

"""

87

Acknowledge a Slack interaction.

88

89

Args:

90

response (dict, optional): Optional response payload

91

- For commands: Response text or response object

92

- For actions: Updated message or modal

93

- For view submissions: Response action or errors

94

"""

95

96

# Usage examples:

97

def handle_command(ack, respond, command):

98

ack() # Simple acknowledgment

99

respond("Processing your request...")

100

101

def handle_action(ack, body):

102

ack({"text": "Button clicked!"}) # Acknowledge with response

103

104

def handle_view_submission(ack, view):

105

# Acknowledge with validation errors

106

if not view["state"]["values"]["field"]["value"]:

107

ack({

108

"response_action": "errors",

109

"errors": {

110

"field": "This field is required"

111

}

112

})

113

else:

114

ack() # Success acknowledgment

115

```

116

117

### Say Function

118

119

Send messages to the channel where an event occurred.

120

121

```python { .api }

122

class Say:

123

"""Function to send messages to the event channel."""

124

125

def __call__(

126

self,

127

text: str = None,

128

blocks: list = None,

129

attachments: list = None,

130

thread_ts: str = None,

131

reply_broadcast: bool = None,

132

unfurl_links: bool = None,

133

unfurl_media: bool = None,

134

**kwargs

135

):

136

"""

137

Send a message to the channel.

138

139

Args:

140

text (str): Message text (required if blocks not provided)

141

blocks (list): Block Kit blocks

142

attachments (list): Message attachments (legacy)

143

thread_ts (str): Thread timestamp to reply in thread

144

reply_broadcast (bool): Broadcast thread reply to channel

145

unfurl_links (bool): Enable link unfurling

146

unfurl_media (bool): Enable media unfurling

147

**kwargs: Additional chat.postMessage parameters

148

149

Returns:

150

dict: API response with message data

151

"""

152

153

# Usage examples:

154

def handle_message(say):

155

say("Hello!") # Simple text message

156

157

say(

158

text="Fallback text",

159

blocks=[

160

{

161

"type": "section",

162

"text": {"type": "mrkdwn", "text": "*Bold text* in Block Kit"}

163

}

164

]

165

) # Rich Block Kit message

166

167

say("Thread reply", thread_ts=message["ts"]) # Reply in thread

168

```

169

170

### Respond Function

171

172

Respond to interactions using response URLs (commands, actions, shortcuts).

173

174

```python { .api }

175

class Respond:

176

"""Function to respond to interactions using response URLs."""

177

178

def __call__(

179

self,

180

text: str = None,

181

blocks: list = None,

182

attachments: list = None,

183

response_type: str = "ephemeral",

184

replace_original: bool = None,

185

delete_original: bool = None,

186

unfurl_links: bool = None,

187

unfurl_media: bool = None,

188

**kwargs

189

):

190

"""

191

Respond to an interaction.

192

193

Args:

194

text (str): Response text

195

blocks (list): Block Kit blocks

196

attachments (list): Message attachments

197

response_type (str): "ephemeral" (private) or "in_channel" (public)

198

replace_original (bool): Replace the original message

199

delete_original (bool): Delete the original message

200

unfurl_links (bool): Enable link unfurling

201

unfurl_media (bool): Enable media unfurling

202

**kwargs: Additional response parameters

203

204

Returns:

205

dict: Response data

206

"""

207

208

# Usage examples:

209

def handle_command(ack, respond):

210

ack()

211

respond("This is a private response") # Only visible to user

212

respond("This is public", response_type="in_channel") # Visible to all

213

214

def handle_button_click(ack, respond):

215

ack()

216

respond(

217

text="Updated message",

218

replace_original=True # Replace the message containing the button

219

)

220

```

221

222

### Complete and Fail Functions

223

224

Functions for workflow step completion and failure handling.

225

226

```python { .api }

227

class Complete:

228

"""Function to mark workflow steps as complete."""

229

230

def __call__(self, outputs: dict = None):

231

"""

232

Mark a workflow step as complete.

233

234

Args:

235

outputs (dict): Step output values for subsequent steps

236

"""

237

238

class Fail:

239

"""Function to mark workflow steps as failed."""

240

241

def __call__(self, error: str):

242

"""

243

Mark a workflow step as failed.

244

245

Args:

246

error (str): Error message describing the failure

247

"""

248

249

# Usage in workflow steps:

250

def execute_step(step, complete, fail):

251

try:

252

# Step execution logic

253

result = process_data(step["inputs"])

254

complete(outputs={"result": result})

255

except Exception as e:

256

fail(error=f"Step failed: {str(e)}")

257

```

258

259

### AI Assistant Utilities

260

261

Functions for managing AI assistant conversations and context.

262

263

```python { .api }

264

class SetStatus:

265

"""Set status for AI assistant conversations."""

266

267

def __call__(self, text: str):

268

"""

269

Set the assistant status text.

270

271

Args:

272

text (str): Status message to display

273

"""

274

275

class SetTitle:

276

"""Set title for AI assistant conversations."""

277

278

def __call__(self, title: str):

279

"""

280

Set the conversation title.

281

282

Args:

283

title (str): Conversation title

284

"""

285

286

class SetSuggestedPrompts:

287

"""Set suggested prompts for AI assistant conversations."""

288

289

def __call__(self, prompts: list):

290

"""

291

Set suggested prompts for the user.

292

293

Args:

294

prompts (list): List of suggested prompt strings

295

"""

296

297

class SaveThreadContext:

298

"""Save context data for AI assistant conversations."""

299

300

def __call__(self, context: dict):

301

"""

302

Save thread context data.

303

304

Args:

305

context (dict): Context data to persist

306

"""

307

308

# Usage in assistant handlers:

309

@app.assistant()

310

def handle_assistant_message(set_status, set_title, save_thread_context):

311

set_status("Processing your request...")

312

set_title("Customer Support Chat")

313

save_thread_context({"topic": "billing", "priority": "high"})

314

```

315

316

### Slack Web API Client

317

318

Direct access to the Slack Web API client for advanced operations.

319

320

```python { .api }

321

# WebClient is from slack_sdk package

322

from slack_sdk import WebClient

323

324

# Available as 'client' in all listeners

325

def handle_event(client: WebClient):

326

"""

327

Use the client for direct API calls.

328

329

Common methods:

330

- client.chat_postMessage()

331

- client.users_info()

332

- client.conversations_list()

333

- client.files_upload()

334

- client.views_open()

335

- client.views_update()

336

"""

337

338

# Usage examples:

339

def handle_command(ack, respond, client, command):

340

ack()

341

342

# Get user info

343

user_info = client.users_info(user=command["user_id"])

344

real_name = user_info["user"]["real_name"]

345

346

# Post to different channel

347

client.chat_postMessage(

348

channel="#general",

349

text=f"{real_name} used the /weather command"

350

)

351

352

respond("Weather data sent to #general")

353

354

def open_modal(ack, body, client):

355

ack()

356

357

# Open a modal view

358

client.views_open(

359

trigger_id=body["trigger_id"],

360

view={

361

"type": "modal",

362

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

363

"blocks": [...]

364

}

365

)

366

```

367

368

### Logger

369

370

Access to the app's logger instance for debugging and monitoring.

371

372

```python { .api }

373

# Logger is Python's standard logging.Logger

374

import logging

375

376

def handle_event(logger: logging.Logger):

377

"""

378

Use logger for debugging and monitoring.

379

380

Available methods:

381

- logger.debug()

382

- logger.info()

383

- logger.warning()

384

- logger.error()

385

- logger.exception()

386

"""

387

388

# Usage examples:

389

def handle_command(ack, command, logger):

390

ack()

391

392

logger.info(f"Command received: {command['command']} from user {command['user_id']}")

393

394

try:

395

# Process command

396

result = complex_operation()

397

logger.debug(f"Operation completed: {result}")

398

except Exception as e:

399

logger.exception("Command processing failed")

400

raise e

401

```

402

403

### Request Body and Payload Data

404

405

Access to raw request data and parsed payloads.

406

407

```python { .api }

408

def handle_event(body: dict, payload: dict):

409

"""

410

Access request data directly.

411

412

Args:

413

body (dict): Complete request body from Slack

414

payload (dict): Parsed event payload (event-specific)

415

"""

416

417

# Usage examples:

418

def handle_action(ack, body, action):

419

ack()

420

421

# body contains full request context

422

user_id = body["user"]["id"]

423

team_id = body["team"]["id"]

424

trigger_id = body.get("trigger_id")

425

426

# action contains specific action data

427

action_id = action["action_id"]

428

value = action.get("value")

429

430

def handle_view_submission(ack, body, view):

431

ack()

432

433

# Extract form values from view state

434

values = view["state"]["values"]

435

form_data = {}

436

437

for block_id, block_values in values.items():

438

for action_id, element in block_values.items():

439

form_data[action_id] = element["value"]

440

```

441

442

### Multi-Workspace Context

443

444

Access to workspace and user identification for multi-workspace apps.

445

446

```python { .api }

447

def handle_event(

448

enterprise_id: str,

449

team_id: str,

450

user_id: str,

451

channel_id: str

452

):

453

"""

454

Access workspace context data.

455

456

Args:

457

enterprise_id (str): Enterprise Grid organization ID (if applicable)

458

team_id (str): Workspace/team ID

459

user_id (str): User ID who triggered the event

460

channel_id (str): Channel ID where event occurred

461

"""

462

463

# Usage for multi-workspace features:

464

def handle_message(message, say, team_id, user_id):

465

# Customize behavior per workspace

466

if team_id == "T123456789":

467

say("Welcome to our main workspace!")

468

else:

469

say("Hello from a connected workspace!")

470

471

# Log user activity per workspace

472

log_user_activity(team_id, user_id, "message_sent")

473

```

474

475

## Usage Examples

476

477

### Complete Handler with All Context

478

479

```python

480

@app.command("/status")

481

def status_command(

482

ack,

483

respond,

484

command,

485

client,

486

logger,

487

body,

488

user_id,

489

team_id,

490

context

491

):

492

"""Complete example using all available context."""

493

494

# Always acknowledge first

495

ack()

496

497

# Log the request

498

logger.info(f"Status command from user {user_id} in team {team_id}")

499

500

# Get additional user info

501

try:

502

user_info = client.users_info(user=user_id)

503

user_name = user_info["user"]["real_name"]

504

505

# Respond with status

506

respond(f"Hello {user_name}! System status: All systems operational 🟢")

507

508

# Optional: Post to admin channel

509

if command.get("text") == "admin":

510

client.chat_postMessage(

511

channel="#admin-alerts",

512

text=f"Status check requested by {user_name}"

513

)

514

515

except Exception as e:

516

logger.exception("Failed to process status command")

517

respond("Sorry, there was an error processing your request.")

518

```

519

520

### Modal Interaction Flow

521

522

```python

523

@app.action("create_ticket")

524

def open_ticket_modal(ack, body, client):

525

"""Open ticket creation modal."""

526

ack()

527

528

modal_view = {

529

"type": "modal",

530

"callback_id": "ticket_modal",

531

"title": {"type": "plain_text", "text": "Create Support Ticket"},

532

"submit": {"type": "plain_text", "text": "Create"},

533

"blocks": [

534

{

535

"type": "input",

536

"block_id": "title_block",

537

"element": {

538

"type": "plain_text_input",

539

"action_id": "title_input",

540

"placeholder": {"type": "plain_text", "text": "Brief description"}

541

},

542

"label": {"type": "plain_text", "text": "Issue Title"}

543

},

544

{

545

"type": "input",

546

"block_id": "priority_block",

547

"element": {

548

"type": "static_select",

549

"action_id": "priority_select",

550

"options": [

551

{"text": {"type": "plain_text", "text": "Low"}, "value": "low"},

552

{"text": {"type": "plain_text", "text": "Medium"}, "value": "medium"},

553

{"text": {"type": "plain_text", "text": "High"}, "value": "high"}

554

]

555

},

556

"label": {"type": "plain_text", "text": "Priority"}

557

}

558

]

559

}

560

561

client.views_open(trigger_id=body["trigger_id"], view=modal_view)

562

563

@app.view_submission("ticket_modal")

564

def handle_ticket_submission(ack, body, view, client, logger):

565

"""Handle ticket creation form submission."""

566

567

# Extract form data

568

values = view["state"]["values"]

569

title = values["title_block"]["title_input"]["value"]

570

priority = values["priority_block"]["priority_select"]["selected_option"]["value"]

571

572

# Validate input

573

if len(title) < 5:

574

ack({

575

"response_action": "errors",

576

"errors": {

577

"title_block": "Title must be at least 5 characters"

578

}

579

})

580

return

581

582

# Create ticket

583

try:

584

ticket_id = create_support_ticket(title, priority, body["user"]["id"])

585

logger.info(f"Created ticket {ticket_id} for user {body['user']['id']}")

586

587

# Success - close modal and notify user

588

ack({

589

"response_action": "clear"

590

})

591

592

# Send confirmation DM

593

client.chat_postMessage(

594

channel=body["user"]["id"],

595

text=f"✅ Support ticket #{ticket_id} created successfully!\n"

596

f"*Title:* {title}\n"

597

f"*Priority:* {priority.title()}"

598

)

599

600

except Exception as e:

601

logger.exception("Failed to create support ticket")

602

ack({

603

"response_action": "errors",

604

"errors": {

605

"title_block": "Failed to create ticket. Please try again."

606

}

607

})

608

```

609

610

## Related Topics

611

612

- [Event Listeners & Request Handling](./event-listeners.md) - How to set up event handlers

613

- [Web Framework Integration](./framework-integration.md) - Using context objects with different frameworks

614

- [OAuth & Multi-Workspace Installation](./oauth-and-installation.md) - Multi-workspace context patterns