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