#2799: fix(imessage): prevent self-chat and outbound echo loops (#2585)
channel: imessage
Cluster:
Messaging Platform Improvements
Trying to kill the iMessage self-reply loop with a few layers of protection:
1. Already checking `is_from_me` early — but it can be false in self-chat cases, so not enough by itself.
2. Extra check: if it’s not a group chat (`is_group=false`) and the only participant is the sender → drop it right away. Catches the classic “talking to myself” echo.
3. Stronger one: when we send a message, save its `messageId` in a small short-lived cache. If an incoming message has an id that’s in the cache → treat it as our own echo and discard it. This catches the weird non-self-chat bounces too.
Added tests:
- Self-chat where `is_from_me=false` → make sure we don’t reply
- Normal inbound → we send → record id → fake same id coming back in → confirm it gets dropped and doesn’t trigger again
Should finally squash the infinite self-reply mess in #2585.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds multiple safeguards to prevent iMessage “self-chat” / outbound echo loops in the monitor:
- Adds a self-chat detector for 1:1 messages where the only participant normalizes to the sender.
- Tracks recently-sent outbound `messageId`s in a short-lived in-memory cache and drops inbound messages whose ids match.
- Wires outbound tracking from `deliverReplies` via a new `onSent` callback.
- Adds tests for self-chat not marked `is_from_me` and for dropping inbound echoes matching a recently sent outbound id.
Overall this fits cleanly into the existing monitor flow by filtering inbound messages early in `handleMessageNow` and extending the send pipeline to report ids back into the monitor.
<h3>Confidence Score: 4/5</h3>
- This PR is largely safe to merge and should reduce iMessage echo loops, with only minor edge-case robustness concerns.
- The changes are localized (early inbound filtering + outbound id tracking) and are covered by targeted tests. The main remaining concerns are small edge cases in cache trimming and id normalization that could reduce effectiveness rather than break core functionality.
- src/imessage/monitor/monitor-provider.ts (outbound id cache pruning), src/imessage/monitor/deliver.ts (messageId normalization assumptions)
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#3300: changed chat session selection logic in iMessage
by KimEJ · 2026-01-28
81.1%
#7353: fix: prevent silent message drops after config.patch restart
by 18-RAJAT · 2026-02-02
80.7%
#8742: fix(webchat): hide internal system messages from UI (#7440)
by revenuestack · 2026-02-04
76.9%
#7127: fix(webchat): add regenerate flag to prevent context leak on response…
by craihub · 2026-02-02
76.4%
#7316: fix: /chat dashboard performance
by felipcsousa · 2026-02-02
76.1%
#7218: fix(telegram): skip empty text messages in threaded mode
by ArsalanShakil · 2026-02-02
75.9%
#16783: Fix cross-channel routing in iMessage monitor
by fengwen2013 · 2026-02-15
75.3%
#8166: fix(telegram): lifecycle fixes for duplicate messages and auto-reco...
by cheenu1092-oss · 2026-02-03
75.0%
#15998: fix: hide metadata block when only conversation_label is present
by netmanyys · 2026-02-14
75.0%
#15564: fix: webchat messages disappear during concurrent session activity
by Automatedcapitalist · 2026-02-13
75.0%