快速结论:当 Chatflow 在流式(response_mode=streaming)模式下运行时,非流式插件工具通过 create_variable_message 输出的自定义变量(例如 session_id)会在流式回复和持久化的 messages.answer 中变成空值,但工作流输出 workflow_runs.outputs.answer 仍是正确的。主要现象是“工作流成功但流式回复缺变量值”,应优先检查 ToolNode 对非流式变量的流式终结(finalization)处理。
适用环境:Dify 1.17.1 自托管(Docker,通过 Kubernetes 部署),并依赖 graphon==0.7.0;报告者说明该问题在当前 graphon main 中也存在。操作系统、Python、CUDA、显卡等版本 Issue 未提供,不作推断。
最快修复方案:暂无确认的一步修复方案。Issue 中提出的修复方向是修改 graphon ToolNode:仅为真正收到流式消息的变量发送 is_final=True 终结标记,非流式变量不要发送空终结标记,这样就能触发 ResponseStreamFilter 已有的变量池回退。但该修复尚未在 Issue 中验证合入。
注意事项:修复点在 graphon 的 ToolNode 与流式处理逻辑中,不属于 Dify 前端或 Markdown 渲染问题,因为保存的 messages.answer 已经缺失该值;修改后需要同时验证流式回复、messages.answer、workflow_runs.outputs.answer 三者一致,并确认真正流式输出的变量不会重复输出。相关 PR #43986 是 Agent V2 的类似修复,不能直接当作 ToolNode 的已修复证据。
问题场景
用户在 Dify 自托管环境中搭建 Chatflow:Start → 创建会话工具节点(ToolNode,输出非流式自定义变量 session_id)→ 转发回合工具节点(输出文本消息 “Hello”)→ Answer 节点,Answer 模板同时引用第二个工具节点的文本和第一个工具节点的变量。使用 response_mode=streaming 执行后,拼接 message.answer 分片,并与 Answer 节点输出、workflow_runs.outputs.answer、保存的 messages.answer 对比,发现流式回复和消息记录中 session_id 为空,而工作流输出正常。
报错原文
Non-streaming tool variables disappear from streamed and saved Chatflow answers
Reply: Hello
session_id:
原因分析
根据 Issue 描述,可能原因在 graphon ToolNode 的流式处理流程:_handle_variable_message() 会把非流式变量写入最终节点输出,但不发送值分片,这是预期行为;随后 _emit_final_stream_events() 却为每个自定义变量都发送一个空的 is_final=True 分片,包括从未流式输出过的变量。ResponseStreamFilter 将该 selector 视为已关闭并消费这个空终结分片,从而推进 Answer 模板,不再从运行时变量池读取真实值。AnswerNode 则独立地从变量池渲染完整模板,因此工作流输出正确,而流式与持久化消息缺失变量值。Dify 流水线将收到的文本分片追加到 _task_state.answer 并保存为 message.answer,所以被响应过滤器遗漏的值会同时从 SSE 和消息历史中消失。
环境排查
- 确认 Dify 版本是否为 1.17.1(自托管 fork),以及 graphon 版本是否为 0.7.0 或当前 main 分支。
- 确认 Chatflow 调用是否使用 response_mode=streaming。
- 确认第一个工具节点是否通过 create_variable_message 输出非流式自定义变量,并在工具 YAML 的 output_schema 中声明该变量。
- 确认 Answer 节点模板是否正确引用两个节点的输出。
- 分别检查流式 message.answer 拼接结果、Answer 节点输出、workflow_runs.outputs.answer 和 messages.answer 四处内容是否一致。
解决步骤
- 先按 Issue 的复现路径确认问题:使用两个工具节点,第一个输出非流式自定义变量,第二个输出文本,经 Answer 节点流式执行。
- 对比 workflow_runs.outputs.answer 与拼接后的 message.answer。若前者包含变量值、后者缺失,即可判定为流式终结处理问题,而非模板配置问题。
- 在 graphon ToolNode 中检查 _handle_variable_message() 与 _emit_final_stream_events(),确认是否为所有自定义变量都发送了空的 is_final=True 分片。
- 可优先尝试:仅为实际收到流式消息的变量发送终结标记,非流式变量不再发送空终结标记,使其走 ResponseStreamFilter 的变量池回退逻辑。
- 修改后重新执行同一 Chatflow,并验证变量类型与赋值语义保持不变。
验证方法
流式执行后,拼接 message.answer 分片,确认其内容与 workflow_runs.outputs.answer、Answer 节点输出以及保存的 messages.answer 完全一致,均包含完整的 session_id 值(例如 sess_example);同时用流式输出变量的工具回归,确认真正流式变量的终结不会造成重复输出。
参考来源
langgenius/dify #43986(Agent V2 类似修复,非 ToolNode)
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug] Local browser test traces can exhaust disk space](https://www.chat-gpts.plus/wp-content/uploads/2026/11/46157-6577dbee-768x403.jpg)
![[Bug]: Scale-out `/render` endpoints and `/inference/v1/generate` ignore the `X-Vllm-Priority` header](https://www.chat-gpts.plus/wp-content/uploads/2026/11/67007-e3d022c9-768x403.jpg)
