问题描述
active_agent 类型的定时任务(future_task / cron_jobs)到点触发后,agent 正常执行并调用 send_message_to_user,工具返回成功,消息也正确写入了 platform_message_history;但已经打开的 WebChat 聊天窗口不会实时显示这条消息,用户看起来就像"什么都没发生"。重新加载后消息才出现,且时间戳完全正确——数据没有丢,缺的是"实时通知"这一环。
附带观察:这类场外主动消息写入 platform_message_history 时 llm_checkpoint_id 为 NULL(同一窗口内正常对话轮次的消息均有 checkpoint)。我们实例的库中,所有 llm_checkpoint_id 为 NULL 的记录均来自定时任务推送,佐证场外消息绕过了会话的 turn/checkpoint 链。
复现步骤
- 在 WebChat 窗口中创建一个
active_agent 定时任务(run_once,如 2 分钟后触发),note 指示到点后调用 send_message_to_user 发送一条测试消息
- 保持该 WebChat 窗口打开,等待触发
- 实际:窗口无任何变化,看起来任务没执行
- 重启 AstrBot 服务后:消息出现,时间正确(已实测)
补充说明:后端 GET /chat/sessions/{id} 返回完整历史、无过滤,因此推断页面刷新(F5)应同样可见,但我们未单独验证仅刷新页面这一路径,故上面只把"重启后可见"列为实测结论。
我们使用两个 run_once 任务(14:55、15:20)+ 一个 cron 任务(15:30,webchat 平台)在同一天实测,行为一致。
数据库证据(v4.28.0,webchat 平台)
platform_message_history 中消息记录存在:sender=bot、user_id=目标会话、时间正确
- 但
llm_checkpoint_id = NULL;同窗口正常对话的消息均有 checkpoint id
- 后端
dashboard/services/chat_service.py 的 get_session 返回全部历史,未按 checkpoint 过滤——即 API 层数据是全的,前端重新拉取后能渲染出这些消息
- dashboard 侧未发现面向"会话历史更新"的通知通道:实时更新只存在于用户自己发起的 chat run 流中(另有
/live-chat/ws,但属于 live_chat 功能)
原因分析(初步,含推断)
定时唤醒的 agent 以"场外"方式运行,其 send_message_to_user 不属于任何 chat run,消息入库后没有任何机制通知已连接的客户端。从"重新加载后可见 + 后端无推送通道"两点推断:前端仅在加载/重连时拉取历史,运行中不会主动同步场外新消息(此推断未逐行核对前端 bundle)。因此消息要等到下一次加载才可见。对用户而言,定时任务(日报、提醒、监控告警)表现得像"静默失败"。
修复方向建议
- 主动消息写入
platform_message_history 后,向正在查看该会话的已连接客户端广播一个轻量的 "history updated" 事件(复用/新增 SSE 或 WebSocket 通道),前端收到后重新拉取该会话历史
- 或者:让定时唤醒产生的回复走正常会话 turn 流(既获得 checkpoint 关联,也能实时渲染)
- 顺带考虑:场外消息是否应挂到会话的 turn/checkpoint 链上(目前为 NULL)——否则即使显示了,在按 turn 组织的前端视图里也可能是游离消息
相关 issue
环境
- AstrBot version: 4.28.0
- OS: Windows
- 部署方式: Windows 本地直装(launcher)
- 消息平台适配器: webchat(内置 Dashboard ChatUI)
- 错误日志: 无报错——全程无异常,纯"静默不可见",这也是排查困难的原因(最初只能靠查数据库还原过程)
检查清单
问题描述
active_agent类型的定时任务(future_task / cron_jobs)到点触发后,agent 正常执行并调用send_message_to_user,工具返回成功,消息也正确写入了platform_message_history;但已经打开的 WebChat 聊天窗口不会实时显示这条消息,用户看起来就像"什么都没发生"。重新加载后消息才出现,且时间戳完全正确——数据没有丢,缺的是"实时通知"这一环。附带观察:这类场外主动消息写入
platform_message_history时llm_checkpoint_id为 NULL(同一窗口内正常对话轮次的消息均有 checkpoint)。我们实例的库中,所有llm_checkpoint_id为 NULL 的记录均来自定时任务推送,佐证场外消息绕过了会话的 turn/checkpoint 链。复现步骤
active_agent定时任务(run_once,如 2 分钟后触发),note 指示到点后调用send_message_to_user发送一条测试消息补充说明:后端
GET /chat/sessions/{id}返回完整历史、无过滤,因此推断页面刷新(F5)应同样可见,但我们未单独验证仅刷新页面这一路径,故上面只把"重启后可见"列为实测结论。我们使用两个
run_once任务(14:55、15:20)+ 一个 cron 任务(15:30,webchat 平台)在同一天实测,行为一致。数据库证据(v4.28.0,webchat 平台)
platform_message_history中消息记录存在:sender=bot、user_id=目标会话、时间正确llm_checkpoint_id = NULL;同窗口正常对话的消息均有 checkpoint iddashboard/services/chat_service.py的get_session返回全部历史,未按 checkpoint 过滤——即 API 层数据是全的,前端重新拉取后能渲染出这些消息/live-chat/ws,但属于 live_chat 功能)原因分析(初步,含推断)
定时唤醒的 agent 以"场外"方式运行,其
send_message_to_user不属于任何 chat run,消息入库后没有任何机制通知已连接的客户端。从"重新加载后可见 + 后端无推送通道"两点推断:前端仅在加载/重连时拉取历史,运行中不会主动同步场外新消息(此推断未逐行核对前端 bundle)。因此消息要等到下一次加载才可见。对用户而言,定时任务(日报、提醒、监控告警)表现得像"静默失败"。修复方向建议
platform_message_history后,向正在查看该会话的已连接客户端广播一个轻量的 "history updated" 事件(复用/新增 SSE 或 WebSocket 通道),前端收到后重新拉取该会话历史相关 issue
platform_message_history无任何记录,可能与该 issue 同源)环境
检查清单