From b541f6d08a0fea0ff092b13a2102b571a1518df6 Mon Sep 17 00:00:00 2001 From: Johannes du Plessis Date: Fri, 8 May 2026 14:51:28 -0700 Subject: [PATCH] slack: slim down the trace reply (drop greeting, suppress unfurl) (#1278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that assistant.threads.setStatus carries the "is thinking…" indicator, the per-run greeting phrase + auto-unfurl on the LangSmith link are just visual noise stacking on top of it. The trace reply now posts only `` + a tip, with link unfurling off so the smith.langchain.com card no longer appears. Adds an `unfurl_links`/`unfurl_media` knob to post_slack_thread_reply_with_ts (default-on to preserve behaviour for every other caller). --- agent/utils/slack.py | 44 +++++++++++-------------- agent/webapp.py | 4 +-- tests/test_github_issue_webhook.py | 6 +--- tests/test_slack_context.py | 53 +++++++++++++++++------------- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/agent/utils/slack.py b/agent/utils/slack.py index 55b86121..bac041f7 100644 --- a/agent/utils/slack.py +++ b/agent/utils/slack.py @@ -334,15 +334,24 @@ async def set_slack_assistant_status( return False -async def post_slack_thread_reply_with_ts(channel_id: str, thread_ts: str, text: str) -> str | None: +async def post_slack_thread_reply_with_ts( + channel_id: str, + thread_ts: str, + text: str, + *, + unfurl_links: bool = True, + unfurl_media: bool = True, +) -> str | None: """Post a reply in a Slack thread and return its Slack timestamp.""" if not SLACK_BOT_TOKEN: return None - payload = { + payload: dict[str, Any] = { "channel": channel_id, "thread_ts": thread_ts, "text": text, + "unfurl_links": unfurl_links, + "unfurl_media": unfurl_media, } async with httpx.AsyncClient() as http_client: @@ -682,19 +691,6 @@ async def resolve_slack_links_in_context( return resolved_links_section, image_urls -TRACE_REPLY_PHRASES: tuple[str, ...] = ( - "Working on it!", - "On it!", - "Diving in!", - "Powering up!", - "Heads down.", - "Cracking knuckles...", - "Spinning up...", - "Looking...", - "Time to cook. 🧑‍🍳", - "Running to the roar!", -) - TRACE_REPLY_TIPS: tuple[str, ...] = ( "You can message me in this thread while I'm running — I'll pick up your follow-up before my next step.", "Kick off another task in parallel — each one runs in its own isolated sandbox, no queuing.", @@ -707,22 +703,22 @@ TRACE_REPLY_TIPS: tuple[str, ...] = ( ) -def _format_trace_reply(message: str, trace_url: str | None) -> str: +def _format_trace_reply(trace_url: str | None) -> str: """Format the initial trace reply with a randomly selected tip.""" tip = random.choice(TRACE_REPLY_TIPS) - head = f"{message} <{trace_url}|View trace>" if trace_url else message - return f"{head}\n_Tip: {tip}_" + head = f"<{trace_url}|View trace>\n" if trace_url else "" + return f"{head}_Tip: {tip}_" -async def post_slack_trace_reply( - channel_id: str, thread_ts: str, thread_id: str, message: str | None = None -) -> str | None: +async def post_slack_trace_reply(channel_id: str, thread_ts: str, thread_id: str) -> str | None: """Post a trace URL reply in a Slack thread and return its Slack timestamp.""" - if message is None: - message = random.choice(TRACE_REPLY_PHRASES) trace_url = get_langsmith_trace_url(thread_id) return await post_slack_thread_reply_with_ts( - channel_id, thread_ts, _format_trace_reply(message, trace_url) + channel_id, + thread_ts, + _format_trace_reply(trace_url), + unfurl_links=False, + unfurl_media=False, ) diff --git a/agent/webapp.py b/agent/webapp.py index d507ed04..f51c6014 100644 --- a/agent/webapp.py +++ b/agent/webapp.py @@ -1021,9 +1021,7 @@ async def process_slack_pr_review_request( if result.get("success"): thread_id = result.get("thread_id") if isinstance(thread_id, str) and thread_id: - await post_slack_trace_reply( - channel_id, thread_ts, thread_id, message="Taking a look..." - ) + await post_slack_trace_reply(channel_id, thread_ts, thread_id) await set_slack_assistant_status(channel_id, thread_ts) return diff --git a/tests/test_github_issue_webhook.py b/tests/test_github_issue_webhook.py index d98591d9..48e40925 100644 --- a/tests/test_github_issue_webhook.py +++ b/tests/test_github_issue_webhook.py @@ -603,14 +603,11 @@ def test_process_slack_pr_review_request_posts_trace_reply(monkeypatch) -> None: captured["slack_thread_ts"] = slack_thread_ts return {"success": True, "thread_id": "reviewer-thread-id", "pr_url": pr_ref.url} - async def fake_post_slack_trace_reply( - channel_id: str, thread_ts: str, thread_id: str, message: str = "Working on it!" - ) -> None: + async def fake_post_slack_trace_reply(channel_id: str, thread_ts: str, thread_id: str) -> None: captured["trace_reply"] = { "channel_id": channel_id, "thread_ts": thread_ts, "thread_id": thread_id, - "message": message, } async def fake_set_slack_assistant_status(channel_id: str, thread_ts: str) -> bool: @@ -641,7 +638,6 @@ def test_process_slack_pr_review_request_posts_trace_reply(monkeypatch) -> None: "channel_id": "C123", "thread_ts": "1700000000.000100", "thread_id": "reviewer-thread-id", - "message": "Taking a look...", } assert captured["status_calls"] == [ ("C123", "1700000000.000100"), diff --git a/tests/test_slack_context.py b/tests/test_slack_context.py index adeb883f..472ef46c 100644 --- a/tests/test_slack_context.py +++ b/tests/test_slack_context.py @@ -5,7 +5,6 @@ import pytest from agent import webapp from agent.utils import slack as slack_utils from agent.utils.slack import ( - TRACE_REPLY_PHRASES, TRACE_REPLY_TIPS, convert_mentions_to_slack_format, format_slack_messages_for_prompt, @@ -222,15 +221,20 @@ def test_format_slack_messages_for_prompt_replaces_bot_id_mention_in_text() -> N assert formatted == "@alice(U123): @open-swe status update?" -def test_post_slack_trace_reply_picks_random_phrase_when_no_message( +def test_post_slack_trace_reply_emits_tip_only_when_no_trace_url( monkeypatch: pytest.MonkeyPatch, ) -> None: - posted: list[str] = [] + posted: list[dict] = [] async def fake_post_slack_thread_reply_with_ts( - channel_id: str, thread_ts: str, text: str + channel_id: str, + thread_ts: str, + text: str, + *, + unfurl_links: bool = True, + unfurl_media: bool = True, ) -> str | None: - posted.append(text) + posted.append({"text": text, "unfurl_links": unfurl_links, "unfurl_media": unfurl_media}) return "1.1" monkeypatch.setattr( @@ -241,35 +245,44 @@ def test_post_slack_trace_reply_picks_random_phrase_when_no_message( asyncio.run(post_slack_trace_reply("C123", "1.0", "thread-id")) assert len(posted) == 1 - head, _, tip_line = posted[0].partition("\n") - assert head in TRACE_REPLY_PHRASES - assert tip_line.startswith("_Tip: ") and tip_line.endswith("_") - assert any(tip in tip_line for tip in TRACE_REPLY_TIPS) + text = posted[0]["text"] + assert text.startswith("_Tip: ") and text.endswith("_") + assert any(tip in text for tip in TRACE_REPLY_TIPS) + assert posted[0]["unfurl_links"] is False + assert posted[0]["unfurl_media"] is False -def test_post_slack_trace_reply_uses_explicit_message_when_provided( +def test_post_slack_trace_reply_includes_trace_link_and_tip( monkeypatch: pytest.MonkeyPatch, ) -> None: - posted: list[str] = [] + posted: list[dict] = [] async def fake_post_slack_thread_reply_with_ts( - channel_id: str, thread_ts: str, text: str + channel_id: str, + thread_ts: str, + text: str, + *, + unfurl_links: bool = True, + unfurl_media: bool = True, ) -> str | None: - posted.append(text) + posted.append({"text": text, "unfurl_links": unfurl_links, "unfurl_media": unfurl_media}) return "1.1" monkeypatch.setattr( slack_utils, "post_slack_thread_reply_with_ts", fake_post_slack_thread_reply_with_ts ) - monkeypatch.setattr(slack_utils, "get_langsmith_trace_url", lambda thread_id: None) + monkeypatch.setattr(slack_utils, "get_langsmith_trace_url", lambda thread_id: "https://smith/x") - asyncio.run(post_slack_trace_reply("C123", "1.0", "thread-id", message="Taking a look...")) + asyncio.run(post_slack_trace_reply("C123", "1.0", "thread-id")) assert len(posted) == 1 - head, _, tip_line = posted[0].partition("\n") - assert head == "Taking a look..." + text = posted[0]["text"] + head, _, tip_line = text.partition("\n") + assert head == "" assert tip_line.startswith("_Tip: ") and tip_line.endswith("_") assert any(tip in tip_line for tip in TRACE_REPLY_TIPS) + assert posted[0]["unfurl_links"] is False + assert posted[0]["unfurl_media"] is False def test_select_slack_context_messages_detects_username_mention() -> None: @@ -516,14 +529,11 @@ def _setup_slack_mention_fakes( captured["active_thread_id"] = thread_id return False - async def fake_post_slack_trace_reply( - channel_id: str, thread_ts: str, thread_id: str, message: str | None = None - ) -> None: + async def fake_post_slack_trace_reply(channel_id: str, thread_ts: str, thread_id: str) -> None: captured["trace_reply"] = { "channel_id": channel_id, "thread_ts": thread_ts, "thread_id": thread_id, - "message": message, } class _FakeRunsClient: @@ -597,7 +607,6 @@ def test_process_slack_mention_creates_thread_first_run_with_trace_reply( "channel_id": "C123", "thread_ts": thread_ts, "thread_id": expected_thread_id, - "message": None, } run_create = captured["run_create"]