Skip to content

Commit a5a2e5b

Browse files
zimegWilliamBergaminmwbrookslukegalbraithrussell
authored
feat: add ai-enabled features text streaming methods, feedback blocks, and loading state (#1766)
Co-authored-by: William Bergamin <[email protected]> Co-authored-by: Michael Brooks <[email protected]> Co-authored-by: Luke Russell <[email protected]>
1 parent 82aad20 commit a5a2e5b

34 files changed

+5805
-439
lines changed

docs/english/web.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ except SlackApiError as e:
3333
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'
3434
```
3535

36+
### Sending ephemeral messages
37+
3638
Sending an ephemeral message, which is only visible to an assigned user in a specified channel, is nearly the same as sending a regular message but with an additional `user` parameter.
3739

3840
``` python
@@ -51,6 +53,114 @@ response = client.chat_postEphemeral(
5153

5254
See the [`chat.postEphemeral`](/reference/methods/chat.postEphemeral) API method for more details.
5355

56+
### Sending streaming messages {#sending-streaming-messages}
57+
58+
You can have your app's messages stream in to replicate conventional AI chatbot behavior. This is done through three Web API methods:
59+
60+
* [`chat_startStream`](/reference/methods/chat.startstream)
61+
* [`chat_appendStream`](/reference/methods/chat.appendstream)
62+
* [`chat_stopStream`](/reference/methods/chat.stopstream)
63+
64+
:::tip[The Python Slack SDK provides a [`chat_stream()`](https://docs.slack.dev/tools/python-slack-sdk/reference/web/client.html#slack_sdk.web.client.WebClient.chat_stream) helper utility to streamline calling these methods.]
65+
66+
See the [_Streaming messages_](/tools/bolt-python/concepts/message-sending#streaming-messages) section of the Bolt for Python docs for implementation instructions.
67+
68+
:::
69+
70+
#### Starting the message stream {#starting-stream}
71+
72+
First you need to begin the message stream:
73+
74+
```python
75+
# Example: Stream a response to any message
76+
@app.message()
77+
def handle_message(message, client):
78+
channel_id = event.get("channel")
79+
team_id = event.get("team")
80+
thread_ts = event.get("thread_ts") or event.get("ts")
81+
user_id = event.get("user")
82+
83+
# Start a new message stream
84+
stream_response = client.chat_startStream(
85+
channel=channel_id,
86+
recipient_team_id=team_id,
87+
recipient_user_id=user_id,
88+
thread_ts=thread_ts,
89+
)
90+
stream_ts = stream_response["ts"]
91+
```
92+
93+
#### Appending content to the message stream {#appending-stream}
94+
95+
With the stream started, you can then append text to it in chunks to convey a streaming effect.
96+
97+
The structure of the text coming in will depend on your source. The following code snippet uses OpenAI's response structure as an example:
98+
99+
```python
100+
# continued from above
101+
for event in returned_message:
102+
if event.type == "response.output_text.delta":
103+
client.chat_appendStream(
104+
channel=channel_id,
105+
ts=stream_ts,
106+
markdown_text=f"{event.delta}"
107+
)
108+
else:
109+
continue
110+
```
111+
112+
#### Stopping the message stream {#stopping-stream}
113+
114+
Your app can then end the stream with the `chat_stopStream` method:
115+
116+
```python
117+
# continued from above
118+
client.chat_stopStream(
119+
channel=channel_id,
120+
ts=stream_ts
121+
)
122+
```
123+
124+
The method also provides you an opportunity to request user feedback on your app's responses using the [feedback buttons](/reference/block-kit/block-elements/feedback-buttons-element) block element within the [context actions](/reference/block-kit/blocks/context-actions-block) block. The user will be presented with thumbs up and thumbs down buttons which send an action to your app when pressed.
125+
126+
```python
127+
def create_feedback_block() -> List[Block]:
128+
blocks: List[Block] = [
129+
ContextActionsBlock(
130+
elements=[
131+
FeedbackButtonsElement(
132+
action_id="feedback",
133+
positive_button=FeedbackButtonObject(
134+
text="Good Response",
135+
accessibility_label="Submit positive feedback on this response",
136+
value="good-feedback",
137+
),
138+
negative_button=FeedbackButtonObject(
139+
text="Bad Response",
140+
accessibility_label="Submit negative feedback on this response",
141+
value="bad-feedback",
142+
),
143+
)
144+
]
145+
)
146+
]
147+
return blocks
148+
149+
@app.message()
150+
def handle_message(message, client):
151+
# ... previous streaming code ...
152+
153+
# Stop the stream and add interactive elements
154+
feedback_block = create_feedback_block()
155+
client.chat_stopStream(
156+
channel=channel_id,
157+
ts=stream_ts,
158+
blocks=feedback_block
159+
)
160+
```
161+
162+
See [Formatting messages with Block Kit](#block-kit) below for more details on using Block Kit with messages.
163+
54164
## Formatting messages with Block Kit {#block-kit}
55165

56166
Messages posted from apps can contain more than just text; they can also include full user interfaces composed of blocks using [Block Kit](/block-kit).

0 commit comments

Comments
 (0)