{"record":{"id":"d8db01e658c3901c","repo":"n8n-io/n8n","slug":"agent-this-name-has-tools-requiring-approval","errorCode":null,"errorMessage":"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).","messagePattern":"Agent \"(.+?)\" 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\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/sdk/agent.ts","lineNumber":986,"sourceCode":"\t\tconst finalTools = [...this.tools];\n\t\tconst configuredDeferredTools = [...this.deferredTools];\n\n\t\tif (this.workspaceInstance) {\n\t\t\tconst wsTools = this.workspaceInstance.getTools();\n\t\t\tfinalTools.push(...wsTools);\n\t\t}\n\n\t\tconst finalStaticTools = finalTools;\n\t\tconst finalDeferredTools = configuredDeferredTools;\n\n\t\t// Validate checkpoint requirement from static tools and known MCP approval config\n\t\t// before attempting any network connections (allows fast failure).\n\t\tconst staticNeedsCheckpoint =\n\t\t\tfinalStaticTools.some((t) => t.suspendSchema) ||\n\t\t\tfinalDeferredTools.some((t) => t.suspendSchema);\n\t\tconst mcpNeedsCheckpoint = this.mcpClients.some((c) => c.declaresApproval());\n\t\tif ((staticNeedsCheckpoint || mcpNeedsCheckpoint) && !this.checkpointStore) {\n\t\t\tthrow new Error(\n\t\t\t\t`Agent \"${this.name}\" has tools requiring approval or suspend/resume but no checkpoint storage. ` +\n\t\t\t\t\t\"Add .checkpoint('memory') for in-process storage, \" +\n\t\t\t\t\t'or pass a persistent store (e.g. LibSQLStore, PgStore).',\n\t\t\t);\n\t\t}\n\n\t\t// Resolve tools from all MCP clients.\n\t\tconst mcpToolLists = await Promise.all(this.mcpClients.map(async (c) => await c.listTools()));\n\t\tconst mcpTools = ensureUniqueMcpToolNames(mcpToolLists.flat());\n\t\tconst mcpConnectionFailures = this.getMcpConnectionFailures();\n\n\t\t// Detect collisions between direct, deferred, and MCP tools.\n\t\tconst staticCollisions = findDuplicateToolNames(finalStaticTools);\n\t\tif (staticCollisions.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Static tool name collision — the following tool names resolve to duplicates: ${staticCollisions.join(', ')}`,\n\t\t\t);\n\t\t}","sourceCodeStart":968,"sourceCodeEnd":1004,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/sdk/agent.ts#L968-L1004","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst agent = new Agent('a')\n  .model(m)\n  .instructions('...')\n  .tools([approvalRequiredTool]);\n// after\nconst agent = new Agent('a')\n  .model(m)\n  .instructions('...')\n  .checkpoint('memory')\n  .tools([approvalRequiredTool]);","handlingStrategy":"validation","validationCode":"const toolsNeedCheckpoint = (tools: { suspendSchema?: unknown }[]) =>\n  tools.some((t) => t.suspendSchema);\nif (toolsNeedCheckpoint(myTools) && !hasCheckpointStore) {\n  agent.checkpoint('memory'); // or a persistent store\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["checkpoint","suspend-resume","approval","configuration","agent"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}