{"record":{"id":"4de028894a3c95fe","repo":"n8n-io/n8n","slug":"human-in-the-loop-nodes-cannot-be-used-inside-a-su","errorCode":null,"errorMessage":"Human-in-the-Loop nodes cannot be used inside a sub-agent. Move \"${action.nodeName}\" to the top-level workflow.","messagePattern":"Human-in-the-Loop nodes cannot be used inside a sub-agent\\. Move \"(.+?)\" to the top-level workflow\\.","errorType":"exception","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/resolveSubAgentRequest.ts","lineNumber":52,"sourceCode":"\n\twhile (isEngineRequest(current)) {\n\t\tassertNoHitlActions(node, current.actions);\n\t\tctx.getExecutionCancelSignal?.()?.throwIfAborted?.();\n\n\t\tconst actionResponses = await Promise.all(\n\t\t\tcurrent.actions.map(async (action) => await executeEngineAction(node, action, tools)),\n\t\t);\n\n\t\tcurrent = await deps.runAgentBatch({ actionResponses, metadata: current.metadata });\n\t}\n\n\treturn current;\n}\n\nfunction assertNoHitlActions(node: INode, actions: Action[]): void {\n\tfor (const action of actions) {\n\t\tif (action.metadata?.hitl) {\n\t\t\tthrow new UserError(\n\t\t\t\t`Human-in-the-Loop nodes cannot be used inside a sub-agent. Move \"${action.nodeName}\" to the top-level workflow.`,\n\t\t\t\t{\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Approval flows need the top-level engine; the sub-agent step is aborted (sibling tool calls skipped).',\n\t\t\t\t\textra: { node: node.name },\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n}\n","sourceCodeStart":34,"sourceCodeEnd":63,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/agents/Agent/agents/ToolsAgent/V3/helpers/resolveSubAgentRequest.ts#L34-L63","documentation":"Thrown by assertNoHitlActions when a sub-agent (Agent Tool V3 running inside a top-level agent) receives an action whose metadata.hitl flag is set. HITL approval nodes rely on the top-level execution engine, which is not available inside a tool-callback sub-agent context, so they are rejected upfront with a clear UserError. The description notes that the sub-agent step is aborted and sibling tool calls are skipped.","triggerScenarios":"An Agent Tool (sub-agent) workflow contains a Wait for Approval / HITL node. The top-level engine routes its actions through resolveSubAgentRequest, which detects the hitl flag and refuses.","commonSituations":"User nested an approval flow inside an Agent Tool expecting it to block; refactored a top-level workflow into a sub-agent without removing the HITL node; copied an approval step into the wrong canvas.","solutions":["Move the HITL (Wait for Approval) node out of the sub-agent and into the top-level workflow.","Replace the HITL node inside the sub-agent with a non-blocking alternative (e.g. auto-approve, or return a default response).","Redesign so the sub-agent returns a value and the top-level workflow performs the approval."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Authoring-time validation: scan the sub-agent workflow for HITL nodes before registering it\nconst hitlNodes = subWorkflow.nodes.filter(n => n.type.includes('hitl') || n.type.includes('approval'));\nif (hitlNodes.length > 0) {\n  throw new UserError('Sub-agent workflow contains HITL nodes — move them to the top-level workflow.');\n}","typeGuard":"function isHitlAction(action: Action): boolean {\n  return !!action.metadata?.hitl;\n}","tryCatchPattern":null,"preventionTips":["Never place Wait-for-Approval nodes inside an Agent Tool sub-agent.","Keep HITL at the top-level workflow canvas.","If a sub-agent needs approval, have it return a 'pending-approval' value and let the top-level workflow gate on it."],"tags":["langchain","agent","tools-agent","hitl","sub-agent","approval","v3"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}