My AI Agent not able to get response from sub-workflow tool call even though the tool returns valid response

Describe the problem/error/question

I have an AI Agent that calls a sub-workflow tool. The sub-workflow tool calls Jira to search for some ticket and then return a JSON array that contains the tickets matching the search criteria. Output of the sub-workflow tool looks like below when I look at the execution log:

[
{
“id”: “10080”,
“key”: “MAN-17”,
“description”: “XYZ”,
“status”: “To Do”,
“summary”: “XYZ”
},
{
“id”: “10079”,
“key”: “MAN-16”,
“description”: “XYZ”,
“status”: “To Do”,
“summary”: “XYZ”
},
{
“id”: “10004”,
“key”: “MAN-5”,
“description”: “XYZ”,
“status”: “To Do”,
“summary”: “XYZ”
}
].

However, when I look at the AI Agent output from the execution log, the Agent doesn’t seem to see the response from the tool and is showing empty . My AI Agent’s prompt is below:
<system_instruction>

Role

You are a Direct Data Relay. Your only task is to fetch data from Jira and display it.

Tool Specifications

  1. Jira-Child:
    • input: { “parent_filter”: “string”, “child_filter”: “string” }

Logic Flow

  1. Step 1: Use the process name from the user to call the Jira-Child tool.
  2. Step 2: Provide the raw output of that tool directly to the user. Do not summarize. Do not edit. Do not iterate. Just show the JSON.

Constraints

  • Literalism: If the tool returns an empty array [], show [].
  • Mandatory Input: You MUST pass “Step1” as the child_filter when calling the tool.
    </system_instruction>

Any suggestion why my Agent is not able to see the child workflow tool’s response?

What is the error message (if any)?

No error message when executing the AI agent or tool. Just the AI agent cannot see the response from the tool, even though the execution log shows the tool output contains the right response.

Please share your workflow

Sub-workflow tool:
{
  "nodes": [
    {
      "parameters": {
        "operation": "getAll",
        "returnAll": true,
        "options": {
          "fields": "key",
          "jql": "=project=MAN and summary ~ \"{{ $json.parent_filter }}\""
        }
      },
      "type": "n8n-nodes-base.jira",
      "typeVersion": 1,
      "position": [
        -64,
        0
      ],
      "id": "3cafc94e-b0d8-4258-802b-12b84a55c5fc",
      "name": "Get many issues",
      "credentials": {
        "jiraSoftwareCloudApi": {
          "id": "i8pqNIwkDVp2hKlo",
          "name": "Jira SW Cloud account"
        }
      }
    },
    {
      "parameters": {
        "operation": "getAll",
        "returnAll": true,
        "options": {
          "fields": "key,description,status,summary,customfield_10038,customfield_10039,customfield_10041,customfield_10042,customfield_10043",
          "jql": "=project=MAN and parent={{ $json.key }} and labels={{ $('When Executed by Another Workflow').first().json.child_filter }}"
        }
      },
      "type": "n8n-nodes-base.jira",
      "typeVersion": 1,
      "position": [
        160,
        0
      ],
      "id": "bb8c38ed-eb8c-4353-b351-28f0a0e58f4c",
      "name": "Get many issues1",
      "credentials": {
        "jiraSoftwareCloudApi": {
          "id": "i8pqNIwkDVp2hKlo",
          "name": "Jira SW Cloud account"
        }
      }
    },
    {
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "child_filter"
            },
            {
              "name": "parent_filter"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        -288,
        0
      ],
      "id": "744480e1-1093-48de-8cdc-22ac0906faf3",
      "name": "When Executed by Another Workflow"
    },
    {
      "parameters": {
        "jsCode": "return items.map(item => {\n  // Jira Simplified Output puts fields at the top level\n  const data = item.json;\n  const key = data.key;\n\n  return {\n    json: {\n      id: data.id,\n      key: key,\n      description: data.fields.description,\n      status: data.fields.status.name,\n      summary: data.fields.summary,\n      recipient_email: data.fields.customfield_10038,\n      chase_frequency: data.fields.customfield_10039,\n      archive_folder: data.fields.customfield_10041,\n      deadline: data.fields.customfield_10042,\n      last_chase_date: data.fields.customfield_10043\n    }\n  };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        368,
        0
      ],
      "id": "bd32dd8f-e755-4388-85a3-b9db4516d52a",
      "name": "Code in JavaScript"
    }
  ],
  "connections": {
    "Get many issues": {
      "main": [
        [
          {
            "node": "Get many issues1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many issues1": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Get many issues",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        []
      ]
    }
  },
  "pinData": {},
  "meta": {
    "instanceId": "e7c260f21e76c6e244587a9b9f44f139839ab96524b5135ec8e14b5aa3e1c353"
  }
}

AI Agent workflow:

{
“nodes”: [
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.chatTrigger”,
“typeVersion”: 1.4,
“position”: [
0,
-64
],
“id”: “52217fa7-18ef-432f-9fea-60dcdbadd9a4”,
“name”: “When chat message received”,
“webhookId”: “75124893-f413-4bab-a99c-7e407c9aa0cd”
},
{
“parameters”: {
“options”: {
“systemMessage”: “=<system_instruction>\n## Role\nYou are a Direct Data Relay. Your only task is to fetch data from Jira and display it.\n\n## Tool Specifications\n1. Jira-Child: \n - input: { “parent_filter”: “string”, “child_filter”: “string” }\n\n## Logic Flow\n1. Step 1: Use the process name from the user to call the Jira-Child tool.\n2. Step 2: Provide the raw output of that tool directly to the user. Do not summarize. Do not edit. Do not iterate. Just show the JSON.\n\n## Constraints\n- Literalism: If the tool returns an empty array [], show [].\n- Mandatory Input: You MUST pass “Step1” as the child_filter when calling the tool.\n</system_instruction>”,
“maxIterations”: 20
}
},
“type”: “@n8n/n8n-nodes-langchain.agent”,
“typeVersion”: 3,
“position”: [
224,
-160
],
“id”: “1db08876-48c8-46dd-a058-df2fd12b157b”,
“name”: “AI Agent1”
},
{
“parameters”: {
“description”: “Use this tool to search and filter Jira issues specifically for process automation. You MUST provide two parameters: parent_filter and child_filter.\n\nparent_filter: Use the name of the process (e.g., “Q4 Process”, “Q2 Process”).\nchild_filter: Use the specific step’s label (e.g., “Step1”).\n\nOutput: Returns a JSON array of issues matching both criteria. Each object contains: id, key, description, status, summary, recipient_email, chase_frequency, archive_folder, deadline, and last_chase_date.”,
“workflowId”: {
“__rl”: true,
“value”: “4XJ3uhFcsqtjBwXO”,
“mode”: “list”,
“cachedResultUrl”: “/workflow/4XJ3uhFcsqtjBwXO”,
“cachedResultName”: “Jira-Child”
},
“workflowInputs”: {
“mappingMode”: “defineBelow”,
“value”: {
“child_filter”: “={{ /n8n-auto-generated-fromAI-override/ $fromAI(‘child_filter’, REQUIRED. The specific Jira task to target. For the initial email request process, this MUST be set to 'Step1' to ensure only the starting tasks are retrieved., ‘string’) }}”,
“parent_filter”: “={{ /n8n-auto-generated-fromAI-override/ $fromAI(‘parent_filter’, REQUIRED. The summary of the high-level process to be searched (e.g., 'Q4 Process'). This should be extracted from the user's natural language input., ‘string’) }}”
},
“matchingColumns”: ,
“schema”: [
{
“id”: “child_filter”,
“displayName”: “child_filter”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”,
“removed”: false
},
{
“id”: “parent_filter”,
“displayName”: “parent_filter”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”,
“removed”: false
}
],
“attemptToConvertTypes”: false,
“convertFieldsToString”: false
}
},
“type”: “@n8n/n8n-nodes-langchain.toolWorkflow”,
“typeVersion”: 2.2,
“position”: [
368,
64
],
“id”: “b8cc2764-af6a-4d32-b399-debe4e69a5d1”,
“name”: “Call 'Jira-Child’2”
},
{
“parameters”: {
“model”: {
“__rl”: true,
“value”: “gpt-4.1-mini”,
“mode”: “list”,
“cachedResultName”: “gpt-4.1-mini”
},
“builtInTools”: {},
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.lmChatOpenAi”,
“typeVersion”: 1.3,
“position”: [
240,
64
],
“id”: “ad066aaa-8c2c-4272-9112-accd644a8493”,
“name”: “OpenAI Chat Model1”,
“credentials”: {
“openAiApi”: {
“id”: “ba1e4J34e4KiHhh0”,
“name”: “OpenAi account”
}
}
}
],
“connections”: {
“When chat message received”: {
“main”: [
[
{
“node”: “AI Agent1”,
“type”: “main”,
“index”: 0
}
]
]
},
“Call 'Jira-Child’2”: {
“ai_tool”: [
[
{
“node”: “AI Agent1”,
“type”: “ai_tool”,
“index”: 0
}
]
]
},
“OpenAI Chat Model1”: {
“ai_languageModel”: [
[
{
“node”: “AI Agent1”,
“type”: “ai_languageModel”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateId”: “ready-to-run-ai-workflow-v4”,
“templateCredsSetupCompleted”: true,
“instanceId”: “e7c260f21e76c6e244587a9b9f44f139839ab96524b5135ec8e14b5aa3e1c353”
}
}

I run the AI Agent by type in ‘start “Q4 Process”’ in the chat window

Share the output returned by the last node

AI Agent node returns:
[

{

“output”: “

}

]

Information on your n8n setup

  • n8n version: latest, I am testing directly on the cloud version of n8n
  • Database (default: SQLite): not applicable
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app): n8n cloud
  • Operating system:

Hi @codymasteriii, if your sub workflow tool does get called and the execution of that workflow does show the json array, then perhaps try and enhance your system prompt to also include the expected output of your Jira tool. Explicitly name the variable to expect if any and what data type it is.

Hi @n8n-by-qasim,

This is not true. You do not need a special return node for the sub-workflow to return the data. All workflows by default will return the last node’s output to a calling workflow/node. Since the sub workflow is not executed via a webhook nor a chat node, this will likely error out or do nothing.

I have tried different ways of updating the prompt and also created various simple test case just to see how child workflow tool response interact with the parent AI Agent, but I can’t even get a simple case work. Does anyone have a working AI Agent example that can be shared to demonstrate how to let the AI Agent loop through a child tool’s JSON response and output the value?
For example, if the child returns [ { id: 1, key: key1 }, { id: 2, key: key2 } ], I want to see the parent AI agent loop through it and output each of the keys. Anyone mind showing an example of this simple case? I couldn’t even get this working, which is bizarre

Hi @codymasteriii unfortunately it is very difficult to help look at your problem without your workflow in a code block.

LLMs work better with Markdown and plain text compared to JSON. Maybe try and return a list of values in plain text from your sub-workflow tool call.

Here’s the AI Agent setup:
{
“nodes”: [
{
“parameters”: {
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.chatTrigger”,
“typeVersion”: 1.4,
“position”: [
1072,
-560
],
“id”: “52217fa7-18ef-432f-9fea-60dcdbadd9a4”,
“name”: “When chat message received”,
“webhookId”: “75124893-f413-4bab-a99c-7e407c9aa0cd”
},
{
“parameters”: {
“options”: {
“systemMessage”: “=# Role\nYou are a Data Processing Specialist. Your task is to act as an intermediary between the user and the run_test2_logic tool. \n\n# Objective\n1. Collect two variables from the user chat message: input (a comma-separated string) and output_type (options: “text”, “json_text”, or “array”).\n2. Call the run_test2_logic tool with these parameters.\n3. Parse the data inside the formatted_output field of the tool’s response, regardless of its format.\n4. Loop through the keys found within the parsed data and display every “Key” and “Summary” discovered.\n\n# Tool Result Handling\nThe tool will return a JSON object. You must specifically look for the key named formatted_output. \n\nDepending on the output_type requested, handle the content of formatted_output as follows:\n\n## Case 1: Array Content\n- If formatted_output is a JSON Array (e.g., [{\"key\": \"XYZ\", \"summary\": \"XYZ1\"}]): \n - Loop through the array and for each items iterated, extract the value of the item’s “key” property.\n\n## Case 2: JSON String Content\n- If formatted_output is a String starting with [ (e.g., \"[{\\\"key\\\": \\\"XYZ\\\",\\\"summary\\\": \\\"XYZ1\\\"}]\"):\n - Parse the string into a valid JSON object first, then iterate through all the “key” and “summary” properties and extract their associated values .\n\n## Case 3: KV Text Content\n- If formatted_output is a Plain Text string (e.g., \"{Key=XYZ,summary=XYZ1},{Key=ABC,summary=ABC1}\"):\n - Use pattern matching to find all occurrences within braces {}. Extract the value appearing after the = sign.\n\n# Output Requirements\nFor every item identified during the parsing step, you must output a specific line using this format:\n- Processing Item [Number]: [Key Value] - [Summary Value]\n\n# Final Summary\nAfter the loop is complete, provide a brief summary:\n- Total Items Processed: [Count]\n- Status: Success\n- Next Step: Ask the user if they have more data to process.\n\n# Constraints\n- If the tool returns an error, explain the error to the user and ask for a new input.\n- Stay in character as a structured data assistant.\n”,
“maxIterations”: 5
}
},
“type”: “@n8n/n8n-nodes-langchain.agent”,
“typeVersion”: 3,
“position”: [
1328,
-592
],
“id”: “8afc6d1f-30bf-46f0-be9a-56c308cf771c”,
“name”: “AI Agent3”
},
{
“parameters”: {
“modelName”: “models/gemini-2.5-pro”,
“options”: {
“temperature”: 0.1,
“topP”: 0.4
}
},
“type”: “@n8n/n8n-nodes-langchain.lmChatGoogleGemini”,
“typeVersion”: 1,
“position”: [
1200,
-384
],
“id”: “7d60d8a4-158b-4a3b-8f61-c5ddb00692f3”,
“name”: “Google Gemini Chat Model2”,
“credentials”: {
“googlePalmApi”: {
“id”: “ImTcg33DXxnMmWFa”,
“name”: “Google Gemini(PaLM) Api account”
}
}
},
{
“parameters”: {
“description”: “Use this tool to process inputs and get formatted keys. It requires ‘input’ (comma-separated string) and ‘output_type’ (text, json_text, or array).”,
“workflowId”: {
“__rl”: true,
“value”: “aZhdmsrUFHH2OWSq”,
“mode”: “list”,
“cachedResultUrl”: “/workflow/aZhdmsrUFHH2OWSq”,
“cachedResultName”: “Test2”
},
“workflowInputs”: {
“mappingMode”: “defineBelow”,
“value”: {
“input”: “={{ /n8n-auto-generated-fromAI-override/ $fromAI(‘input’, , 'string') }}", "output_type": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('output_type', , ‘string’) }}”
},
“matchingColumns”: ,
“schema”: [
{
“id”: “input”,
“displayName”: “input”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”,
“removed”: false
},
{
“id”: “output_type”,
“displayName”: “output_type”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“canBeUsedToMatch”: true,
“type”: “string”,
“removed”: false
}
],
“attemptToConvertTypes”: false,
“convertFieldsToString”: false
}
},
“type”: “@n8n/n8n-nodes-langchain.toolWorkflow”,
“typeVersion”: 2.2,
“position”: [
1488,
-384
],
“id”: “685e8fc8-f6ac-44d6-baec-4c713095518f”,
“name”: “run_test2_logic”
}
],
“connections”: {
“When chat message received”: {
“main”: [
[
{
“node”: “AI Agent3”,
“type”: “main”,
“index”: 0
}
]
]
},
“Google Gemini Chat Model2”: {
“ai_languageModel”: [
[
{
“node”: “AI Agent3”,
“type”: “ai_languageModel”,
“index”: 0
}
]
]
},
“run_test2_logic”: {
“ai_tool”: [
[
{
“node”: “AI Agent3”,
“type”: “ai_tool”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateId”: “ready-to-run-ai-workflow-v4”,
“templateCredsSetupCompleted”: true,
“instanceId”: “e7c260f21e76c6e244587a9b9f44f139839ab96524b5135ec8e14b5aa3e1c353”
}
}

the chat input is “input=XYZ,ABC,RPQ; output_type=json_text”, where output_type can be text, json_text or array.
the sub-tool workflow is below:
{
“nodes”: [
{
“parameters”: {
“workflowInputs”: {
“values”: [
{
“name”: “input”
},
{
“name”: “output_type”
}
]
}
},
“type”: “n8n-nodes-base.executeWorkflowTrigger”,
“typeVersion”: 1.1,
“position”: [
0,
0
],
“id”: “1d47447b-fb36-4462-9ae6-fb588c3f0be2”,
“name”: “When Executed by Another Workflow”
},
{
“parameters”: {
“jsCode”: “// Get input values from the previous node\nconst input = $input.first().json.input; // e.g., “XYZ,ABC,RPQ”\nconst type = $input.first().json.output_type; // “text”, “json_text”, or other\n\n// Clean the string and turn into an array: [“XYZ”, “ABC”, “RPQ”]\nconst items = input.split(‘,’).map(item => item.trim());\n\nlet result;\n\nif (type === ‘text’) {\n // Returns: “{Key=XYZ},{Key=ABC},{Key=RPQ}”\n result = items.map(item => {key=${item},summary=${item+\"1\"}}).join(‘,’);\n} \nelse if (type === ‘json_text’) {\n // Returns a stringified JSON array: “[{“key”:“XYZ”},{“key”:“ABC”},{“key”:“RPQ”}]”\n const jsonArray = items.map(item => ({ key: item, summary: item + “1” }));\n result = JSON.stringify(jsonArray);\n} \nelse {\n // Returns an actual JSON array (Object)\n result = items.map(item => ({ key: item, summary: item + “1” }));\n}\n\nreturn {\n formatted_output: result\n};”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
208,
0
],
“id”: “354f0324-5cbe-405b-8d13-0e7e5fae6f24”,
“name”: “Code in JavaScript”
}
],
“connections”: {
“When Executed by Another Workflow”: {
“main”: [
[
{
“node”: “Code in JavaScript”,
“type”: “main”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“instanceId”: “e7c260f21e76c6e244587a9b9f44f139839ab96524b5135ec8e14b5aa3e1c353”
}
}

I tested this multiple times. The behavior is not very stable. In this test, all three output_type have chance to succeed (i.e., the AI agent is able to see and parse the output from the child tool). However, when running the test with different output_types multiple times, the AI Agent is not always able to see the child tool’s response. Even when the child tool is returning just a text string, the AI Agent may still output it doesn’t any result from the child tool. The other thing I am having problem with is the tool generates a JSON object that has two attributes. If I want the parser logic in the AI Agent prompt to parse both values, then the AI Agent will fail completely (at least in the number of trials I did). When the prompt only asks it to parse the key value, it will work from time to time between trials. My AI Agent instruction to parse both key and summary field is like below (using JSON Array as example):
Case 1: Array Content

  • If formatted_output is a JSON Array (e.g., [{"key": "XYZ", "summary": "XYZ1"}]):
    • Loop through the array and for each items iterated, extract the value of the item’s “key” and “summary” property.
      The overall impression I get is for a simple loop parsing JSON array instruction, the AI Agent’s behavior is quite unstable.

Please can you share this in a code block. I am unable to use the above. If it is too big, please share via google drive or a paste bin link