n8n-io/n8n · error · Error
${toolName} was registered without a runSubAgent callback, a
Error message
${toolName} was registered without a runSubAgent callback, and no host runner was provided. Register it on an Agent (for inline delegation) or pass runSubAgent. What it means
Thrown at runtime inside the delegate tool's handler when options.runSubAgent is falsy. The createDelegateSubAgentTool function creates a tool that needs a runner to actually execute the child agent. When registered on an Agent (via the Agent's delegate method), the Agent's build process injects runSubAgent automatically. If the tool is used standalone without that injection, the handler has no way to execute the child and fails.
Source
Thrown at packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts:667
if (output.status === 'suspended') {
return await cascadeChildSuspension(ctx, request, output);
}
return output;
}
const childPathIndexKey = getChildPathIndexKey(ctx);
const childPathIndex = childPathIndexes.get(childPathIndexKey) ?? 0;
taskPath = createChildSubAgentTaskPath(input.taskName, childPathIndex);
childPathIndexes.set(childPathIndexKey, childPathIndex + 1);
request = createDelegateSubAgentRequest(input, ctx, taskPath, childPathIndex, options.policy);
startedAt = Date.now();
emitSubAgentStarted(ctx, request, startedAt);
const toolName = options.name ?? DELEGATE_SUB_AGENT_TOOL_NAME;
if (!options.runSubAgent) {
throw new Error(
`${toolName} was registered without a runSubAgent callback, and no host runner was provided. Register it on an Agent (for inline delegation) or pass runSubAgent.`,
);
}
const output = await options.runSubAgent(
request,
createRunnerHelpers(ctx, request, options.name),
);
emitSubAgentCompleted(ctx, request, output, startedAt);
if (
output.status === 'suspended' &&
options.resumeSubAgent !== undefined &&
isInterruptibleToolContext(ctx)
) {
return await cascadeChildSuspension(ctx, request, output);
}
return output;
} catch (error) {
// When the parent has a signal it is the authority: `isAbortError` alsoView on GitHub (pinned to 5ac6606e81)
Solutions
- Register the delegate tool through the Agent's .delegate() method instead of createDelegateSubAgentTool + .tools().
- If using createDelegateSubAgentTool directly, pass a runSubAgent callback that invokes your host's child-agent runner.
- Ensure the Agent's build() method runs before the tool is invoked (the build injects runSubAgent).
Example fix
// before
const tool = createDelegateSubAgentTool({});
agent.tools([tool]); // runSubAgent never injected
// after
agent.delegate(); // Agent build injects runSubAgent automatically Defensive patterns
Strategy: validation
Validate before calling
// Ensure the delegate tool is registered through the Agent, not standalone:
if (!options.runSubAgent && !registeredViaAgent) {
throw new Error('Delegate tool needs runSubAgent or Agent registration');
} Prevention
- Register delegate tools via Agent.delegate() so the build injects runSubAgent automatically.
- Do not push createDelegateSubAgentTool() output into agent.tools() manually.
- If using a host runner, always pass a runSubAgent callback to createDelegateSubAgentTool.
When it happens
Trigger: Creating a delegate tool with createDelegateSubAgentTool() and adding it to an agent via a path that bypasses the Agent's built-in delegate wiring (e.g. constructing the tool manually and pushing it into .tools()). Or passing the tool to a custom runtime that does not set runSubAgent.
Common situations: Building a custom agent class or runtime that does not extend the Agent's delegate registration. Extracting the tool for testing without mocking runSubAgent. Migrating from a manual tool registration pattern to the Agent builder without removing the old manual registration.
Related errors
- Invalid delegate sub-agent tool name "${name}": must start w
- ${toolName} requires resumeSubAgent and cancelSubAgent to be
- ${toolName} host runner does not support inline delegation w
- Model ID is required
- Delegated child input is missing or invalid
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/0aefce3726ad9ed4.
Report an issue: GitHub.