Skip to content

Feishu: Bot replies leak out of P2P topic thread into main chat #9916

@genspider

Description

@genspider

Bug Description

When a user creates a topic thread (话题) inside their P2P chat with the bot, and then sends a message from within that topic thread, the bot's reply appears in the main P2P chat instead of inside the topic thread.

Steps to Reproduce

  1. Open a P2P chat with the Hermes bot
  2. Create a new topic/thread inside that P2P chat
  3. From within the topic, send a message to the bot
  4. The bot processes the message correctly, but replies to the main P2P chat, not inside the topic

Expected Behavior

Bot replies should appear inside the topic thread where the user sent the message.

Root Cause

In gateway/platforms/feishu.py, _send_raw_message (line 3286–3293) always sends messages using receive_id_type="chat_id":

body = self._build_create_message_body(
    receive_id=chat_id,
    msg_type=msg_type,
    content=payload,
    uuid_value=str(uuid.uuid4()),
)
request = self._build_create_message_request("chat_id", body)
return await asyncio.to_thread(self._client.im.v1.message.create, request)

When a user sends a message from a topic, the inbound message object carries a thread_id (correctly extracted at line 2197: thread_id=getattr(message, "thread_id", None)). This thread_id is passed in metadata to the send pipeline. However, _send_raw_message only uses metadata["thread_id"] to set reply_in_thread=True for the message.reply API path (line 3275) — it is never used as the receive_id when creating a new top-level message (the else branch at line 3286).

As a result, every non-reply message is sent to the P2P chat_id, causing it to appear in the main chat rather than the topic.

Suggested Fix

In _send_raw_message, when metadata contains a thread_id, use receive_id_type="thread_id" and pass receive_id=thread_id to route the message into the correct topic:

thread_id = (metadata or {}).get("thread_id")
if thread_id:
    body = self._build_create_message_body(
        receive_id=thread_id,
        msg_type=msg_type,
        content=payload,
        uuid_value=str(uuid.uuid4()),
    )
    request = self._build_create_message_request("thread_id", body)
else:
    body = self._build_create_message_body(
        receive_id=chat_id,
        msg_type=msg_type,
        content=payload,
        uuid_value=str(uuid.uuid4()),
    )
    request = self._build_create_message_request("chat_id", body)

The reply_to path (line 3276–3284) already correctly handles topic replies via message.reply, so no changes are needed there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliveryplatform/feishuFeishu / Lark adaptertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions