n8n-io/n8n · error · Error

${toolName} requires resumeSubAgent and cancelSubAgent to be

Error message

${toolName} requires resumeSubAgent and cancelSubAgent to be configured together

What it means

Thrown during createDelegateSubAgentTool when exactly one of resumeSubAgent and cancelSubAgent is provided. The library requires these two callbacks to be configured as a pair because resumption and cancellation are the two lifecycle exits for a suspended child agent — providing one without the other leaves the delegation in a half-configured state that would fail at runtime.

Source

Thrown at packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts:459

 *   agent.tool(createDelegateSubAgentTool({
 *     runSubAgent: (request) => runner.run(request),
 *     availableSubAgents,
 *     policy: { maxChildren: 10 },
 *   }));
 */
export function createDelegateSubAgentTool(options: CreateDelegateSubAgentToolOptions = {}) {
	// Per-parent child path index for stable task paths (/root/name_0, /root/name_1, ...).
	const childPathIndexes = new Map<string, number>();
	const toolName = resolveDelegateSubAgentToolName(options.name);
	const resolvedOptions: CreateDelegateSubAgentToolOptions = {
		...options,
		policy: resolveDelegateSubAgentPolicy(options.policy, toolName),
	};
	if (
		(resolvedOptions.resumeSubAgent === undefined) !==
		(resolvedOptions.cancelSubAgent === undefined)
	) {
		throw new Error(
			`${toolName} requires resumeSubAgent and cancelSubAgent to be configured together`,
		);
	}
	const inlineProviderToolInstruction = resolvedOptions.resolveInlineSubAgentProviderTools
		? "Provider-defined tools are loaded for the inline child's selected model provider."
		: 'Inline children do not inherit provider-defined tools.';

	const toolBuilder = new Tool(toolName)
		.description(resolveDelegateSubAgentDescription(resolvedOptions))
		.systemInstruction(
			resolveDelegateSubAgentSystemInstruction(
				resolvedOptions,
				toolName,
				inlineProviderToolInstruction,
			),
		)
		.input(delegateSubAgentInputSchema)
		.output(delegateSubAgentOutputSchema);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Provide both resumeSubAgent and cancelSubAgent callbacks together.
  2. If you do not need suspend/resume support, omit both callbacks entirely.
  3. If you only need resume, implement a no-op cancelSubAgent that calls the host's cancellation API.

Example fix

// before
const tool = createDelegateSubAgentTool({
  resumeSubAgent: (req, helpers) => host.resume(req),
});
// after
const tool = createDelegateSubAgentTool({
  resumeSubAgent: (req, helpers) => host.resume(req),
  cancelSubAgent: (req, ctx) => host.cancel(req),
});
Defensive patterns

Strategy: validation

Validate before calling

function validateDelegateCallbacks(opts: CreateDelegateSubAgentToolOptions): void {
  const hasResume = opts.resumeSubAgent !== undefined;
  const hasCancel = opts.cancelSubAgent !== undefined;
  if (hasResume !== hasCancel) {
    throw new Error('resumeSubAgent and cancelSubAgent must both be provided or both omitted');
  }
}
validateDelegateCallbacks(options);

Prevention

When it happens

Trigger: Calling createDelegateSubAgentTool({ resumeSubAgent: fn }) without cancelSubAgent, or vice versa. The XOR check (one is undefined, the other is not) is what trips the error.

Common situations: Intending to support suspend/resume of delegated children but forgetting the cancellation handler. Copying a partial configuration from example code that only showed resume. Upgrading from a version where these were independent options to one where they must be paired.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/d824faad96b846f2. Report an issue: GitHub.