From 6b9123a9599fa89257036b059a1b785353da5f5e Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Mon, 22 Jun 2026 22:27:07 -0700 Subject: [PATCH] feat: update app manifest to use agent_view Flips all three implementations from assistant_view to agent_view in preparation for the new Agent DM Messages Tab experience: - Rename features.assistant_view -> features.agent_view in every manifest, and the inner assistant_description -> agent_description. - Remove assistant_thread_started from event subscriptions. - Merge set_suggested_prompts into app_home_opened, gated on event["tab"] so the Home tab keeps publishing its Block Kit view and the Messages tab pins the suggested prompts. - Delete the now-unused assistant_thread_started.py handlers and refresh tests to cover both tab branches. The handler now calls client.assistant_threads_setSuggestedPrompts directly (the set_suggested_prompts middleware helper is only injected for assistant_thread_started). TODO(agent-dm-messages-tab) markers note where app_context_changed wiring will land once Bolt exposes the event type. --- claude-agent-sdk/listeners/events/__init__.py | 2 -- .../listeners/events/app_home_opened.py | 27 +++++++++++++++-- .../events/assistant_thread_started.py | 24 --------------- claude-agent-sdk/manifest.json | 5 ++-- .../tests/test_app_home_opened.py | 21 +++++++++++++- .../listeners/events/__init__.py | 2 -- .../listeners/events/app_home_opened.py | 29 +++++++++++++++++-- .../events/assistant_thread_started.py | 22 -------------- openai-agents-sdk/manifest.json | 5 ++-- .../tests/test_app_home_opened.py | 19 +++++++++++- pydantic-ai/listeners/events/__init__.py | 2 -- .../listeners/events/app_home_opened.py | 29 +++++++++++++++++-- .../events/assistant_thread_started.py | 22 -------------- pydantic-ai/manifest.json | 5 ++-- pydantic-ai/tests/test_app_home_opened.py | 19 +++++++++++- 15 files changed, 138 insertions(+), 95 deletions(-) delete mode 100644 claude-agent-sdk/listeners/events/assistant_thread_started.py delete mode 100644 openai-agents-sdk/listeners/events/assistant_thread_started.py delete mode 100644 pydantic-ai/listeners/events/assistant_thread_started.py diff --git a/claude-agent-sdk/listeners/events/__init__.py b/claude-agent-sdk/listeners/events/__init__.py index f9a1dfb..01f9e9e 100644 --- a/claude-agent-sdk/listeners/events/__init__.py +++ b/claude-agent-sdk/listeners/events/__init__.py @@ -2,12 +2,10 @@ from .app_home_opened import handle_app_home_opened from .app_mentioned import handle_app_mentioned -from .assistant_thread_started import handle_assistant_thread_started from .message import handle_message def register(app: AsyncApp): app.event("app_home_opened")(handle_app_home_opened) app.event("app_mention")(handle_app_mentioned) - app.event("assistant_thread_started")(handle_assistant_thread_started) app.event("message")(handle_message) diff --git a/claude-agent-sdk/listeners/events/app_home_opened.py b/claude-agent-sdk/listeners/events/app_home_opened.py index 1198092..2e725c6 100644 --- a/claude-agent-sdk/listeners/events/app_home_opened.py +++ b/claude-agent-sdk/listeners/events/app_home_opened.py @@ -7,12 +7,33 @@ from listeners.views.app_home_builder import build_app_home_view +SUGGESTED_PROMPTS = [ + {"title": "Write a Message", "message": "Help me draft a message to my team"}, + {"title": "Summarize", "message": "Can you help me summarize something?"}, + {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, +] + async def handle_app_home_opened( - client: AsyncWebClient, context: AsyncBoltContext, logger: Logger + client: AsyncWebClient, event: dict, context: AsyncBoltContext, logger: Logger ): - """Publish the App Home view when a user opens the app's Home tab.""" + """Handle app_home_opened events. + + Under agent_view, this event fires for both the Home tab and the Messages + tab (the agent DM). Branch on ``event["tab"]``: + * ``"messages"`` -- pin suggested prompts to the top of the DM. + * ``"home"`` -- publish the App Home Block Kit view. + """ try: + if event.get("tab") == "messages": + await client.assistant_threads_setSuggestedPrompts( + channel_id=event["channel"], + title="How can I help you today?", + prompts=SUGGESTED_PROMPTS, + ) + # TODO(agent-dm-messages-tab): handle app_context_changed once Bolt supports it + return + user_id = context.user_id install_url = None is_connected = False @@ -27,4 +48,4 @@ async def handle_app_home_opened( view = build_app_home_view(install_url=install_url, is_connected=is_connected) await client.views_publish(user_id=user_id, view=view) except Exception as e: - logger.exception(f"Failed to publish App Home: {e}") + logger.exception(f"Failed to handle app_home_opened: {e}") diff --git a/claude-agent-sdk/listeners/events/assistant_thread_started.py b/claude-agent-sdk/listeners/events/assistant_thread_started.py deleted file mode 100644 index 5185352..0000000 --- a/claude-agent-sdk/listeners/events/assistant_thread_started.py +++ /dev/null @@ -1,24 +0,0 @@ -from logging import Logger - -from slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts import ( - AsyncSetSuggestedPrompts, -) - -SUGGESTED_PROMPTS = [ - {"title": "Write a Message", "message": "Help me draft a message to my team"}, - {"title": "Summarize", "message": "Can you help me summarize something?"}, - {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, -] - - -async def handle_assistant_thread_started( - set_suggested_prompts: AsyncSetSuggestedPrompts, logger: Logger -): - """Handle assistant thread started events by setting suggested prompts.""" - try: - await set_suggested_prompts( - prompts=SUGGESTED_PROMPTS, - title="How can I help you today?", - ) - except Exception as e: - logger.exception(f"Failed to handle assistant thread started: {e}") diff --git a/claude-agent-sdk/manifest.json b/claude-agent-sdk/manifest.json index dce64d0..b459faa 100644 --- a/claude-agent-sdk/manifest.json +++ b/claude-agent-sdk/manifest.json @@ -3,8 +3,8 @@ "name": "Starter Agent - Claude SDK" }, "features": { - "assistant_view": { - "assistant_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", + "agent_view": { + "agent_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", "suggested_prompts": [] }, "app_home": { @@ -63,7 +63,6 @@ "bot_events": [ "app_home_opened", "app_mention", - "assistant_thread_started", "message.channels", "message.groups", "message.im" diff --git a/claude-agent-sdk/tests/test_app_home_opened.py b/claude-agent-sdk/tests/test_app_home_opened.py index 1c52f03..b5724b5 100644 --- a/claude-agent-sdk/tests/test_app_home_opened.py +++ b/claude-agent-sdk/tests/test_app_home_opened.py @@ -14,13 +14,15 @@ class TestAppHomeOpened: def setup_method(self): self.fake_client = Mock(AsyncWebClient) self.fake_client.views_publish = AsyncMock() + self.fake_client.assistant_threads_setSuggestedPrompts = AsyncMock() self.fake_context = Mock(AsyncBoltContext) self.fake_context.user_id = "U123" @pytest.mark.asyncio - async def test_publishes_home_view(self): + async def test_publishes_home_view_when_tab_is_home(self): await handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, ) @@ -29,6 +31,22 @@ async def test_publishes_home_view(self): kwargs = self.fake_client.views_publish.call_args.kwargs assert kwargs["user_id"] == "U123" assert kwargs["view"]["type"] == "home" + self.fake_client.assistant_threads_setSuggestedPrompts.assert_not_called() + + @pytest.mark.asyncio + async def test_sets_suggested_prompts_when_tab_is_messages(self): + await handle_app_home_opened( + client=self.fake_client, + event={"tab": "messages", "channel": "D123"}, + context=self.fake_context, + logger=test_logger, + ) + + self.fake_client.assistant_threads_setSuggestedPrompts.assert_called_once() + kwargs = self.fake_client.assistant_threads_setSuggestedPrompts.call_args.kwargs + assert kwargs["channel_id"] == "D123" + assert isinstance(kwargs["prompts"], list) + self.fake_client.views_publish.assert_not_called() @pytest.mark.asyncio async def test_views_publish_exception(self, caplog): @@ -36,6 +54,7 @@ async def test_views_publish_exception(self, caplog): await handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, ) diff --git a/openai-agents-sdk/listeners/events/__init__.py b/openai-agents-sdk/listeners/events/__init__.py index 206ad37..bf83b72 100644 --- a/openai-agents-sdk/listeners/events/__init__.py +++ b/openai-agents-sdk/listeners/events/__init__.py @@ -2,12 +2,10 @@ from .app_home_opened import handle_app_home_opened from .app_mentioned import handle_app_mentioned -from .assistant_thread_started import handle_assistant_thread_started from .message import handle_message def register(app: App): app.event("app_home_opened")(handle_app_home_opened) app.event("app_mention")(handle_app_mentioned) - app.event("assistant_thread_started")(handle_assistant_thread_started) app.event("message")(handle_message) diff --git a/openai-agents-sdk/listeners/events/app_home_opened.py b/openai-agents-sdk/listeners/events/app_home_opened.py index 47dc3d8..92a5cc0 100644 --- a/openai-agents-sdk/listeners/events/app_home_opened.py +++ b/openai-agents-sdk/listeners/events/app_home_opened.py @@ -7,10 +7,33 @@ from listeners.views.app_home_builder import build_app_home_view +SUGGESTED_PROMPTS = [ + {"title": "Write a Message", "message": "Help me draft a message to my team"}, + {"title": "Summarize", "message": "Can you help me summarize something?"}, + {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, +] -def handle_app_home_opened(client: WebClient, context: BoltContext, logger: Logger): - """Publish the App Home view when a user opens the app's Home tab.""" + +def handle_app_home_opened( + client: WebClient, event: dict, context: BoltContext, logger: Logger +): + """Handle app_home_opened events. + + Under agent_view, this event fires for both the Home tab and the Messages + tab (the agent DM). Branch on ``event["tab"]``: + * ``"messages"`` -- pin suggested prompts to the top of the DM. + * ``"home"`` -- publish the App Home Block Kit view. + """ try: + if event.get("tab") == "messages": + client.assistant_threads_setSuggestedPrompts( + channel_id=event["channel"], + title="How can I help you today?", + prompts=SUGGESTED_PROMPTS, + ) + # TODO(agent-dm-messages-tab): handle app_context_changed once Bolt supports it + return + user_id = context.user_id install_url = None is_connected = False @@ -25,4 +48,4 @@ def handle_app_home_opened(client: WebClient, context: BoltContext, logger: Logg view = build_app_home_view(install_url=install_url, is_connected=is_connected) client.views_publish(user_id=user_id, view=view) except Exception as e: - logger.exception(f"Failed to publish App Home: {e}") + logger.exception(f"Failed to handle app_home_opened: {e}") diff --git a/openai-agents-sdk/listeners/events/assistant_thread_started.py b/openai-agents-sdk/listeners/events/assistant_thread_started.py deleted file mode 100644 index e04d826..0000000 --- a/openai-agents-sdk/listeners/events/assistant_thread_started.py +++ /dev/null @@ -1,22 +0,0 @@ -from logging import Logger - -from slack_bolt.context.set_suggested_prompts import SetSuggestedPrompts - -SUGGESTED_PROMPTS = [ - {"title": "Write a Message", "message": "Help me draft a message to my team"}, - {"title": "Summarize", "message": "Can you help me summarize something?"}, - {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, -] - - -def handle_assistant_thread_started( - set_suggested_prompts: SetSuggestedPrompts, logger: Logger -): - """Handle assistant thread started events by setting suggested prompts.""" - try: - set_suggested_prompts( - prompts=SUGGESTED_PROMPTS, - title="How can I help you today?", - ) - except Exception as e: - logger.exception(f"Failed to handle assistant thread started: {e}") diff --git a/openai-agents-sdk/manifest.json b/openai-agents-sdk/manifest.json index 196846e..8296805 100644 --- a/openai-agents-sdk/manifest.json +++ b/openai-agents-sdk/manifest.json @@ -3,8 +3,8 @@ "name": "Starter Agent - OpenAI SDK" }, "features": { - "assistant_view": { - "assistant_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", + "agent_view": { + "agent_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", "suggested_prompts": [] }, "app_home": { @@ -63,7 +63,6 @@ "bot_events": [ "app_home_opened", "app_mention", - "assistant_thread_started", "message.channels", "message.groups", "message.im" diff --git a/openai-agents-sdk/tests/test_app_home_opened.py b/openai-agents-sdk/tests/test_app_home_opened.py index f9df038..96c4823 100644 --- a/openai-agents-sdk/tests/test_app_home_opened.py +++ b/openai-agents-sdk/tests/test_app_home_opened.py @@ -15,9 +15,10 @@ def setup_method(self): self.fake_context = Mock(BoltContext) self.fake_context.user_id = "U123" - def test_publishes_home_view(self): + def test_publishes_home_view_when_tab_is_home(self): handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, ) @@ -26,12 +27,28 @@ def test_publishes_home_view(self): kwargs = self.fake_client.views_publish.call_args.kwargs assert kwargs["user_id"] == "U123" assert kwargs["view"]["type"] == "home" + self.fake_client.assistant_threads_setSuggestedPrompts.assert_not_called() + + def test_sets_suggested_prompts_when_tab_is_messages(self): + handle_app_home_opened( + client=self.fake_client, + event={"tab": "messages", "channel": "D123"}, + context=self.fake_context, + logger=test_logger, + ) + + self.fake_client.assistant_threads_setSuggestedPrompts.assert_called_once() + kwargs = self.fake_client.assistant_threads_setSuggestedPrompts.call_args.kwargs + assert kwargs["channel_id"] == "D123" + assert isinstance(kwargs["prompts"], list) + self.fake_client.views_publish.assert_not_called() def test_views_publish_exception(self, caplog): self.fake_client.views_publish.side_effect = Exception("test exception") handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, ) diff --git a/pydantic-ai/listeners/events/__init__.py b/pydantic-ai/listeners/events/__init__.py index 206ad37..bf83b72 100644 --- a/pydantic-ai/listeners/events/__init__.py +++ b/pydantic-ai/listeners/events/__init__.py @@ -2,12 +2,10 @@ from .app_home_opened import handle_app_home_opened from .app_mentioned import handle_app_mentioned -from .assistant_thread_started import handle_assistant_thread_started from .message import handle_message def register(app: App): app.event("app_home_opened")(handle_app_home_opened) app.event("app_mention")(handle_app_mentioned) - app.event("assistant_thread_started")(handle_assistant_thread_started) app.event("message")(handle_message) diff --git a/pydantic-ai/listeners/events/app_home_opened.py b/pydantic-ai/listeners/events/app_home_opened.py index 47dc3d8..92a5cc0 100644 --- a/pydantic-ai/listeners/events/app_home_opened.py +++ b/pydantic-ai/listeners/events/app_home_opened.py @@ -7,10 +7,33 @@ from listeners.views.app_home_builder import build_app_home_view +SUGGESTED_PROMPTS = [ + {"title": "Write a Message", "message": "Help me draft a message to my team"}, + {"title": "Summarize", "message": "Can you help me summarize something?"}, + {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, +] -def handle_app_home_opened(client: WebClient, context: BoltContext, logger: Logger): - """Publish the App Home view when a user opens the app's Home tab.""" + +def handle_app_home_opened( + client: WebClient, event: dict, context: BoltContext, logger: Logger +): + """Handle app_home_opened events. + + Under agent_view, this event fires for both the Home tab and the Messages + tab (the agent DM). Branch on ``event["tab"]``: + * ``"messages"`` -- pin suggested prompts to the top of the DM. + * ``"home"`` -- publish the App Home Block Kit view. + """ try: + if event.get("tab") == "messages": + client.assistant_threads_setSuggestedPrompts( + channel_id=event["channel"], + title="How can I help you today?", + prompts=SUGGESTED_PROMPTS, + ) + # TODO(agent-dm-messages-tab): handle app_context_changed once Bolt supports it + return + user_id = context.user_id install_url = None is_connected = False @@ -25,4 +48,4 @@ def handle_app_home_opened(client: WebClient, context: BoltContext, logger: Logg view = build_app_home_view(install_url=install_url, is_connected=is_connected) client.views_publish(user_id=user_id, view=view) except Exception as e: - logger.exception(f"Failed to publish App Home: {e}") + logger.exception(f"Failed to handle app_home_opened: {e}") diff --git a/pydantic-ai/listeners/events/assistant_thread_started.py b/pydantic-ai/listeners/events/assistant_thread_started.py deleted file mode 100644 index e04d826..0000000 --- a/pydantic-ai/listeners/events/assistant_thread_started.py +++ /dev/null @@ -1,22 +0,0 @@ -from logging import Logger - -from slack_bolt.context.set_suggested_prompts import SetSuggestedPrompts - -SUGGESTED_PROMPTS = [ - {"title": "Write a Message", "message": "Help me draft a message to my team"}, - {"title": "Summarize", "message": "Can you help me summarize something?"}, - {"title": "Brainstorm", "message": "I need help brainstorming ideas"}, -] - - -def handle_assistant_thread_started( - set_suggested_prompts: SetSuggestedPrompts, logger: Logger -): - """Handle assistant thread started events by setting suggested prompts.""" - try: - set_suggested_prompts( - prompts=SUGGESTED_PROMPTS, - title="How can I help you today?", - ) - except Exception as e: - logger.exception(f"Failed to handle assistant thread started: {e}") diff --git a/pydantic-ai/manifest.json b/pydantic-ai/manifest.json index f9e3201..2c926c7 100644 --- a/pydantic-ai/manifest.json +++ b/pydantic-ai/manifest.json @@ -3,8 +3,8 @@ "name": "Starter Agent - Pydantic AI" }, "features": { - "assistant_view": { - "assistant_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", + "agent_view": { + "agent_description": "Hi, I am an agent built using Bolt for Python. I am here to help you out!", "suggested_prompts": [] }, "app_home": { @@ -63,7 +63,6 @@ "bot_events": [ "app_home_opened", "app_mention", - "assistant_thread_started", "message.channels", "message.groups", "message.im" diff --git a/pydantic-ai/tests/test_app_home_opened.py b/pydantic-ai/tests/test_app_home_opened.py index f9df038..96c4823 100644 --- a/pydantic-ai/tests/test_app_home_opened.py +++ b/pydantic-ai/tests/test_app_home_opened.py @@ -15,9 +15,10 @@ def setup_method(self): self.fake_context = Mock(BoltContext) self.fake_context.user_id = "U123" - def test_publishes_home_view(self): + def test_publishes_home_view_when_tab_is_home(self): handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, ) @@ -26,12 +27,28 @@ def test_publishes_home_view(self): kwargs = self.fake_client.views_publish.call_args.kwargs assert kwargs["user_id"] == "U123" assert kwargs["view"]["type"] == "home" + self.fake_client.assistant_threads_setSuggestedPrompts.assert_not_called() + + def test_sets_suggested_prompts_when_tab_is_messages(self): + handle_app_home_opened( + client=self.fake_client, + event={"tab": "messages", "channel": "D123"}, + context=self.fake_context, + logger=test_logger, + ) + + self.fake_client.assistant_threads_setSuggestedPrompts.assert_called_once() + kwargs = self.fake_client.assistant_threads_setSuggestedPrompts.call_args.kwargs + assert kwargs["channel_id"] == "D123" + assert isinstance(kwargs["prompts"], list) + self.fake_client.views_publish.assert_not_called() def test_views_publish_exception(self, caplog): self.fake_client.views_publish.side_effect = Exception("test exception") handle_app_home_opened( client=self.fake_client, + event={"tab": "home", "channel": "D123"}, context=self.fake_context, logger=test_logger, )