execute_workflow
Run automated workflows by ID with custom variables to streamline tasks like daily planning, code review, and project management.
Instructions
Execute a workflow by ID with optional variables
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| workflowId | Yes | The ID of the workflow to execute | |
| variables | No | Variables to pass to the workflow |
Implementation Reference
- src/workflows/workflows.ts:141-223 (registration)MCP server tool registration for 'execute_workflow', including input schema, description, and the complete inline handler function that retrieves the workflow from the registry and executes it via the WorkflowEngine.server.tool( "execute_workflow", "Execute a workflow by ID with optional variables", { workflowId: z.string().describe("The ID of the workflow to execute"), variables: z.record(z.any()).optional().describe("Variables to pass to the workflow"), }, async (args) => { try { const workflow = registry.getWorkflow(args.workflowId); if (!workflow) { return { content: [ { type: "text", text: `Workflow not found: ${args.workflowId}`, }, ], isError: true, }; } const result = await registry.workflowEngine.execute(workflow, args.variables); if (result.success) { // Format the results for display const stepsSummary = Array.from(result.results.entries()).map(([stepId, stepResult]) => ({ stepId, success: stepResult.success, error: stepResult.error, })); return { content: [ { type: "text", text: JSON.stringify( { workflow: workflow.name, success: true, duration: result.duration, variables: result.variables, steps: stepsSummary, }, null, 2 ), }, ], }; } else { return { content: [ { type: "text", text: JSON.stringify( { workflow: workflow.name, success: false, error: result.error, duration: result.duration, }, null, 2 ), }, ], isError: true, }; } } catch (error) { return { content: [ { type: "text", text: `Error executing workflow: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } );
- src/core/workflow-engine.ts:229-347 (handler)Core handler for executing workflows, called by the tool's inline handler. Implements full workflow execution including step-by-step processing, conditional execution, error handling with retries, and support for different step types (tool, skill, prompt, condition, loop). Note: excerpt abbreviated for brevity; full method spans lines 229-347.async execute( workflow: Workflow, initialVars?: Record<string, unknown> ): Promise<WorkflowResult> { const startTime = Date.now(); // Create execution context const context: WorkflowExecutionContext = { variables: { ...workflow.variables, ...initialVars }, results: new Map(), state: { currentStep: 0, startTime, completedSteps: [], failedSteps: [], }, }; try { // Execute each step for (let i = 0; i < workflow.steps.length; i++) { context.state.currentStep = i; const step = workflow.steps[i]; // Check run condition if present if (step.runCondition) { const shouldRun = Boolean(this.evaluator.evaluate(step.runCondition, context)); if (!shouldRun) { continue; // Skip this step } } try { const result = await this.executeStep(step, context); const stepResult: WorkflowStepResult = { stepId: step.id, success: true, result, retries: 0, duration: 0, }; context.results.set(step.id, stepResult); context.state.completedSteps.push(step.id); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); const stepResult: WorkflowStepResult = { stepId: step.id, success: false, error: errorMessage, retries: 0, duration: 0, }; context.results.set(step.id, stepResult); context.state.failedSteps.push(step.id); // Handle error based on onError setting if (step.onError === "continue") { continue; // Continue to next step } else if (step.onError === "retry" && step.retryCount) { // Retry logic let success = false; for (let r = 0; r < step.retryCount; r++) { try { const result = await this.executeStep(step, context); const retryResult: WorkflowStepResult = { stepId: step.id, success: true, result, retries: r + 1, duration: 0, }; context.results.set(step.id, retryResult); context.state.failedSteps = context.state.failedSteps.filter( (id) => id !== step.id ); success = true; break; } catch { // Continue retrying } } if (!success) { return { success: false, variables: context.variables, results: context.results, error: `Step '${step.id}' failed after ${step.retryCount} retries`, duration: Date.now() - startTime, }; } } else { // Default: stop on error return { success: false, variables: context.variables, results: context.results, error: `Step '${step.id}' failed: ${errorMessage}`, duration: Date.now() - startTime, }; } } } return { success: context.state.failedSteps.length === 0, variables: context.variables, results: context.results, duration: Date.now() - startTime, }; } catch (error) { return { success: false, variables: context.variables, results: context.results, error: error instanceof Error ? error.message : String(error), duration: Date.now() - startTime, }; } }
- src/core/registry.ts:42-47 (helper)Instantiation of the WorkflowEngine in the central Registry singleton, providing the executors needed for workflow execution (tool, skill, prompt, skills registry).this.workflowEngine = new WorkflowEngine( this.toolExecutor, this.skillExecutor, this, // Registry implements PromptExecutor this.skills // Pass skills registry );