n8n-io/n8n · error · Error
Agent " " has tools requiring approval or suspend/resume…
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.
Solutions
- Call agent.checkpoint('memory') for in-process (non-persistent, development) checkpoint storage.
- Call agent.checkpoint(new LibSQLStore(...)) or agent.checkpoint(new PgStore(...)) for production persistent storage.
- 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
- Call agent.checkpoint('memory') whenever using approval or suspend/resume tools.
- Use a persistent checkpoint store (LibSQLStore, PgStore) in production.
- Audit tool definitions for suspendSchema before building the agent.
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
- Agent " " requires a model
- Agent " " requires instructions
- . This is most likely because some of your tools are…
- Human-in-the-Loop nodes cannot be used inside a sub-agent…
- Invalid memory configuration. Use: new Memory() for…
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d8db01e658c3901c.
Report an issue: GitHub.
Appendix: 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)