hermes - 💡(How to fix) Fix [Bug]: BlueBubbles attachments arrive as a second event and interrupt the in-progress turn (no debounce/merge like Telegram)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When a user sends a single iMessage that contains both text and an attachment, the BlueBubbles adapter dispatches the text and the attachment as two separate inbound events. The gateway treats the second event as a brand-new user message arriving mid-turn, emits ⚡ Interrupting current task. I'll respond to your message shortly., and splits one logical message into two turns.

Telegram already solves exactly this for albums via a debounce-and-merge step (_queue_media_group_event / _flush_media_group_event). The BlueBubbles adapter has no equivalent, so attachments routinely self-interrupt.

Root Cause

  • The BlueBubbles adapter subscribes to both new-message and updated-message and dispatches each immediately.
  • The existing MessageDeduplicator only suppresses exact GUID duplicates (delivered/read/edit echoes); an attachment-bearing updated-message is genuinely new content (and/or arrives after the dedup TTL), so it is processed — and interrupts.
  • This is distinct from #30708 (duplicate-event dedup) and #8513 (edit/retraction handling); it's specifically about coalescing the two-phase text+attachment delivery into one event.

(Note: I confirmed the interrupt path and the two-event behavior from gateway logs, but did not capture the raw webhook event type at default verbosity — maintainers can confirm whether the attachment arrives as updated-message vs a fresh new-message.)

Fix Action

Fix / Workaround

Summary

When a user sends a single iMessage that contains both text and an attachment, the BlueBubbles adapter dispatches the text and the attachment as two separate inbound events. The gateway treats the second event as a brand-new user message arriving mid-turn, emits ⚡ Interrupting current task. I'll respond to your message shortly., and splits one logical message into two turns.

Analysis

  • The BlueBubbles adapter subscribes to both new-message and updated-message and dispatches each immediately.
  • The existing MessageDeduplicator only suppresses exact GUID duplicates (delivered/read/edit echoes); an attachment-bearing updated-message is genuinely new content (and/or arrives after the dedup TTL), so it is processed — and interrupts.
  • This is distinct from #30708 (duplicate-event dedup) and #8513 (edit/retraction handling); it's specifically about coalescing the two-phase text+attachment delivery into one event.

Code Example

07:25:25  inbound message: platform=bluebubbles user=+1******** msg='<text>'
07:26:30  Queued follow-up for session agent:main:bluebubbles:dm::
          final stream delivery not confirmed; sending first response before continuing
RAW_BUFFERClick to expand / collapse

Summary

When a user sends a single iMessage that contains both text and an attachment, the BlueBubbles adapter dispatches the text and the attachment as two separate inbound events. The gateway treats the second event as a brand-new user message arriving mid-turn, emits ⚡ Interrupting current task. I'll respond to your message shortly., and splits one logical message into two turns.

Telegram already solves exactly this for albums via a debounce-and-merge step (_queue_media_group_event / _flush_media_group_event). The BlueBubbles adapter has no equivalent, so attachments routinely self-interrupt.

Environment

  • Hermes Agent v0.14.0 (2026.5.16)
  • BlueBubbles server 1.9.9, macOS 26.4.1, private API enabled
  • Single-user iMessage DM via the BlueBubbles webhook adapter

Steps to reproduce

  1. From an iMessage client, send one message containing text and an image/file attachment to the agent.
  2. Observe the agent's responses.

Expected

The text and its attachment are delivered to the agent as one logical message (one turn), exactly as a Telegram album is.

Actual

  • The text event starts a turn.
  • The attachment arrives as a separate event a few seconds later (BlueBubbles appears to emit it as an updated-message once the attachment finishes transferring).
  • The gateway sees a new inbound mid-turn → sends ⚡ Interrupting current task… and queues the attachment as a follow-up, producing two turns for one user action.

Representative gateway log (text at 07:25:25, follow-up/interrupt ~65s later):

07:25:25  inbound message: platform=bluebubbles user=+1******** msg='<text>'
07:26:30  Queued follow-up for session agent:main:bluebubbles:dm:…:
          final stream delivery not confirmed; sending first response before continuing

Analysis

  • The BlueBubbles adapter subscribes to both new-message and updated-message and dispatches each immediately.
  • The existing MessageDeduplicator only suppresses exact GUID duplicates (delivered/read/edit echoes); an attachment-bearing updated-message is genuinely new content (and/or arrives after the dedup TTL), so it is processed — and interrupts.
  • This is distinct from #30708 (duplicate-event dedup) and #8513 (edit/retraction handling); it's specifically about coalescing the two-phase text+attachment delivery into one event.

(Note: I confirmed the interrupt path and the two-event behavior from gateway logs, but did not capture the raw webhook event type at default verbosity — maintainers can confirm whether the attachment arrives as updated-message vs a fresh new-message.)

Proposed fix

Mirror the Telegram adapter's approach in gateway/platforms/bluebubbles.py:

  • Buffer an attachment-bearing event briefly (short debounce, e.g. a BB_ATTACHMENT_WAIT_SECONDS analogous to Telegram's MEDIA_GROUP_WAIT_SECONDS), keyed by message/chat GUID.
  • On a follow-up event for the same message within the window, merge media URLs + caption into the buffered MessageEvent (reset the timer), then flush a single handle_message call.

Reference implementation: gateway/platforms/telegram.py_queue_media_group_event / _flush_media_group_event. Feishu and Yuanbao adapters use similar debounce-batching.

Related

  • #30708 — BlueBubbles adapter lacks inbound dedup
  • #8513 — Handle BlueBubbles updated-message events (edits/retractions)

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Bug]: BlueBubbles attachments arrive as a second event and interrupt the in-progress turn (no debounce/merge like Telegram)