From 7dc48510dc5bc2ae507cc24c9c079a069b44fb4c Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 19 Dec 2025 19:19:42 -0800 Subject: [PATCH] fix(tool-input): allow multiple instances of workflow block or kb tools as agent tools (#2495) * fix(tool-input): allow multiple instances of workflow block or kb tools as agent tools * ack PR comments --- .../components/tool-input/tool-input.tsx | 5 +++ .../emcn/components/popover/popover.tsx | 4 +- apps/sim/providers/utils.ts | 10 ++++- apps/sim/tools/index.ts | 43 ++++++++++++++++--- bun.lock | 16 +++---- package.json | 2 +- 6 files changed, 62 insertions(+), 18 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx index 882a96839..7d209c115 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx @@ -982,6 +982,11 @@ export function ToolInput({ if (hasMultipleOperations(blockType)) { return false } + // Allow multiple instances for workflow and knowledge blocks + // Each instance can target a different workflow/knowledge base + if (blockType === 'workflow' || blockType === 'knowledge') { + return false + } return selectedTools.some((tool) => tool.toolId === toolId) } diff --git a/apps/sim/components/emcn/components/popover/popover.tsx b/apps/sim/components/emcn/components/popover/popover.tsx index a01f30c9f..dd8a06e4a 100644 --- a/apps/sim/components/emcn/components/popover/popover.tsx +++ b/apps/sim/components/emcn/components/popover/popover.tsx @@ -720,8 +720,10 @@ const PopoverSearch = React.forwardRef( } React.useEffect(() => { + setSearchQuery('') + onValueChange?.('') inputRef.current?.focus() - }, []) + }, [setSearchQuery, onValueChange]) return (
diff --git a/apps/sim/providers/utils.ts b/apps/sim/providers/utils.ts index 179df6e0b..9db3098e9 100644 --- a/apps/sim/providers/utils.ts +++ b/apps/sim/providers/utils.ts @@ -479,8 +479,16 @@ export async function transformBlockTool( const llmSchema = await createLLMToolSchema(toolConfig, userProvidedParams) + // Create unique tool ID by appending resource ID for multi-instance tools + let uniqueToolId = toolConfig.id + if (toolId === 'workflow_executor' && userProvidedParams.workflowId) { + uniqueToolId = `${toolConfig.id}_${userProvidedParams.workflowId}` + } else if (toolId.startsWith('knowledge_') && userProvidedParams.knowledgeBaseId) { + uniqueToolId = `${toolConfig.id}_${userProvidedParams.knowledgeBaseId}` + } + return { - id: toolConfig.id, + id: uniqueToolId, name: toolConfig.name, description: toolConfig.description, params: userProvidedParams, diff --git a/apps/sim/tools/index.ts b/apps/sim/tools/index.ts index 34c242b3d..b4898a686 100644 --- a/apps/sim/tools/index.ts +++ b/apps/sim/tools/index.ts @@ -16,6 +16,26 @@ import { const logger = createLogger('Tools') +/** + * Normalizes a tool ID by stripping resource ID suffix (UUID). + * Workflow tools: 'workflow_executor_' -> 'workflow_executor' + * Knowledge tools: 'knowledge_search_' -> 'knowledge_search' + */ +function normalizeToolId(toolId: string): string { + // Check for workflow_executor_ pattern + if (toolId.startsWith('workflow_executor_') && toolId.length > 'workflow_executor_'.length) { + return 'workflow_executor' + } + // Check for knowledge__ pattern + const knowledgeOps = ['knowledge_search', 'knowledge_upload_chunk', 'knowledge_create_document'] + for (const op of knowledgeOps) { + if (toolId.startsWith(`${op}_`) && toolId.length > op.length + 1) { + return op + } + } + return toolId +} + /** * Maximum request body size in bytes before we warn/error about size limits. * Next.js 16 has a default middleware/proxy body limit of 10MB. @@ -186,20 +206,29 @@ export async function executeTool( try { let tool: ToolConfig | undefined + // Normalize tool ID to strip resource suffixes (e.g., workflow_executor_ -> workflow_executor) + const normalizedToolId = normalizeToolId(toolId) + // If it's a custom tool, use the async version with workflowId - if (toolId.startsWith('custom_')) { + if (normalizedToolId.startsWith('custom_')) { const workflowId = params._context?.workflowId - tool = await getToolAsync(toolId, workflowId) + tool = await getToolAsync(normalizedToolId, workflowId) if (!tool) { - logger.error(`[${requestId}] Custom tool not found: ${toolId}`) + logger.error(`[${requestId}] Custom tool not found: ${normalizedToolId}`) } - } else if (toolId.startsWith('mcp-')) { - return await executeMcpTool(toolId, params, executionContext, requestId, startTimeISO) + } else if (normalizedToolId.startsWith('mcp-')) { + return await executeMcpTool( + normalizedToolId, + params, + executionContext, + requestId, + startTimeISO + ) } else { // For built-in tools, use the synchronous version - tool = getTool(toolId) + tool = getTool(normalizedToolId) if (!tool) { - logger.error(`[${requestId}] Built-in tool not found: ${toolId}`) + logger.error(`[${requestId}] Built-in tool not found: ${normalizedToolId}`) } } diff --git a/bun.lock b/bun.lock index c41820447..e5af8d82d 100644 --- a/bun.lock +++ b/bun.lock @@ -37,7 +37,7 @@ "drizzle-kit": "^0.31.4", "husky": "9.1.7", "lint-staged": "16.0.0", - "turbo": "2.6.3", + "turbo": "2.7.0", }, }, "apps/docs": { @@ -3303,19 +3303,19 @@ "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], - "turbo": ["turbo@2.6.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.3", "turbo-darwin-arm64": "2.6.3", "turbo-linux-64": "2.6.3", "turbo-linux-arm64": "2.6.3", "turbo-windows-64": "2.6.3", "turbo-windows-arm64": "2.6.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA=="], + "turbo": ["turbo@2.7.0", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.0", "turbo-darwin-arm64": "2.7.0", "turbo-linux-64": "2.7.0", "turbo-linux-arm64": "2.7.0", "turbo-windows-64": "2.7.0", "turbo-windows-arm64": "2.7.0" }, "bin": { "turbo": "bin/turbo" } }, "sha512-1dUGwi6cSSVZts1BwJa/Gh7w5dPNNGsNWZEAuRKxXWME44hTKWpQZrgiPnqMc5jJJOovzPK5N6tL+PHYRYL5Wg=="], - "turbo-darwin-64": ["turbo-darwin-64@2.6.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlJJDc1CQ7SK5Y5qnl7AzpkvKSnpkfPmnA+HeU/sgny3oHZckPV2776ebO2M33CYDSor7+8HQwaodY++IINhYg=="], + "turbo-darwin-64": ["turbo-darwin-64@2.7.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-gwqL7cJOSYrV/jNmhXM8a2uzSFn7GcUASOuen6OgmUsafUj9SSWcgXZ/q0w9hRoL917hpidkdI//UpbxbZbwwg=="], - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.6.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MwVt7rBKiOK7zdYerenfCRTypefw4kZCue35IJga9CH1+S50+KTiCkT6LBqo0hHeoH2iKuI0ldTF2a0aB72z3w=="], + "turbo-darwin-arm64": ["turbo-darwin-arm64@2.7.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-f3F5DYOnfE6lR6v/rSld7QGZgartKsnlIYY7jcF/AA7Wz27za9XjxMHzb+3i4pvRhAkryFgf2TNq7eCFrzyTpg=="], - "turbo-linux-64": ["turbo-linux-64@2.6.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cqpcw+dXxbnPtNnzeeSyWprjmuFVpHJqKcs7Jym5oXlu/ZcovEASUIUZVN3OGEM6Y/OTyyw0z09tOHNt5yBAVg=="], + "turbo-linux-64": ["turbo-linux-64@2.7.0", "", { "os": "linux", "cpu": "x64" }, "sha512-KsC+UuKlhjCL+lom10/IYoxUsdhJOsuEki72YSr7WGYUSRihcdJQnaUyIDTlm0nPOb+gVihVNBuVP4KsNg1UnA=="], - "turbo-linux-arm64": ["turbo-linux-arm64@2.6.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-MterpZQmjXyr4uM7zOgFSFL3oRdNKeflY7nsjxJb2TklsYqiu3Z9pQ4zRVFFH8n0mLGna7MbQMZuKoWqqHb45w=="], + "turbo-linux-arm64": ["turbo-linux-arm64@2.7.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1tjIYULeJtpmE/ovoI9qPBFJCtUEM7mYfeIMOIs4bXR6t/8u+rHPwr3j+vRHcXanIc42V1n3Pz52VqmJtIAviw=="], - "turbo-windows-64": ["turbo-windows-64@2.6.3", "", { "os": "win32", "cpu": "x64" }, "sha512-biDU70v9dLwnBdLf+daoDlNJVvqOOP8YEjqNipBHzgclbQlXbsi6Gqqelp5er81Qo3BiRgmTNx79oaZQTPb07Q=="], + "turbo-windows-64": ["turbo-windows-64@2.7.0", "", { "os": "win32", "cpu": "x64" }, "sha512-KThkAeax46XiH+qICCQm7R8V2pPdeTTP7ArCSRrSLqnlO75ftNm8Ljx4VAllwIZkILrq/GDM8PlyhZdPeUdDxQ=="], - "turbo-windows-arm64": ["turbo-windows-arm64@2.6.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-dDHVKpSeukah3VsI/xMEKeTnV9V9cjlpFSUs4bmsUiLu3Yv2ENlgVEZv65wxbeE0bh0jjpmElDT+P1KaCxArQQ=="], + "turbo-windows-arm64": ["turbo-windows-arm64@2.7.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-kzI6rsQ3Ejs+CkM9HEEP3Z4h5YMCRxwIlQXFQmgXSG3BIgorCkRF2Xr7iQ2i9AGwY/6jbiAYeJbvi3yCp+noFw=="], "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="], diff --git a/package.json b/package.json index ff8685c5a..34d8de099 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "drizzle-kit": "^0.31.4", "husky": "9.1.7", "lint-staged": "16.0.0", - "turbo": "2.6.3" + "turbo": "2.7.0" }, "lint-staged": { "*.{js,jsx,ts,tsx,json,css,scss}": [