Skip to content

fix(slack-bot): ensure PR/MR URLs surface in Slack replies#1711

Open
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
fix/slack-bot-pr-url-surfacing
Open

fix(slack-bot): ensure PR/MR URLs surface in Slack replies#1711
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
fix/slack-bot-pr-url-surfacing

Conversation

@kilo-code-bot
Copy link
Copy Markdown
Contributor

@kilo-code-bot kilo-code-bot bot commented Mar 30, 2026

Summary

Users reported that PR/MR URLs created by the cloud agent never appear in Slack bot replies. Investigation found three independent root causes:

  • Legacy bot missing prompt instruction: The legacy Slack bot (src/lib/slack-bot.ts) did not append "Open a pull request and return the PR URL" to the cloud agent prompt for code mode sessions. The System 2 bot (Pound) already did this at src/lib/bot/tools/spawn-cloud-agent-session.ts:87-93, but the legacy bot only appended the PR signature — not the URL return instruction.
  • No explicit LLM instruction to relay URLs: Neither bot's system prompt nor tool description explicitly told the outer LLM to extract PR/MR URLs from tool results and include them in the user-facing reply. The tool description in the legacy bot only said "Provide exactly one of githubRepo or gitlabProject" with no post-call guidance. The System 2 bot's tool description already had this instruction but the system prompt did not reinforce it.
  • Slack section block 3000-char truncation: The legacy webhook route (src/app/slack/webhook/route.ts:219-232) placed the entire formatted response in a single section block. Slack's API silently truncates section.text at 3000 characters. Cloud agent responses often exceed this, with the PR URL appearing near the end — exactly where it gets cut off.

Fixes applied:

  1. Legacy bot now appends "Open a PR/MR and return the URL" to the cloud agent prompt in code mode (matching System 2 behavior)
  2. Both bots' system prompts now include a "Sharing results" section instructing the LLM to extract and relay PR/MR URLs
  3. Legacy tool description updated to include post-call URL relay instruction
  4. Legacy webhook now splits long responses into multiple section blocks to stay within Slack's 3000-char limit

Verification

  • pnpm typecheck — passed
  • pnpm format:check — passed (via pre-push hook)
  • ESLint — passed (via pre-push hook)
  • Manual review of all three changed files for correctness

Visual Changes

N/A

Reviewer Notes

  • The System 2 bot (Pound, src/lib/bot/run.ts) was already better instrumented than the legacy bot — its tool description at line 152 already said "check the result for a PR/MR URL and share it with the user." The system prompt section added here reinforces this at a different layer.
  • The toSectionBlocks function in the webhook route splits on newline boundaries to avoid breaking URLs mid-character. Falls back to hard-split if no newline is found within the limit.
  • The 3000-char section block limit is a known Slack API constraint. The text field outside blocks is preserved as-is (40k char limit) and serves as fallback for clients that don't render blocks.

Three root causes prevented PR/MR URLs from reaching users:

1. Legacy bot did not append 'return the PR URL' instruction to the
   cloud agent prompt (System 2 already did this).

2. Neither bot system prompt nor tool description explicitly told the
   outer LLM to extract and relay the PR/MR URL from tool results.

3. Legacy webhook put the entire response in a single Slack section
   block, which silently truncates at 3000 chars — often cutting off
   the URL at the end.

Fixes:
- Append PR/MR URL instruction to legacy cloud agent prompt (code mode)
- Add 'Sharing results' section to both system prompts
- Add PR URL relay instruction to legacy tool description
- Split long responses into multiple section blocks to stay within
  Slack's 3000-char section limit
type: 'section',
text: { type: 'mrkdwn', text: remaining.slice(0, splitAt) },
});
remaining = remaining.slice(splitAt + 1);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

WARNING: Hard-split path drops one character

When no newline exists within the limit, splitAt is set to charLimit, but this line still advances by + 1. That skips the character at the split boundary, so long single-line responses lose one character per block and can still break PR/MR URLs or code blocks.

Suggested change
remaining = remaining.slice(splitAt + 1);
remaining = remaining.slice(remaining[splitAt] === '\n' ? splitAt + 1 : splitAt);

@kilo-code-bot
Copy link
Copy Markdown
Contributor Author

kilo-code-bot bot commented Mar 30, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/app/slack/webhook/route.ts 71 The hard-split fallback drops the character at the split boundary, so long single-line responses can still corrupt PR/MR URLs.

Fix these issues in Kilo Cloud

Other Observations (not in diff)

N/A

Files Reviewed (3 files)
  • src/app/slack/webhook/route.ts - 1 issue
  • src/lib/bot/run.ts - 0 issues
  • src/lib/slack-bot.ts - 0 issues

Reviewed by gpt-5.4-20260305 · 222,130 tokens

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants