Slack AI App thread not listed in History tab unless user sends a message
We're using the Slack Python Bolt SDK to build an AI assistant app via the AI Apps framework, and we're seeing a behavior that feels inconsistent with user expectations. I’d like to confirm if this is expected or a UI bug.
Reproducible in:
The slack_bolt version
slack_bolt==1.23.0
slack_sdk==3.35.0
Python runtime version
Python 3.12.9
OS info
Runtime: AWS Lambda using Python 3.12 (x86_64)
Steps to reproduce:
-
A user clicks New Chat from the Slack AI app UI.
-
We handle the
@assistant.thread_startedevent:- Use
say(...)to post an intro block in the new thread - Run an async lazy function to post a personalized greeting via OpenAI Responses API
- Save context including
previous_response_idto maintain thread state
- Use
-
User does not send a message (so
@assistant.user_messagenever fires) -
User later checks the “History” tab
Expected result:
The newly created thread should appear in the History tab since:
- It was created via the Slack AI App interface
- The assistant replied with multiple messages (intro and greeting)
- Thread context was set and persisted
- A title was optionally set via
set_title(...)
Actual result:
If the user never sends a message, the thread is never listed in the History tab. It seems the thread only appears in History once the @assistant.user_message listener is triggered. Returning to the Chat tab sends them to a prior thread. From the user's point of view, the newly created chat is "lost."
Additional context:
- This behavior is leading to confusion. We serve this app to ~3,000 users, and some are reporting that the assistant "lost their chat" or that the rename feature (which updates the thread title) is broken, since renamed threads also don't show up in History unless the user has sent a message.
- We use OpenAI’s Responses API to personalize each chat on
thread_started, and we trackprevious_response_idfor continuity. Users reasonably expect that chat context to persist. - We also attempted using
set_title(...)andset_status(...)early in the thread but that did not impact visibility in History.
Relevant code sample:
Below is a simplified version of our implementation to clarify how we're handling the @assistant.thread_started event and related logic:
def initialize_app() -> App:
try:
slack_settings = load_slack_settings()
app = App(
token=slack_settings.token,
signing_secret=slack_settings.signing_secret,
process_before_response=True,
logger=base_logger,
ignoring_self_assistant_message_events_enabled=False,
)
app.use(assistant)
return app
except ValueError as e:
base_logger.error("Failed to initialize Slack app: %s", e)
raise
app = initialize_app()
def get_slack_handler() -> SlackRequestHandler:
"""Return a pre-constructed handler for aws.main."""
return SlackRequestHandler(app=app)
@assistant.thread_started(lazy=[process_thread_start_async])
def handle_thread_start_ack(
req: BoltRequest,
ack: Ack,
logger: Logger,
payload: Dict[str, Any],
set_suggested_prompts: SetSuggestedPrompts,
set_status: SetStatus,
say: Say,
) -> None:
"""
Sync handler: acknowledge event and return immediately.
All heavier work lives in process_thread_start_async.
"""
ack()
...
combined_blocks = build_combined_intro_blocks(channel_id, thread_ts)
say(blocks=combined_blocks)
return
def process_thread_start_async(
say: Say,
payload: Dict[str, Any],
logger: Logger,
save_thread_context: SaveThreadContext,
set_suggested_prompts: SetSuggestedPrompts,
client: WebClient,
set_status: SetStatus,
set_title: SetTitle,
) -> None:
try:
context = extract_thread_context(payload)
set_title(f"Untitled - {now.strftime('%Y-%m-%d %H:%M:%S')}")
set_status("Setting up your personalized workspace...")
greeting_prompts = build_greeting_prompts(user_id=user_id)
greeting_msg, resp_id = process_greeting_flow(
user_id=user_id,
user_message=get_greeting_user_message(),
developer_prompts=greeting_prompts,
logger=logger,
)
context["previous_response_id"] = resp_id
save_thread_context(context)
say(greeting_msg)
except Exception as e:
logger.error(
"process_thread_start_async - unexpected error: %s", e, exc_info=True
)
Requirements
Is this behavior expected? If so, is there any way to ensure a thread is surfaced in the History tab even without a user message? Or is this a current limitation in Slack’s AI App frontend?
Thanks for your time and support!
Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.
Hey @noelmendoza-sam! 👋 Thanks for sharing these cases with an example 📚 ✨
If the user never sends a message, the thread is never listed in the History tab.
This is expected behavior at this time with the intention of avoiding handfuls of "abandoned" threads where someone might've clicked "New chat" without continuing the conversation.
A related note on this exists in documentation:
The user then will type a message or click on a prompt which will trigger a
message.imevent. The event will be the same whether the user clicked the suggested prompt or typed it manually. Users will be able to message your app via the container or through your app's Chat tab.
https://docs.slack.dev/ai/developing-ai-apps#listen-message-im
But I do understand this can be confusing behavior. I'll share this feedback about the chats appearing as missing and making the History tab more clear in documentation.
Please let us know of other questions around this or elsewise whenever! 👾
Thanks @zimeg for the clarification! That makes sense from a technical standpoint. I appreciate you walking through the expected behavior and the rationale behind preventing abandoned threads.
That said, I wanted to share some context from our side that might be helpful for your product team:
Our app is live with thousands of users, and we've implemented a fairly guided onboarding experience inside @assistant.thread_started, including a personalized greeting via OpenAI’s Responses API and full thread context persistence.
Since users see a greeting message and can rename the chat using our custom title setter, they naturally perceive the thread as "active" or "in progress."
When they later return and don't see that chat in the History tab, many assume the app is broken or that their conversation was lost, even though everything functioned as intended behind the scenes.
I completely understand the concern about clutter from abandoned threads, but from a UX perspective, the current behavior feels unintuitive. Especially for users expecting a ChatGPT experience (?).
Some suggestions that might help improve this experience:
-
Consider exposing a way for developers to mark a thread as "persistent," even if the user hasn’t sent a message yet.
-
Alternatively, offering users a native way to delete chats from History could help manage clutter more gracefully.
-
And if nothing else, clarifying in documentation that threads only appear in History once a user message is received (@assistant.user_message) would help align expectations.
Really appreciate the thoughtful response. Just wanted to surface this as user-facing friction we're seeing in practice. Happy to provide any more detail if helpful!
👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.
As this issue has been inactive for more than one month, we will be closing it. Thank you to all the participants! If you would like to raise a related issue, please create a new issue which includes your specific details and references this issue number.