#5567·nanobot

Feat: 飞书渠道应整合多轮回复为单条流式卡片消息

Author: yrxevaCreated Aug 27, 2026Updated Sep 7, 2026

问题描述

飞书渠道中,用户发送一条消息后,agent 可能回复 n 条消息(工具提示、进度消息、最终回复等),用户体验较差。希望整合为 一条流式卡片消息,保持 用户发一条消息 → agent 回复一条消息 的对应关系。

当前行为

以飞书渠道为例,当 agent 处理用户请求时:

  1. 流式输出阶段:通过 send_delta() 使用 CardKit 流式卡片(已有实现)
  2. 工具调用阶段:通过 send() 发送独立的进度/工具提示消息
  3. 最终回复阶段:再次通过 send() 发送最终内容

导致用户在飞书中看到多条分离的消息。

期望行为

  • 用户发一条消息 → agent 回复一条消息
  • 所有输出(流式文本、工具提示、进度信息)都应内联到同一条流式卡片中
  • 保持现有流式卡片的逐字更新体验

技术分析

从代码看,飞书 channel 已有 send_delta() 实现 CardKit 流式卡片:

  • nanobot/channels/feishu/runtime.py_FeishuStreamBufsend_delta() 已支持流式更新
  • send() 方法仍会独立发送消息(工具提示、媒体、最终回复等)

关键问题在 ChannelManager._send_once()nanobot/channels/manager.py):

  • StreamDeltaEvent / StreamEndEvent → 调用 send_delta()(流式卡片)
  • 其他事件(ProgressEvent、普通 OutboundMessage)→ 调用 send()(独立消息)

建议方案

  1. 优先方案:在 send_delta() 中捕获所有非流式输出,内联到流式卡片

    • 当有活跃流式卡片时,工具提示/进度消息通过 send_delta() 追加到同一卡片
    • 最终回复也追加到同一卡片,而非重新调用 send()
  2. 备选方案:在 ChannelManager 层面做路由决策

    • 检测目标 channel 是否支持流式卡片
    • 若支持,将所有输出统一走 send_delta() 路径
  3. 配置开关:新增 feishu.stream_card.merge_non_stream 配置项,控制是否将非流式消息合并到流式卡片

影响范围

  • 主要影响飞书渠道(已实现流式卡片)
  • 类似实现可扩展到 Discord、Telegram 等支持富文本/卡片的渠道
  • 不影响不支持流式的渠道(纯文本渠道保持现有行为)

相关 Component

Channel (Feishu), Channel Manager

附加说明

  • 现有 feishu_stream_card 插件仅提供启动/关闭通知功能,不解决多消息整合问题
  • 飞书 CardKit streaming_mode 已能支持持续更新,技术上可行