| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Full Changelog: v1.29.0...v1.30.0
Full Changelog: v1.28.0...v1.29.0
Bring magic to a conversation with say_stream for streaming messages and show loading status with set_status. Now available for app.event and app.message listeners:
@app.event("app_mention")
def handle_mention(say_stream, set_status):
set_status(
status="Thinking...",
loading_messages=["Waking up...", "Loading a witty response..."],
)
stream = say_stream(buffer_size=100)
stream.append(markdown_text="Thinking... :thinking_face:\n\n")
stream.append(markdown_text="Here is my response!")
stream.stop()Full Changelog: v1.27.0...v1.28.0
Milestone: https://github.com/slackapi/bolt-python/milestone/96
Package: https://pypi.org/project/slack-bolt/1.28.0/
Full Changelog: v1.26.0...v1.27.0
Milestone: https://github.com/slackapi/bolt-python/milestone/95?closed=1
Try the AI Agent Sample app to explore the AI-enabled features and existing Assistant helper:
# Create a new AI Agent app
$ slack create slack-ai-agent-app --template slack-samples/bolt-python-assistant-template
$ cd slack-ai-agent-app/
# Initialize Python Virtual Environment
$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt
# Add your OPENAI_API_KEY
$ export OPENAI_API_KEY=sk-proj-ahM...
# Run the local dev server
$ slack runAfter the app starts, send a message to the "slack-ai-agent-app" bot for a unique response.
Loading states allows you to not only set the status (e.g. "My app is typing...") but also sprinkle some personality by cycling through a collection of loading messages.
Bolt Assistant Class usage:
@assistant.user_message
def respond_in_assistant_thread(
client: WebClient,
context: BoltContext,
get_thread_context: GetThreadContext,
logger: Logger,
payload: dict,
say: Say,
set_status: SetStatus,
):
set_status(
status="thinking...",
loading_messages=[
"Teaching the hamsters to type faster…",
"Untangling the internet cables…",
"Consulting the office goldfish…",
"Polishing up the response just for you…",
"Convincing the AI to stop overthinking…",
],
)Web Client SDK usage:
@app.message()
def handle_message(client, context, event, message):
client.assistant_threads_setStatus(
channel_id=channel_id,
thread_ts=thread_ts,
status="thinking...",
loading_messages=[
"Teaching the hamsters to type faster…",
"Untangling the internet cables…",
"Consulting the office goldfish…",
"Polishing up the response just for you…",
"Convincing the AI to stop overthinking…",
],
)
# Start a new message streamThe chat_stream() helper utility can be used to streamline calling the 3 text streaming methods:
# Start a new message stream
streamer = client.chat_stream(
channel=channel_id,
recipient_team_id=team_id,
recipient_user_id=user_id,
thread_ts=thread_ts,
)
# Loop over OpenAI response stream
# https://platform.openai.com/docs/api-reference/responses/create
for event in returned_message:
if event.type == "response.output_text.delta":
streamer.append(markdown_text=f"{event.delta}")
else:
continue
feedback_block = create_feedback_block()
streamer.stop(blocks=feedback_block)Alternative to the Text Streaming Helper is to call the individual methods.
First, start a chat text stream to stream a response to any message:
@app.message()
def handle_message(message, client, context, event, message):
# Start a new message stream
stream_response = client.chat_startStream(
channel=channel_id,
recipient_team_id=team_id,
recipient_user_id=user_id,
thread_ts=thread_ts,
)
stream_ts = stream_response["ts"]After starting a chat text stream, you can then append text to it in chunks (often from your favourite LLM SDK) to convey a streaming effect:
for event in returned_message:
if event.type == "response.output_text.delta":
client.chat_appendStream(
channel=channel_id,
ts=stream_ts,
markdown_text=f"{event.delta}"
)
else:
continueLastly, you can stop the chat text stream to finalize your message:
client.chat_stopStream(
channel=channel_id,
ts=stream_ts,
blocks=feedback_block
)Add feedback buttons to the bottom of a message, after stopping a text stream, to gather user feedback:
def create_feedback_block() -> List[Block]:
blocks: List[Block] = [
ContextActionsBlock(
elements=[
FeedbackButtonsElement(
action_id="feedback",
positive_button=FeedbackButtonObject(
text="Good Response",
accessibility_label="Submit positive feedback on this response",
value="good-feedback",
),
negative_button=FeedbackButtonObject(
text="Bad Response",
accessibility_label="Submit negative feedback on this response",
value="bad-feedback",
),
)
]
)
]
return blocks
@app.message()
def handle_message(message, client):
# ... previous streaming code ...
# Stop the stream and add feedback buttons
feedback_block = create_feedback_block()
client.chat_stopStream(
channel=channel_id,
ts=stream_ts,
blocks=feedback_block
)response = client.chat_postMessage(
channel="C111",
markdown_text=markdown_content,
)Learn more in slackapi/python-slack-sdk#1718
📚 https://docs.slack.dev/reference/block-kit/blocks/markdown-block/
from slack_sdk.models.blocks import MarkdownBlock
...
@app.message("hello")
def message_hello(say):
say(
blocks=[
MarkdownBlock(text="**lets's go!**"),
],
text="let's go!",
)Learn more in slackapi/python-slack-sdk#1748
Add support for the workflows.featured.{add|list|remove|set} methods:
app.client.workflows_featured_add(channel_id="C0123456789", trigger_ids=["Ft0123456789"])
app.client.workflows_featured_list(channel_ids="C0123456789")
app.client.workflows_featured_remove(channel_id="C0123456789", trigger_ids=["Ft0123456789"])
app.client.workflows_featured_set(channel_id="C0123456789", trigger_ids=["Ft0123456789"])Learn more in slackapi/python-slack-sdk#1712
Milestone: https://github.com/slackapi/bolt-python/milestone/94?closed=1
Full Changelog: v1.25.0...v1.26.0
Package: https://pypi.org/project/slack-bo...
We've fixed a regression around the logger, by default the logger used by the WebClient will be the same as the one used by the Bolt application. If the WebClient defines its own logger then it will be used:
my_logger = logging.getLogger("my_logger")
app = App(client=WebClient(token=os.environ.get("SLACK_BOT_TOKEN"), logger=my_logger))
@app.command("/sample-command")
def sample_command(ack: Ack, client: WebClient):
ack()
assert client.logger.name == my_logger.name| Back | FazBrowse Home | New Git URL |