From e02fe941867c4fb27f36d55846cd0fbc8251fa1d Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Thu, 5 Feb 2026 20:26:47 -0800 Subject: [PATCH] Clean up mcp --- apps/sim/app/api/mcp/copilot/route.ts | 154 ++----- .../orchestrator/tool-executor/index.ts | 9 + .../orchestrator/tool-executor/param-types.ts | 17 + .../tool-executor/workflow-tools/mutations.ts | 85 ++++ .../tool-executor/workflow-tools/queries.ts | 5 +- apps/sim/lib/copilot/tools/mcp/definitions.ts | 378 ++++++++++-------- 6 files changed, 344 insertions(+), 304 deletions(-) diff --git a/apps/sim/app/api/mcp/copilot/route.ts b/apps/sim/app/api/mcp/copilot/route.ts index 7e330ff01..bf7d09ead 100644 --- a/apps/sim/app/api/mcp/copilot/route.ts +++ b/apps/sim/app/api/mcp/copilot/route.ts @@ -34,144 +34,40 @@ export const dynamic = 'force-dynamic' * the workflow lifecycle and best practices. */ const MCP_SERVER_INSTRUCTIONS = ` -## Sim Workflow Copilot - Usage Guide +## Sim Workflow Copilot -You are interacting with Sim's workflow automation platform. These tools orchestrate specialized AI agents that build workflows. Follow these guidelines carefully. +Sim is a workflow automation platform. Workflows are visual pipelines of connected blocks (Agent, Function, Condition, API, integrations, etc.). The Agent block is the core — an LLM with tools, memory, structured output, and knowledge bases. ---- +### Workflow Lifecycle (Happy Path) -## Platform Knowledge +1. \`list_workspaces\` → know where to work +2. \`create_workflow(name, workspaceId)\` → get a workflowId +3. \`copilot_build(request, workflowId)\` → plan and build in one pass +4. \`copilot_test(request, workflowId)\` → verify it works +5. \`copilot_deploy("deploy as api", workflowId)\` → make it accessible externally (optional) -Sim is a workflow automation platform. Workflows are visual pipelines of blocks. +For fine-grained control, use \`copilot_plan\` → \`copilot_edit\` instead of \`copilot_build\`. Pass the plan object from copilot_plan EXACTLY as-is to copilot_edit's context.plan field. -### Block Types +### Working with Existing Workflows -**Core Logic:** -- **Agent** - The heart of Sim (LLM block with tools, memory, structured output, knowledge bases) -- **Function** - JavaScript code execution -- **Condition** - If/else branching -- **Router** - AI-powered content-based routing -- **Loop** - While/do-while iteration -- **Parallel** - Simultaneous execution -- **API** - HTTP requests +When the user refers to a workflow by name or description ("the email one", "my Slack bot"): +1. Use \`copilot_discovery\` to find it by functionality +2. Or use \`list_workflows\` and match by name +3. Then pass the workflowId to other tools -**Integrations (3rd Party):** -- OAuth: Slack, Gmail, Google Calendar, Sheets, Outlook, Linear, GitHub, Notion -- API: Stripe, Twilio, SendGrid, any REST API +### Organization -### The Agent Block +- \`rename_workflow\` — rename a workflow +- \`move_workflow\` — move a workflow into a folder (or root with null) +- \`move_folder\` — nest a folder inside another (or root with null) +- \`create_folder(name, parentId)\` — create nested folder hierarchies -The Agent block is the core of intelligent workflows: -- **Tools** - Add integrations, custom tools, web search to give it capabilities -- **Memory** - Multi-turn conversations with persistent context -- **Structured Output** - JSON schema for reliable parsing -- **Knowledge Bases** - RAG-powered document retrieval +### Key Rules -**Design principle:** Put tools INSIDE agents rather than using standalone tool blocks. - -### Triggers - -| Type | Description | -|------|-------------| -| Manual/Chat | User sends message in UI (start block: input, files, conversationId) | -| API | REST endpoint with custom input schema | -| Webhook | External services POST to trigger URL | -| Schedule | Cron-based (hourly, daily, weekly) | - -### Deployments - -| Type | Trigger | Use Case | -|------|---------|----------| -| API | Start block | REST endpoint for programmatic access | -| Chat | Start block | Managed chat UI with auth options | -| MCP | Start block | Expose as MCP tool for AI agents | -| General | Schedule/Webhook | Activate triggers to run automatically | - -**Undeployed workflows only run in the builder UI.** - -### Variable Syntax - -Reference outputs from previous blocks: \`\` -Reference environment variables: \`{{ENV_VAR_NAME}}\` - -Rules: -- Block names must be lowercase, no spaces, no special characters -- Use dot notation for nested fields: \`\` - ---- - -## Workflow Lifecycle - -1. **Create**: For NEW workflows, FIRST call create_workflow to get a workflowId -2. **Plan**: Use copilot_plan with the workflowId to plan the workflow -3. **Edit**: Use copilot_edit with the workflowId AND the plan to build the workflow -4. **Deploy**: ALWAYS deploy after building using copilot_deploy before testing/running -5. **Test**: Use copilot_test to verify the workflow works correctly -6. **Share**: Provide the user with the workflow URL after completion - ---- - -## CRITICAL: Always Pass workflowId - -- For NEW workflows: Call create_workflow FIRST, then use the returned workflowId -- For EXISTING workflows: Pass the workflowId to all copilot tools -- copilot_plan, copilot_edit, copilot_deploy, copilot_test, copilot_debug all REQUIRE workflowId - ---- - -## CRITICAL: How to Handle Plans - -The copilot_plan tool returns a structured plan object. You MUST: - -1. **Do NOT modify the plan**: Pass the plan object EXACTLY as returned to copilot_edit -2. **Do NOT interpret or summarize the plan**: The edit agent needs the raw plan data -3. **Pass the plan in the context.plan field**: \`{ "context": { "plan": } }\` -4. **Include ALL plan data**: Block configurations, connections, credentials, everything - -Example flow: -\`\`\` -1. copilot_plan({ request: "build a workflow...", workflowId: "abc123" }) - -> Returns: { "plan": { "blocks": [...], "connections": [...], ... } } - -2. copilot_edit({ - workflowId: "abc123", - message: "Execute the plan", - context: { "plan": } - }) -\`\`\` - -**Why this matters**: The plan contains technical details (block IDs, field mappings, API schemas) that the edit agent needs verbatim. Summarizing or rephrasing loses critical information. - ---- - -## CRITICAL: Error Handling - -**If the user says "doesn't work", "broke", "failed", "error" → ALWAYS use copilot_debug FIRST.** - -Don't guess. Don't plan. Debug first to find the actual problem. - ---- - -## Important Rules - -- ALWAYS deploy a workflow before attempting to run or test it -- Workflows must be deployed to have an "active deployment" for execution -- After building, call copilot_deploy with the appropriate deployment type (api, chat, or mcp) -- Return the workflow URL to the user so they can access it in Sim - ---- - -## Quick Operations (use direct tools) -- list_workflows, list_workspaces, list_folders, get_workflow: Fast database queries -- create_workflow: Create new workflow and get workflowId (CALL THIS FIRST for new workflows) -- create_folder: Create new resources - -## Workflow Building (use copilot tools) -- copilot_plan: Plan workflow changes (REQUIRES workflowId) - returns a plan object -- copilot_edit: Execute the plan (REQUIRES workflowId AND plan from copilot_plan) -- copilot_deploy: Deploy workflows (REQUIRES workflowId) -- copilot_test: Test workflow execution (REQUIRES workflowId) -- copilot_debug: Diagnose errors (REQUIRES workflowId) - USE THIS FIRST for issues +- You can test workflows immediately after building — deployment is only needed for external access (API, chat, MCP). +- All copilot tools (build, plan, edit, deploy, test, debug) require workflowId. +- If the user reports errors → use \`copilot_debug\` first, don't guess. +- Variable syntax: \`\` for block outputs, \`{{ENV_VAR}}\` for env vars. ` function createResponse(id: RequestId, result: unknown): JSONRPCResponse { @@ -378,7 +274,6 @@ async function handleBuildToolCall( } const chatId = crypto.randomUUID() - const context = (args.context as Record) || {} const requestPayload = { message: requestText, @@ -391,7 +286,6 @@ async function handleBuildToolCall( version: SIM_AGENT_VERSION, headless: true, chatId, - context, } const result = await orchestrateCopilotStream(requestPayload, { diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/index.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/index.ts index dbd3a24a9..9ca5c9763 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/index.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/index.ts @@ -38,6 +38,9 @@ import type { ListFoldersParams, ListUserWorkflowsParams, ListWorkspaceMcpServersParams, + MoveFolderParams, + MoveWorkflowParams, + RenameWorkflowParams, RunWorkflowParams, SetGlobalWorkflowVariablesParams, } from './param-types' @@ -52,6 +55,9 @@ import { executeListFolders, executeListUserWorkflows, executeListUserWorkspaces, + executeMoveFolder, + executeMoveWorkflow, + executeRenameWorkflow, executeRunWorkflow, executeSetGlobalWorkflowVariables, } from './workflow-tools' @@ -85,6 +91,9 @@ const SIM_WORKFLOW_TOOL_HANDLERS: Record< list_folders: (p, c) => executeListFolders(p as ListFoldersParams, c), create_workflow: (p, c) => executeCreateWorkflow(p as CreateWorkflowParams, c), create_folder: (p, c) => executeCreateFolder(p as CreateFolderParams, c), + rename_workflow: (p, c) => executeRenameWorkflow(p as unknown as RenameWorkflowParams, c), + move_workflow: (p, c) => executeMoveWorkflow(p as unknown as MoveWorkflowParams, c), + move_folder: (p, c) => executeMoveFolder(p as unknown as MoveFolderParams, c), get_workflow_data: (p, c) => executeGetWorkflowData(p as GetWorkflowDataParams, c), get_block_outputs: (p, c) => executeGetBlockOutputs(p as GetBlockOutputsParams, c), get_block_upstream_references: (p, c) => diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/param-types.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/param-types.ts index 30d519087..87c78ffbf 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/param-types.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/param-types.ts @@ -125,3 +125,20 @@ export interface CreateWorkspaceMcpServerParams { isPublic?: boolean workflowIds?: string[] } + +// === Workflow Organization Params === + +export interface RenameWorkflowParams { + workflowId: string + name: string +} + +export interface MoveWorkflowParams { + workflowId: string + folderId: string | null +} + +export interface MoveFolderParams { + folderId: string + parentId: string | null +} diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/mutations.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/mutations.ts index 0b5afbf12..a3c3c0efc 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/mutations.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/mutations.ts @@ -12,6 +12,9 @@ import { ensureWorkflowAccess, ensureWorkspaceAccess, getDefaultWorkspaceId } fr import type { CreateFolderParams, CreateWorkflowParams, + MoveFolderParams, + MoveWorkflowParams, + RenameWorkflowParams, RunWorkflowParams, SetGlobalWorkflowVariablesParams, VariableOperation, @@ -283,3 +286,85 @@ export async function executeSetGlobalWorkflowVariables( return { success: false, error: error instanceof Error ? error.message : String(error) } } } + +export async function executeRenameWorkflow( + params: RenameWorkflowParams, + context: ExecutionContext +): Promise { + try { + const workflowId = params.workflowId + if (!workflowId) { + return { success: false, error: 'workflowId is required' } + } + const name = typeof params.name === 'string' ? params.name.trim() : '' + if (!name) { + return { success: false, error: 'name is required' } + } + if (name.length > 200) { + return { success: false, error: 'Workflow name must be 200 characters or less' } + } + + await ensureWorkflowAccess(workflowId, context.userId) + + await db + .update(workflow) + .set({ name, updatedAt: new Date() }) + .where(eq(workflow.id, workflowId)) + + return { success: true, output: { workflowId, name } } + } catch (error) { + return { success: false, error: error instanceof Error ? error.message : String(error) } + } +} + +export async function executeMoveWorkflow( + params: MoveWorkflowParams, + context: ExecutionContext +): Promise { + try { + const workflowId = params.workflowId + if (!workflowId) { + return { success: false, error: 'workflowId is required' } + } + + await ensureWorkflowAccess(workflowId, context.userId) + + const folderId = params.folderId || null + + await db + .update(workflow) + .set({ folderId, updatedAt: new Date() }) + .where(eq(workflow.id, workflowId)) + + return { success: true, output: { workflowId, folderId } } + } catch (error) { + return { success: false, error: error instanceof Error ? error.message : String(error) } + } +} + +export async function executeMoveFolder( + params: MoveFolderParams, + context: ExecutionContext +): Promise { + try { + const folderId = params.folderId + if (!folderId) { + return { success: false, error: 'folderId is required' } + } + + const parentId = params.parentId || null + + if (parentId === folderId) { + return { success: false, error: 'A folder cannot be moved into itself' } + } + + await db + .update(workflowFolder) + .set({ parentId, updatedAt: new Date() }) + .where(eq(workflowFolder.id, folderId)) + + return { success: true, output: { folderId, parentId } } + } catch (error) { + return { success: false, error: error instanceof Error ? error.message : String(error) } + } +} diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts index dd4231b97..cc8a724f0 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts @@ -3,7 +3,6 @@ import { customTools, permissions, workflow, workflowFolder, workspace } from '@ import { and, asc, desc, eq, isNull, or } from 'drizzle-orm' import type { ExecutionContext, ToolCallResult } from '@/lib/copilot/orchestrator/types' import { - extractWorkflowNames, formatNormalizedWorkflowForCopilot, normalizeWorkflowName, } from '@/lib/copilot/tools/shared/workflow-utils' @@ -114,8 +113,6 @@ export async function executeListUserWorkflows( const workflows = await getAccessibleWorkflowsForUser(context.userId, { workspaceId, folderId }) - const names = extractWorkflowNames(workflows) - const workflowList = workflows.map((w) => ({ workflowId: w.id, workflowName: w.name || '', @@ -123,7 +120,7 @@ export async function executeListUserWorkflows( folderId: w.folderId, })) - return { success: true, output: { workflow_names: names, workflows: workflowList } } + return { success: true, output: { workflows: workflowList } } } catch (error) { return { success: false, error: error instanceof Error ? error.message : String(error) } } diff --git a/apps/sim/lib/copilot/tools/mcp/definitions.ts b/apps/sim/lib/copilot/tools/mcp/definitions.ts index 6ef285729..226662dbf 100644 --- a/apps/sim/lib/copilot/tools/mcp/definitions.ts +++ b/apps/sim/lib/copilot/tools/mcp/definitions.ts @@ -17,11 +17,21 @@ export type SubagentToolDef = { * These are fast database queries that don't need AI reasoning. */ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ + { + name: 'list_workspaces', + toolId: 'list_user_workspaces', + description: + 'List all workspaces the user has access to. Returns workspace IDs, names, and roles. Use this first to determine which workspace to operate in.', + inputSchema: { + type: 'object', + properties: {}, + }, + }, { name: 'list_workflows', toolId: 'list_user_workflows', description: - 'List all workflows the user has access to. Returns workflow IDs, names, and workspace info.', + 'List all workflows the user has access to. Returns workflow IDs, names, workspace, and folder info. Use workspaceId/folderId to scope results.', inputSchema: { type: 'object', properties: { @@ -36,20 +46,11 @@ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ }, }, }, - { - name: 'list_workspaces', - toolId: 'list_user_workspaces', - description: - 'List all workspaces the user has access to. Returns workspace IDs, names, and roles.', - inputSchema: { - type: 'object', - properties: {}, - }, - }, { name: 'list_folders', toolId: 'list_folders', - description: 'List all folders in a workspace.', + description: + 'List all folders in a workspace. Returns folder IDs, names, and parent relationships for organizing workflows.', inputSchema: { type: 'object', properties: { @@ -64,7 +65,8 @@ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ { name: 'get_workflow', toolId: 'get_user_workflow', - description: 'Get a workflow by ID. Returns the full workflow definition.', + description: + 'Get a workflow by ID. Returns the full workflow definition including all blocks, connections, and configuration.', inputSchema: { type: 'object', properties: { @@ -79,7 +81,8 @@ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ { name: 'create_workflow', toolId: 'create_workflow', - description: 'Create a new workflow. Returns the new workflow ID.', + description: + 'Create a new empty workflow. Returns the new workflow ID. Always call this FIRST before copilot_build for new workflows. Use workspaceId to place it in a specific workspace.', inputSchema: { type: 'object', properties: { @@ -106,7 +109,8 @@ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ { name: 'create_folder', toolId: 'create_folder', - description: 'Create a new folder in a workspace.', + description: + 'Create a new folder for organizing workflows. Use parentId to create nested folder hierarchies.', inputSchema: { type: 'object', properties: { @@ -126,6 +130,65 @@ export const DIRECT_TOOL_DEFS: DirectToolDef[] = [ required: ['name'], }, }, + { + name: 'rename_workflow', + toolId: 'rename_workflow', + description: 'Rename an existing workflow.', + inputSchema: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'The workflow ID to rename.', + }, + name: { + type: 'string', + description: 'The new name for the workflow.', + }, + }, + required: ['workflowId', 'name'], + }, + }, + { + name: 'move_workflow', + toolId: 'move_workflow', + description: + 'Move a workflow into a different folder. Set folderId to null to move to the workspace root.', + inputSchema: { + type: 'object', + properties: { + workflowId: { + type: 'string', + description: 'The workflow ID to move.', + }, + folderId: { + type: ['string', 'null'], + description: 'Target folder ID, or null to move to workspace root.', + }, + }, + required: ['workflowId', 'folderId'], + }, + }, + { + name: 'move_folder', + toolId: 'move_folder', + description: + 'Move a folder into another folder. Set parentId to null to move to the workspace root.', + inputSchema: { + type: 'object', + properties: { + folderId: { + type: 'string', + description: 'The folder ID to move.', + }, + parentId: { + type: ['string', 'null'], + description: 'Target parent folder ID, or null to move to workspace root.', + }, + }, + required: ['folderId', 'parentId'], + }, + }, ] export const SUBAGENT_TOOL_DEFS: SubagentToolDef[] = [ @@ -151,15 +214,15 @@ CAN DO: - Set environment variables and workflow variables CANNOT DO: -- Run or test workflows (use copilot_test separately after deploying) +- Run or test workflows (use copilot_test separately) - Deploy workflows (use copilot_deploy separately) WORKFLOW: 1. Call create_workflow to get a workflowId (for new workflows) 2. Call copilot_build with the request and workflowId 3. Build agent gathers info and builds in one pass -4. Call copilot_deploy to deploy the workflow -5. Optionally call copilot_test to verify it works`, +4. Call copilot_test to verify it works +5. Optionally call copilot_deploy to make it externally accessible`, inputSchema: { type: 'object', properties: { @@ -205,13 +268,11 @@ DO NOT USE (use direct tools instead): { name: 'copilot_plan', agentId: 'plan', - description: `Plan workflow changes by gathering required information. + description: `Plan workflow changes by gathering required information. For most cases, prefer copilot_build which combines planning and editing in one step. USE THIS WHEN: -- Building a new workflow -- Modifying an existing workflow -- You need to understand what blocks and integrations are available -- The workflow requires multiple blocks or connections +- You need fine-grained control over the build process +- You want to inspect the plan before executing it WORKFLOW ID (REQUIRED): - For NEW workflows: First call create_workflow to get a workflowId, then pass it here @@ -241,23 +302,16 @@ IMPORTANT: Pass the returned plan EXACTLY to copilot_edit - do not modify or sum { name: 'copilot_edit', agentId: 'edit', - description: `Execute a workflow plan and apply edits. - -USE THIS WHEN: -- You have a plan from copilot_plan that needs to be executed -- Building or modifying a workflow based on the plan -- Making changes to blocks, connections, or configurations + description: `Execute a workflow plan from copilot_plan. For most cases, prefer copilot_build which combines planning and editing in one step. WORKFLOW ID (REQUIRED): - You MUST provide the workflowId parameter -- For new workflows, get the workflowId from create_workflow first PLAN (REQUIRED): - Pass the EXACT plan object from copilot_plan in the context.plan field - Do NOT modify, summarize, or interpret the plan - pass it verbatim -- The plan contains technical details the edit agent needs exactly as-is -IMPORTANT: After copilot_edit completes, you MUST call copilot_deploy before the workflow can be run or tested.`, +After copilot_edit completes, you can test immediately with copilot_test, or deploy with copilot_deploy to make it accessible externally.`, inputSchema: { type: 'object', properties: { @@ -281,43 +335,15 @@ IMPORTANT: After copilot_edit completes, you MUST call copilot_deploy before the required: ['workflowId'], }, }, - { - name: 'copilot_debug', - agentId: 'debug', - description: `Diagnose errors or unexpected workflow behavior. - -WORKFLOW ID (REQUIRED): Always provide the workflowId of the workflow to debug.`, - inputSchema: { - type: 'object', - properties: { - error: { type: 'string', description: 'The error message or description of the issue.' }, - workflowId: { type: 'string', description: 'REQUIRED. The workflow ID to debug.' }, - context: { type: 'object' }, - }, - required: ['error', 'workflowId'], - }, - }, { name: 'copilot_deploy', agentId: 'deploy', - description: `Deploy or manage workflow deployments. - -CRITICAL: You MUST deploy a workflow after building before it can be run or tested. -Workflows without an active deployment will fail with "no active deployment" error. - -WORKFLOW ID (REQUIRED): -- Always provide the workflowId parameter -- This must match the workflow you built with copilot_edit - -USE THIS: -- After copilot_edit completes to activate the workflow -- To update deployment settings -- To redeploy after making changes + description: `Deploy a workflow to make it accessible externally. Workflows can be tested without deploying, but deployment is needed for API access, chat UIs, or MCP exposure. DEPLOYMENT TYPES: -- "deploy as api" - REST API endpoint -- "deploy as chat" - Chat interface -- "deploy as mcp" - MCP server`, +- "deploy as api" - REST API endpoint for programmatic access +- "deploy as chat" - Managed chat UI with auth options +- "deploy as mcp" - Expose as MCP tool for AI agents`, inputSchema: { type: 'object', properties: { @@ -334,114 +360,10 @@ DEPLOYMENT TYPES: required: ['request', 'workflowId'], }, }, - { - name: 'copilot_auth', - agentId: 'auth', - description: 'Handle OAuth connection flows.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_knowledge', - agentId: 'knowledge', - description: 'Create and manage knowledge bases.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_custom_tool', - agentId: 'custom_tool', - description: 'Create or manage custom tools.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_info', - agentId: 'info', - description: 'Inspect blocks, outputs, and workflow metadata.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - workflowId: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_workflow', - agentId: 'workflow', - description: 'Manage workflow environment and configuration.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - workflowId: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_research', - agentId: 'research', - description: 'Research external APIs and documentation.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, - { - name: 'copilot_tour', - agentId: 'tour', - description: 'Explain platform features and usage.', - inputSchema: { - type: 'object', - properties: { - request: { type: 'string' }, - context: { type: 'object' }, - }, - required: ['request'], - }, - }, { name: 'copilot_test', agentId: 'test', - description: `Run workflows and verify outputs. - -PREREQUISITE: The workflow MUST be deployed first using copilot_deploy. -Undeployed workflows will fail with "no active deployment" error. - -WORKFLOW ID (REQUIRED): -- Always provide the workflowId parameter - -USE THIS: -- After deploying to verify the workflow works correctly -- To test with sample inputs -- To validate workflow behavior before sharing with user`, + description: `Run a workflow and verify its outputs. Works on both deployed and undeployed (draft) workflows. Use after building to verify correctness.`, inputSchema: { type: 'object', properties: { @@ -455,10 +377,126 @@ USE THIS: required: ['request', 'workflowId'], }, }, + { + name: 'copilot_debug', + agentId: 'debug', + description: + 'Diagnose errors or unexpected workflow behavior. Provide the error message and workflowId. Returns root cause analysis and fix suggestions.', + inputSchema: { + type: 'object', + properties: { + error: { type: 'string', description: 'The error message or description of the issue.' }, + workflowId: { type: 'string', description: 'REQUIRED. The workflow ID to debug.' }, + context: { type: 'object' }, + }, + required: ['error', 'workflowId'], + }, + }, + { + name: 'copilot_auth', + agentId: 'auth', + description: + 'Check OAuth connection status, list connected services, and initiate new OAuth connections. Use when a workflow needs third-party service access (Google, Slack, GitHub, etc.).', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_knowledge', + agentId: 'knowledge', + description: + 'Manage knowledge bases for RAG-powered document retrieval. Supports listing, creating, updating, and deleting knowledge bases. Knowledge bases can be attached to agent blocks for context-aware responses.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_custom_tool', + agentId: 'custom_tool', + description: + 'Manage custom tools (reusable API integrations). Supports listing, creating, updating, and deleting custom tools. Custom tools can be added to agent blocks as callable functions.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_info', + agentId: 'info', + description: + 'Inspect a workflow\'s blocks, connections, outputs, variables, and metadata. Always provide workflowId to scope results to a specific workflow.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + workflowId: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_workflow', + agentId: 'workflow', + description: + 'Manage workflow-level configuration: environment variables, settings, scheduling, and deployment status.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + workflowId: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_research', + agentId: 'research', + description: + 'Research external APIs and documentation. Use when building workflows that integrate with third-party services and you need to understand their API, authentication, or data formats.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, + { + name: 'copilot_tour', + agentId: 'tour', + description: + 'Explain platform features, concepts, and usage patterns. Use when the user asks "how does X work?" about the Sim platform, block types, triggers, deployments, or workflow concepts.', + inputSchema: { + type: 'object', + properties: { + request: { type: 'string' }, + context: { type: 'object' }, + }, + required: ['request'], + }, + }, { name: 'copilot_superagent', agentId: 'superagent', - description: 'Execute direct external actions (email, Slack, etc.).', + description: + 'Execute direct actions NOW: send an email, post to Slack, make an API call, etc. Use when the user wants to DO something immediately rather than build a workflow for it.', inputSchema: { type: 'object', properties: {