Why is the tool's json output a dictionary list instead of returning the tool's output directly? #4513

Closed
opened 2026-02-21 18:06:50 -05:00 by yindo · 3 comments
Owner

Originally created by @Sakura4036 on GitHub (Jul 9, 2024).

Self Checks

  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

0.6.13

Cloud or Self Hosted

Self Hosted (Source)

Steps to reproduce

  1. create or use a tool which return json message by using create_json_message function
  2. use the returned data in in the code execution node

✔️ Expected Behavior

The tool's json output returns the data returned by create_json_message in the tool definition directly! This means that I can't use this data directly and need to use the list index (i.e. arg1[0] )to get the json data.

Actual Behavior

the tool's json output a dictionary list instead of returning the tool's output directly.

worng: use the returned data directly:

image

right: use the list index (i.e. arg1[0] )to get the json data:

image

Originally created by @Sakura4036 on GitHub (Jul 9, 2024). ### Self Checks - [X] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [X] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [X] I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). - [X] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:) - [X] Please do not modify this template :) and fill in all the required fields. ### Dify version 0.6.13 ### Cloud or Self Hosted Self Hosted (Source) ### Steps to reproduce 1. create or use a tool which return json message by using `create_json_message` function 2. use the returned data in in the code execution node ### ✔️ Expected Behavior The tool's json output returns the data returned by `create_json_message` in the tool definition **directly**! This means that I can't use this data directly and need to use the **list index** (i.e. `arg1[0]` )to get the json data. ### ❌ Actual Behavior the tool's json output a dictionary list instead of returning the tool's output directly. #### worng: use the returned data directly: ![image](https://github.com/langgenius/dify/assets/42060616/75ff22c5-97e3-4643-97fb-3676a1162ddd) #### right: use the **list index** (i.e. `arg1[0]` )to get the json data: ![image](https://github.com/langgenius/dify/assets/42060616/484e21b4-7576-4fa4-8145-da7cb21c5a73)
yindo added the 🐞 bug label 2026-02-21 18:06:50 -05:00
yindo closed this issue 2026-02-21 18:06:50 -05:00
Author
Owner

@Sakura4036 commented on GitHub (Jul 9, 2024):

@hjlarry

@Sakura4036 commented on GitHub (Jul 9, 2024): @hjlarry
Author
Owner

@dosubot[bot] commented on GitHub (Jul 9, 2024):

The tool's JSON output is structured as a dictionary list instead of returning the tool's output directly to ensure that the data is organized in a way that can be easily parsed and utilized. This approach allows for the inclusion of multiple tools and their respective outputs in a single, cohesive format.

For example, the external_data_tools_list property returns a list of dictionaries:

@property
def external_data_tools_list(self) -> list[dict]:
    return json.loads(self.external_data_tools) if self.external_data_tools else []

Similarly, the tool_outputs_dict property returns a dictionary:

@property
def tool_outputs_dict(self) -> dict:
    tools = self.tools
    try:
        if self.observation:
            data = json.loads(self.observation)
            result = {}
            for tool in tools:
                if tool in data:
                    result[tool] = data[tool]
                else:
                    if len(tools) == 1:
                        result[tool] = data
                    else:
                        result[tool] = {}
            return result
        else:
            return {
                tool: {} for tool in tools
            }
    except Exception as e:
        if self.observation:
            return {
                tool: self.observation for tool in tools
            }

This structured approach ensures that the output is comprehensive and can handle multiple tools and their outputs effectively [1][2].

To continue talking to Dosu, mention @dosu.

@dosubot[bot] commented on GitHub (Jul 9, 2024): <!-- Answer --> The tool's JSON output is structured as a dictionary list instead of returning the tool's output directly to ensure that the data is organized in a way that can be easily parsed and utilized. This approach allows for the inclusion of multiple tools and their respective outputs in a single, cohesive format. For example, the `external_data_tools_list` property returns a list of dictionaries: ```python @property def external_data_tools_list(self) -> list[dict]: return json.loads(self.external_data_tools) if self.external_data_tools else [] ``` Similarly, the `tool_outputs_dict` property returns a dictionary: ```python @property def tool_outputs_dict(self) -> dict: tools = self.tools try: if self.observation: data = json.loads(self.observation) result = {} for tool in tools: if tool in data: result[tool] = data[tool] else: if len(tools) == 1: result[tool] = data else: result[tool] = {} return result else: return { tool: {} for tool in tools } except Exception as e: if self.observation: return { tool: self.observation for tool in tools } ``` This structured approach ensures that the output is comprehensive and can handle multiple tools and their outputs effectively <sup>[[1]](https://github.com/langgenius/dify/blob/main/api/models/model.py)</sup><sup>[[2]](https://github.com/langgenius/dify/blob/main/api/core/tools/provider/builtin/json_process/tools/parse.py)</sup>. <!-- Dosu Comment Footer --> *To continue talking to [Dosu](https://dosu.dev), mention @dosu.*
Author
Owner

@hjlarry commented on GitHub (Jul 9, 2024):

because the create_json_message function should return a ToolInvokeMessage like other functions create_text_message, create_link_message.
and the tools are designed to support response both ToolInvokeMessage and list[ToolInvokeMessage]

for example, when you design a tool, in the _invoke method you return [self.create_text_message('a'), self.create_text_message('b')], the final result is "text": "a\nb",.
So for the json type, use list is a kind of compatibility.

@hjlarry commented on GitHub (Jul 9, 2024): because the `create_json_message` function should return a `ToolInvokeMessage` like other functions `create_text_message`, `create_link_message`. and the tools are designed to support response both `ToolInvokeMessage` and `list[ToolInvokeMessage]` for example, when you design a tool, in the `_invoke` method you return `[self.create_text_message('a'), self.create_text_message('b')]`, the final result is `"text": "a\nb",`. So for the json type, use list is a kind of compatibility.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#4513