fix: enforce terse Slack tool messages (#1717) (#197)

(cherry picked from commit 092abafa4cb955c3823f727d35d7bad94e1147ab)

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
This commit is contained in:
Adam Moussa 2026-07-16 17:51:17 -04:00 • committed by GitHub
parent a787514e07
commit 7b9eff62e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 31 additions and 6 deletions

View file

@ -84,7 +84,7 @@ OPEN_SWE_SHARED_BASE = """You are **Open SWE**, an open-source agent built on La
### Communication
- Focus on the substance and keep summaries brief. Use light markdown (`###`/`####` headings, bold, code) — avoid `#`/`##` titles.
- In Slack, keep every reply terse — a few sentences at most. Lead with the answer or outcome; skip preamble, restating the request, and step-by-step recaps. Do not paste long output, diffs, file listings, or multi-section write-ups into a Slack reply. When the response would genuinely be long — a detailed report, a design/analysis write-up, a large code or log excerpt — write that content to a Markdown file under `/workspace/plans/` and publish it with the `save_plan` tool, then post a terse Slack reply with a one-line summary and the plan-review link so the user can read the full version there. This non-plan share path does not enter plan mode; use it instead of splitting a long answer across multiple Slack messages.
- Whenever calling `slack_thread_reply`, make `message` as terse as possible while still conveying the necessary information. Default to one sentence containing only the outcome/status and link, or one blocking question. Omit greetings, preambles, headings, recaps, implementation details, and redundant context; use bullets only when multiple items are essential. This rule applies only to Slack tool messages, not normal assistant messages shown in the web UI. Never paste long output, diffs, file listings, or multi-section write-ups into Slack. When detail is necessary, write it to a Markdown file under `/workspace/plans/`, publish it with `save_plan`, and send only a one-line summary plus the plan-review link. This non-plan share path does not enter plan mode.
- In Slack, when a user asks to “break out,” “split out,” or “start a separate thread” for part of the work, summarize the requested aspect and relevant context into self-contained instructions, then call `slack_start_new_thread` instead of only replying in the current thread.
- In Slack, when acknowledging a user follow-up while you continue working, prefer `slack_add_reaction` with the default `eyes` reaction over posting a perfunctory “Updating…” / “I’ll check…” confirmation reply.
- For Slack-triggered information-only answers, post only a concise summary in the associated Slack thread with `slack_thread_reply`, then provide the complete answer inline in your final assistant response. For other Slack updates, keep thread replies brief and avoid duplicating the same text later.

View file

@ -32,11 +32,13 @@ async def slack_thread_reply(
) -> dict[str, Any]:
"""Post a message to the current Slack thread.
Use this for clarifying questions, mid-run progress updates, and the final
summary. You can call this multiple times during a run — if you're about to
do long-running work (cloning, large refactors, big test runs) consider
posting a brief status update first so the user knows what's happening.
Always end the run with a final reply summarizing what you did.
Use this for clarifying questions, essential progress updates, and the final
outcome. Make `message` as terse as possible: default to one sentence with
only the outcome/status and link, or one blocking question. Omit greetings,
preambles, headings, recaps, implementation details, and redundant context;
use bullets only when multiple items are essential. This terseness rule is
specific to Slack tool messages, not normal web UI assistant messages.
Always end the run with a terse final outcome.
Format messages using Slack's mrkdwn format, NOT standard Markdown.
Key differences: *bold*, _italic_, ~strikethrough~, <url|link text>,

View file

@ -88,6 +88,20 @@ def test_construct_system_prompt_identifies_own_repo() -> None:
assert "Open SWE" in OPEN_SWE_SHARED_BASE
def test_shared_base_requires_terse_slack_replies_with_share_path() -> None:
from agent.prompt import OPEN_SWE_SHARED_BASE
assert "calling `slack_thread_reply`" in OPEN_SWE_SHARED_BASE
assert "as terse as possible" in OPEN_SWE_SHARED_BASE
assert "Default to one sentence" in OPEN_SWE_SHARED_BASE
assert "applies only to Slack tool messages" in OPEN_SWE_SHARED_BASE
assert "not normal assistant messages shown in the web UI" in OPEN_SWE_SHARED_BASE
assert "Never paste long output" in OPEN_SWE_SHARED_BASE
assert "`save_plan`" in OPEN_SWE_SHARED_BASE
assert "plan-review link" in OPEN_SWE_SHARED_BASE
assert "does not enter plan mode" in OPEN_SWE_SHARED_BASE
def test_harness_profile_replaces_deepagents_base_for_supported_providers() -> None:
"""The Open SWE base prompt is registered per provider and replaces the SDK base."""
import deepagents.profiles.harness.harness_profiles as hp

View file

@ -19,6 +19,15 @@ def _config() -> dict[str, Any]:
}
def test_slack_thread_reply_prompt_requires_slack_only_terseness() -> None:
prompt = slack_reply_tool.slack_thread_reply.__doc__ or ""
assert "as terse as possible" in prompt
assert "default to one sentence" in prompt
assert "specific to Slack tool messages" in prompt
assert "not normal web UI assistant messages" in prompt
async def test_slack_thread_reply_returns_structured_error_for_msg_too_long(
monkeypatch: pytest.MonkeyPatch,
) -> None: