n8n-io/n8n · error · Error

Agent "${this.name}" has tools requiring approval or suspend

Error message

Agent "${this.name}" has tools requiring approval or suspend/resume but no checkpoint storage. Add .checkpoint('memory') for in-process storage, or pass a persistent store (e.g. LibSQLStore, PgStore).

What it means

Thrown by Agent.build() before any network connections when static or deferred tools have a suspendSchema (meaning they can suspend/resume or require approval) but no checkpoint store is configured. The library does a fast pre-check on known tool configurations so it fails immediately rather than after connecting to MCP servers. Suspendable tools need checkpoint storage to persist their suspended state across resume cycles.

Source

Thrown at packages/@n8n/agents/src/sdk/agent.ts:986

		const finalTools = [...this.tools];
		const configuredDeferredTools = [...this.deferredTools];

		if (this.workspaceInstance) {
			const wsTools = this.workspaceInstance.getTools();
			finalTools.push(...wsTools);
		}

		const finalStaticTools = finalTools;
		const finalDeferredTools = configuredDeferredTools;

		// Validate checkpoint requirement from static tools and known MCP approval config
		// before attempting any network connections (allows fast failure).
		const staticNeedsCheckpoint =
			finalStaticTools.some((t) => t.suspendSchema) ||
			finalDeferredTools.some((t) => t.suspendSchema);
		const mcpNeedsCheckpoint = this.mcpClients.some((c) => c.declaresApproval());
		if ((staticNeedsCheckpoint || mcpNeedsCheckpoint) && !this.checkpointStore) {
			throw new Error(
				`Agent "${this.name}" has tools requiring approval or suspend/resume but no checkpoint storage. ` +
					"Add .checkpoint('memory') for in-process storage, " +
					'or pass a persistent store (e.g. LibSQLStore, PgStore).',
			);
		}

		// Resolve tools from all MCP clients.
		const mcpToolLists = await Promise.all(this.mcpClients.map(async (c) => await c.listTools()));
		const mcpTools = ensureUniqueMcpToolNames(mcpToolLists.flat());
		const mcpConnectionFailures = this.getMcpConnectionFailures();

		// Detect collisions between direct, deferred, and MCP tools.
		const staticCollisions = findDuplicateToolNames(finalStaticTools);
		if (staticCollisions.length > 0) {
			throw new Error(
				`Static tool name collision — the following tool names resolve to duplicates: ${staticCollisions.join(', ')}`,
			);
		}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Call agent.checkpoint('memory') for in-process (non-persistent, development) checkpoint storage.
  2. Call agent.checkpoint(new LibSQLStore(...)) or agent.checkpoint(new PgStore(...)) for production persistent storage.
  3. Remove the suspendSchema from the tool if suspend/resume is not needed.

Example fix

// before
const agent = new Agent('a')
  .model(m)
  .instructions('...')
  .tools([approvalRequiredTool]);
// after
const agent = new Agent('a')
  .model(m)
  .instructions('...')
  .checkpoint('memory')
  .tools([approvalRequiredTool]);
Defensive patterns

Strategy: validation

Validate before calling

const toolsNeedCheckpoint = (tools: { suspendSchema?: unknown }[]) =>
  tools.some((t) => t.suspendSchema);
if (toolsNeedCheckpoint(myTools) && !hasCheckpointStore) {
  agent.checkpoint('memory'); // or a persistent store
}

Prevention

When it happens

Trigger: Adding a tool with a suspendSchema (approval-required or suspend/resume tool) to an agent without calling agent.checkpoint('memory') or agent.checkpoint(persistentStore). Also triggered by deferred tools with suspendSchema or MCP clients that declare approval support.

Common situations: Adding an approval-gated MCP tool or a human-in-the-loop tool without setting up checkpoint persistence. Upgrading a tool to require approval but forgetting to add checkpoint storage. Developing locally with in-process tools and not realizing one was changed to suspendable.

Related errors


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