Skip to content

Conversation

@zimeg
Copy link
Member

@zimeg zimeg commented Jan 14, 2026

Summary

This PR adds the plan_update chunk for updating the plan block title in chat streams.

Testing

The following shows the plan block title updating after each few seconds:

import time
# ...

streamer = client.chat_stream(
    channel="C0123456789",
    recipient_team_id="T0123456789",
    recipient_user_id="U0123456789",
    thread_ts="17000000000.00000",
    task_display_mode="plan",
)

streamer.append(
    chunks=[
        MarkdownTextChunk(
            text="Hello.\nI have received the task. ",
        ),
        MarkdownTextChunk(
            text="This task appears manageable.\nThat is good.",
        ),
        TaskUpdateChunk(
            id="001",
            title="Understanding the task...",
            status="in_progress",
            details="- Identifying the goal\n- Identifying constraints",
        ),
        TaskUpdateChunk(
            id="002",
            title="Performing acrobatics...",
            status="pending",
        ),
    ],
)
time.sleep(4)

streamer.append(
    chunks=[
        PlanUpdateChunk(
            title="Adding the final pieces...",
        ),
        TaskUpdateChunk(
            id="001",
            title="Understanding the task...",
            status="complete",
            details="\n- Pretending this was obvious",
            output="We'll continue to ramble now",
        ),
        TaskUpdateChunk(
            id="002",
            title="Performing acrobatics...",
            status="in_progress",
        ),
    ],
)
time.sleep(4)

streamer.stop(
    chunks=[
        TaskUpdateChunk(
            id="002",
            title="Performing acrobatics...",
            status="complete",
            details="- Jumped atop ropes\n- Juggled bowling pins\n- Rode a single wheel too",
        ),
        MarkdownTextChunk(
            text="The crowd appears to be astouned and applauds :popcorn:"
        ),
        PlanUpdateChunk(
            title="Celebrating a job well done!",
        ),
    ],
)

Category

  • slack_sdk.models (UI component builders)
  • /docs (Documents)
  • tests/integration_tests (Automated tests for this library)

Requirements

  • I've read and understood the Contributing Guidelines and have done my best effort to follow them.
  • I've read and agree to the Code of Conduct.
  • I've run python3 -m venv .venv && source .venv/bin/activate && ./scripts/run_validation.sh after making the changes.

@zimeg zimeg requested review from mwbrooks and srtaalej January 14, 2026 00:06
@zimeg zimeg self-assigned this Jan 14, 2026
@zimeg zimeg added enhancement M-T: A feature request for new functionality Version: 3x labels Jan 14, 2026
@codecov
Copy link

codecov bot commented Jan 14, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.93%. Comparing base (7c32814) to head (4d355da).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
slack_sdk/models/messages/chunk.py 81.81% 2 Missing ⚠️
Additional details and impacted files
@@                          Coverage Diff                           @@
##           zimeg-feat-ai-apps-chunks-streamer    #1821      +/-   ##
======================================================================
- Coverage                               83.93%   83.93%   -0.01%     
======================================================================
  Files                                     116      116              
  Lines                                   13192    13203      +11     
======================================================================
+ Hits                                    11073    11082       +9     
- Misses                                   2119     2121       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@zimeg zimeg marked this pull request as ready for review January 14, 2026 20:09
@zimeg zimeg requested a review from a team as a code owner January 14, 2026 20:09
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌟

super().__init__(type=self.type)
show_unknown_key_warning(self, others)

self.title = title
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for getting clarification on what this chunk should look like 😸

Copy link
Member

@mwbrooks mwbrooks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Thanks for adding the plan_update chunk!

🧪 Local testing works well on my side. Thanks for the code sample.

✅ The code looks good and it works well for me! In case others want to check, I'll include my listeners/assistant/message.py from the sample app.

bolt-python-assistant-template/listeners/assistant/message.py:
from logging import Logger
from typing import Dict, List

from slack_bolt import BoltContext, Say, SetStatus
from slack_sdk import WebClient

from ai.llm_caller import call_llm

from ..views.feedback_block import create_feedback_block

import time
from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk, URLSource, PlanUpdateChunk


def message(
    client: WebClient,
    context: BoltContext,
    logger: Logger,
    payload: dict,
    say: Say,
    set_status: SetStatus,
):
    """
    Handles when users send messages or select a prompt in an assistant thread and generate AI responses:

    Args:
        client: Slack WebClient for making API calls
        context: Bolt context containing channel and thread information
        logger: Logger instance for error tracking
        payload: Event payload with message details (channel, user, text, etc.)
        say: Function to send messages to the thread
        set_status: Function to update the assistant's status
    """
    try:
        channel_id = payload["channel"]
        team_id = context.team_id
        thread_ts = payload["thread_ts"]
        user_id = context.user_id

        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…",
            ],
        )

        replies = client.conversations_replies(
            channel=context.channel_id,
            ts=context.thread_ts,
            oldest=context.thread_ts,
            limit=10,
        )
        messages_in_thread: List[Dict[str, str]] = []
        for message in replies["messages"]:
            role = "user" if message.get("bot_id") is None else "assistant"
            messages_in_thread.append({"role": role, "content": message["text"]})

        streamer = client.chat_stream(
            channel=channel_id,
            recipient_team_id=team_id,
            recipient_user_id=user_id,
            thread_ts=thread_ts,
            task_display_mode="plan",
        )

        streamer.append(
            chunks=[
                MarkdownTextChunk(
                    text="Hello.\nI have received the task. ",
                ),
                MarkdownTextChunk(
                    text="This task appears manageable.\nThat is good.",
                ),
                TaskUpdateChunk(
                    id="001",
                    title="Understanding the task...",
                    status="in_progress",
                    details="- Identifying the goal\n- Identifying constraints",
                ),
                TaskUpdateChunk(
                    id="002",
                    title="Performing acrobatics...",
                    status="pending",
                ),
            ],
        )
        time.sleep(4)

        streamer.append(
            chunks=[
                PlanUpdateChunk(
                    title="Adding the final pieces...",
                ),
                TaskUpdateChunk(
                    id="001",
                    title="Understanding the task...",
                    status="complete",
                    details="\n- Pretending this was obvious",
                    output="We'll continue to ramble now",
                ),
                TaskUpdateChunk(
                    id="002",
                    title="Performing acrobatics...",
                    status="in_progress",
                ),
            ],
        )
        time.sleep(4)

        streamer.stop(
            chunks=[
                TaskUpdateChunk(
                    id="002",
                    title="Performing acrobatics...",
                    status="complete",
                    details="- Jumped atop ropes\n- Juggled bowling pins\n- Rode a single wheel too",
                ),
                MarkdownTextChunk(
                    text="The crowd appears to be astound and applauds :popcorn:"
                ),
                PlanUpdateChunk(
                    title="Celebrating a job well done!",
                ),
            ],
        )

    except Exception as e:
        logger.exception(f"Failed to handle a user message event: {e}")
        say(f":warning: Something went wrong! ({e})")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement M-T: A feature request for new functionality semver:minor Version: 3x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants