Loading...
Loading...
Workflow Orchestration provides a visual AI flow-building framework with MCP plugin support, conditional branching, parallel execution, and error recovery.
npx skill4agent add itallstartedwithaidea/agent-skills workflow-orchestrationgraph TD
A[Trigger: Manual / Schedule / Webhook] --> B[Node 1: Input Parser]
B --> C{Conditional Router}
C -->|Type A| D[Node 2a: LLM Analysis]
C -->|Type B| E[Node 2b: Database Query via MCP]
D --> F[Node 3: Parallel Execution]
E --> F
F --> G[Node 3a: Image Generation]
F --> H[Node 3b: Content Formatting]
G --> I[Node 4: Human Review Checkpoint]
H --> I
I -->|Approved| J[Node 5: Publish via MCP]
I -->|Rejected| K[Node 5: Return to Step 2]
J --> L[Node 6: Log + Notify]interface WorkflowNode {
id: string;
type: "llm" | "mcp" | "transform" | "condition" | "human_review" | "parallel";
config: Record<string, unknown>;
next: string | string[] | ConditionalNext[];
retries?: number;
timeout_ms?: number;
}
interface ConditionalNext {
condition: string;
target: string;
}
interface Workflow {
id: string;
name: string;
trigger: { type: "manual" | "schedule" | "webhook"; config: Record<string, unknown> };
nodes: WorkflowNode[];
}
class WorkflowEngine {
private state = new Map<string, unknown>();
async execute(workflow: Workflow, input: unknown): Promise<unknown> {
this.state.set("input", input);
let currentNode = workflow.nodes[0];
while (currentNode) {
const result = await this.executeNode(currentNode);
this.state.set(currentNode.id, result);
const nextId = this.resolveNext(currentNode, result);
currentNode = nextId ? workflow.nodes.find(n => n.id === nextId)! : undefined!;
}
return Object.fromEntries(this.state);
}
private async executeNode(node: WorkflowNode): Promise<unknown> {
for (let attempt = 0; attempt <= (node.retries ?? 0); attempt++) {
try {
switch (node.type) {
case "llm": return await this.executeLLM(node.config);
case "mcp": return await this.executeMCP(node.config);
case "transform": return this.executeTransform(node.config);
case "parallel": return await this.executeParallel(node.config);
case "human_review": return await this.waitForHumanReview(node.config);
default: throw new Error(`Unknown node type: ${node.type}`);
}
} catch (error) {
if (attempt === (node.retries ?? 0)) throw error;
await this.delay(1000 * Math.pow(2, attempt));
}
}
}
private async executeMCP(config: Record<string, unknown>): Promise<unknown> {
const { server, tool, arguments: args } = config as {
server: string; tool: string; arguments: Record<string, unknown>;
};
return callMcpTool(server, tool, this.interpolate(args));
}
private async executeParallel(config: Record<string, unknown>): Promise<unknown[]> {
const { nodeIds } = config as { nodeIds: string[] };
const nodes = nodeIds.map(id => this.findNode(id));
return Promise.all(nodes.map(n => this.executeNode(n)));
}
private interpolate(obj: Record<string, unknown>): Record<string, unknown> {
return JSON.parse(
JSON.stringify(obj).replace(/\{\{(\w+)\.(\w+)\}\}/g, (_, nodeId, key) => {
const nodeResult = this.state.get(nodeId) as Record<string, unknown>;
return String(nodeResult?.[key] ?? "");
})
);
}
}| Platform | Support | Notes |
|---|---|---|
| Cursor | Full | MCP integration + workflow design |
| VS Code | Full | Extension-based workflow |
| Windsurf | Full | Flow builder support |
| Claude Code | Full | Workflow code generation |
| Cline | Full | Pipeline orchestration |
| aider | Partial | Code-level workflow support |
workfloworchestrationmcpdagparallel-executionconditional-routinghuman-in-the-loopautomation