Skip to content

fix(gateway): pass reply_to for Feishu thread routing on status/progress/stream messages - #9384

Closed
creasexul wants to merge 1 commit into
NousResearch:mainfrom
creasexul:fix/feishu-status-thread-routing
Closed

fix(gateway): pass reply_to for Feishu thread routing on status/progress/stream messages#9384
creasexul wants to merge 1 commit into
NousResearch:mainfrom
creasexul:fix/feishu-status-thread-routing

Conversation

@creasexul

Copy link
Copy Markdown

Problem

Feishu's CreateMessage API does not support thread_id — only the ReplyMessage API does (via reply_in_thread). Several message-sending paths in the gateway only passed metadata={'thread_id': ...} without reply_to, causing these messages to appear outside the conversation thread on Feishu as standalone messages:

  • Context pressure warnings ("⚠️ Context: ▰▰▰▰... 93% to compaction")
  • Connection retry notifications ("⚠️ Connection to provider dropped... Reconnecting")
  • Long-running heartbeats ("⏳ Still working... 10 min elapsed")
  • Tool progress updates (when edit_message fallback triggers)
  • Stream consumer messages (first message + fallback chunks)

Root Cause

The _send_raw_message method in feishu.py uses the ReplyMessage API (which supports threading) only when reply_to is provided. When only metadata={'thread_id': ...} is passed, it falls through to CreateMessage, which ignores thread_id entirely.

The tool progress path already had a comment documenting this behavior but the fix was incomplete — it was never applied to status callbacks, long-running notifications, or the stream consumer.

Fix

  1. Added _progress_reply_to = event_message_id if _progress_thread_id else None as a shared variable
  2. Threaded reply_to through all affected send paths:
    • send_progress_messages() — 3 send calls
    • _status_callback_sync() — context pressure, connection retry
    • _notify_long_running() — heartbeat notifications
    • GatewayStreamConsumer — added reply_to constructor param, used in initial send + fallback paths

Files Changed

  • gateway/run.py — 5 send calls + new _progress_reply_to variable
  • gateway/stream_consumer.py — new reply_to param + 4 send calls

Testing

  • Non-thread conversations: _progress_reply_to is None, behavior unchanged
  • Other platforms: reply_to=None is the default, no behavioral change
  • Feishu threads: messages now use ReplyMessage API and appear inside the thread

…ess/stream messages

Feishu's CreateMessage API does not support thread_id — only the
ReplyMessage API does (via reply_in_thread). Several message-sending
paths in the gateway only passed metadata={'thread_id': ...} without
reply_to, causing status notifications, tool progress updates, stream
consumer messages, and long-running heartbeats to appear outside the
conversation thread on Feishu.

Fixed paths:
- Tool progress messages (send_progress_messages)
- Status callback messages (context pressure, connection retry)
- Long-running heartbeat notifications (Still working...)
- GatewayStreamConsumer initial send + fallback sends

The fix adds a _progress_reply_to variable (set to event_message_id
when a thread context exists) and threads it through all send() calls
and the GatewayStreamConsumer constructor.

@houko houko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good fix — properly routing Feishu progress messages to threads via reply_to is important for thread continuity. 👍

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/feishu Feishu / Lark adapter labels Apr 27, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused Feishu routing fix. This is already implemented on current main; this automated hermes-sweeper review is closing the superseded PR.

  • Commit 441ef75d157d6308a9f14d42a7b0ec8566866ef8 (fix(feishu): keep topic replies in threads) is on main and ships in v2026.5.7.
  • gateway/run.py:17358 derives the Feishu reply target from the triggering message and the progress paths pass it to adapter.send (gateway/run.py:17514, gateway/run.py:17662).
  • Status and streaming use the same target through gateway/run.py:17800 and gateway/run.py:17987.
  • plugins/platforms/feishu/adapter.py:4609 promotes reply_to_message_id from thread metadata to Feishu's ReplyMessage API with reply_in_thread=true.
  • Current regressions cover progress routing (tests/gateway/test_run_progress_topics.py:451) and metadata-driven Feishu replies (tests/gateway/test_feishu.py:2080).

The discussion’s cross-reference to #19750 tracks the same resolved behavior.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/feishu Feishu / Lark adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants