Clean up mcp

This commit is contained in:
Siddharth Ganesan
2026-02-05 20:26:47 -08:00
parent 05ee6da190
commit e02fe94186
6 changed files with 344 additions and 304 deletions

View File

@@ -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: \`<blockname.field>\`
Reference environment variables: \`{{ENV_VAR_NAME}}\`
Rules:
- Block names must be lowercase, no spaces, no special characters
- Use dot notation for nested fields: \`<blockname.field.subfield>\`
---
## 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": <plan_object> } }\`
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": <EXACT plan object from step 1> }
})
\`\`\`
**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: \`<blockname.field>\` 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<string, unknown>) || {}
const requestPayload = {
message: requestText,
@@ -391,7 +286,6 @@ async function handleBuildToolCall(
version: SIM_AGENT_VERSION,
headless: true,
chatId,
context,
}
const result = await orchestrateCopilotStream(requestPayload, {

View File

@@ -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) =>

View File

@@ -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
}

View File

@@ -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<ToolCallResult> {
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<ToolCallResult> {
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<ToolCallResult> {
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) }
}
}

View File

@@ -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) }
}

View File

@@ -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: {