normalize json before deduplicating in `ToolEngine.tool_response_to_str`

这个报错通常出现在 Dify 通过 Agent 调用 MCP 工具、且工具返回的是紧凑 JSON 对象时。日志或工具调用历史里会出现两份内容相同、格式不同的对象(一份紧凑、一份格式化),优先排查 ToolEngine.tool_response_to_str 的字符串去重逻辑。

快速结论:这个报错通常出现在 Dify 通过 Agent 调用 MCP 工具、且工具返回的是紧凑 JSON 对象时。日志或工具调用历史里会出现两份内容相同、格式不同的对象(一份紧凑、一份格式化),优先排查 ToolEngine.tool_response_to_str 的字符串去重逻辑。

适用环境:Dify 1.17.1,Self Hosted(Docker),触发工具为 Swagger MCP,Agent 调用该工具后可在工具调用历史复现。

最快修复方案:暂无确认的一步修复方案。Issue 讨论已确认去重逻辑按原始字符串比较,但未给出合入的修复代码。

注意事项:现有去重逻辑对 VARIABLE 消息、workflow-as-tool 的 JSON/text 组合等场景也只做原始字符串比较,因此任何“同一数据、不同空白或键序”的返回都可能绕过去重,不能只靠调整展示层解决。

问题场景

在 Dify 1.17.1 Self Hosted(Docker)中,接入一个返回紧凑 JSON 对象的 Swagger MCP 工具,让 Agent 调用该工具,然后查看工具调用历史。预期是按函数注释所说完成去重,实际却看到两个重复对象:一个紧凑 JSON,一个格式化后的 JSON。

报错原文

normalize json before deduplicating in `ToolEngine.tool_response_to_str`

原因分析

已确认的原因:ToolEngine.tool_response_to_str 中的去重是“原始字符串比较”,而不是“解析后的结构比较”。

具体来说,existing_parts 由 TEXT/LINK 等消息的原始字符串构成,而 json_parts 中每一项是 json.dumps(safe_json_value(json_message.json_object), ensure_ascii=False) 的结果,成员判断用的是普通字符串相等。对于 MCP 工具,MCPTool._process_text_content 会在工具原始文本输出看起来像 JSON 对象或数组时,把它解析并重新发出为 JSON 消息。这样同一份数据就可能出现两次:一次是工具原本的紧凑 JSON 文本,另一次是 JSON 消息重新序列化后的格式化输出。由于空白字符或键顺序不同,两个字符串逐字节不相等,集合成员判断失败,于是两份都被写入 observation。

此前针对该函数的重复输出修复覆盖了 VARIABLE 消息、workflow-as-tool 的 JSON/text 组合等场景,但它们同样只比较原始字符串。要捕获“紧凑 vs. 美化”JSON,需要先做规范化,例如先 json.loads 再用排序键重新 dumps,或直接比较解析后的对象,而当前实现没有做这一步。

环境排查

  • 确认 Dify 版本是否为 1.17.1。
  • 确认部署方式是否为 Self Hosted(Docker)。
  • 确认触发的工具类型是否为 MCP 工具(本次为 Swagger MCP)。
  • 确认工具返回内容是否为紧凑 JSON 对象或数组。
  • 确认复现路径是否经过 Agent 工具调用,并且能在工具调用历史中看到两份内容。

解决步骤

  1. 按 Issue 的复现步骤构造场景:接入返回紧凑 JSON 对象的 Swagger MCP 工具,让 Agent 调用该工具。
  2. 打开工具调用历史,确认是否出现两个重复对象:一个紧凑格式、一个格式化格式。
  3. 查看 api/core/tools/tool_engine.pytool_response_to_str 的去重实现,确认 existing_partsjson_parts 之间是原始字符串比较。
  4. 查看 api/core/tools/mcp_tool/tool.pyMCPTool._process_text_content 的行为,确认工具原始文本输出会被解析并重新发出为 JSON 消息。
  5. 如需修复,应先把 JSON 文本规范化(解析后按排序键重新序列化,或直接比较解析后的对象),再执行去重;Issue 讨论中未提供已合入的具体补丁。

验证方法

使用同一 Swagger MCP 工具与 Agent 调用路径重新运行,检查工具调用历史中是否只剩一份对象,不再同时出现紧凑 JSON 与格式化 JSON。若修复后仍有两份内容,说明规范化或去重逻辑尚未覆盖该分支。

参考来源

langgenius/dify #42195

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 24149

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注