#2414: fix(slack): route DM replies to original channel, not App Home
channel: slack
Cluster:
Agent Messaging Enhancements
Fixes #2412
## Problem
When @mentioned in a DM between two other users (User A ↔ User B), the bot replies to App Home instead of the original DM.
## Root Cause
`prepare.ts:440` sets `slackTo = user:${message.user}` for DMs.
In `send.ts:81`, `user:X` targets trigger:
```typescript
await client.conversations.open({ users: recipient.id })
```
This opens a **new** bot↔user DM (App Home), not the original channel.
## Fix
Always use `channel:${message.channel}` — the Slack API accepts channel IDs for all conversation types (channels, DMs, MPIMs).
`lastRoute` tracking (line 538) intentionally still uses `user:X` for identity/session purposes.
## Testing
- [x] Verified code path in `send.ts` confirms `user:` prefix triggers `conversations.open`
- [x] Manual test: @mention bot in DM between two other users
Co-Authored-By: Warp <agent@warp.dev>
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR fixes Slack DM reply routing by always setting `To`/`OriginatingTo` to `channel:${message.channel}` in `src/slack/monitor/message-handler/prepare.ts`, preventing the downstream Slack sender from treating DMs as `user:` targets (which triggers `conversations.open` and creates a new bot↔user DM/App Home). Session/identity tracking via `lastRoute` remains keyed by `user:${message.user}` for DM contexts.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- Change is localized to Slack inbound message preparation and aligns with Slack’s API expectations: replies are now always sent to the original channel ID, avoiding the unintended `conversations.open` path that created a new bot↔user DM. No broader behavior changes beyond DM routing are apparent.
- src/slack/monitor/message-handler/prepare.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#15863: fix: route agent-to-agent Slack messages to bound sessions
by MisterGuy420 · 2026-02-14
81.9%
#19435: fix(slack): properly handle group DM (MPIM) events
by Utkarshbhimte · 2026-02-17
80.9%
#10643: fix(slack): classify D-prefix DMs correctly when channel_type disag...
by mcaxtr · 2026-02-06
79.5%
#20406: fix(slack): respect replyToMode when computing statusThreadTs in DMs
by QuinnYates · 2026-02-18
78.9%
#8024: fix(slack): resolve channel names via directory for cross-account m...
by emma-digital-assistant · 2026-02-03
78.9%
#23320: fix(slack): respect replyToMode when incomingThreadTs is auto-created
by dorukardahan · 2026-02-22
78.5%
#23804: fix(slack): preserve string thread context in queue + DM route
by vincentkoc · 2026-02-22
78.4%
#19403: feat(slack): add dm.threadSession option for per-message thread ses...
by Vasiliy-Bondarenko · 2026-02-17
78.4%
#7719: fix(slack): thread replies with @mentions dropped in requireMention...
by SocialNerd42069 · 2026-02-03
77.4%
#4749: fix: handle string thread IDs in queue drain for Slack
by nvonpentz · 2026-01-30
76.8%