Claude Code Plugins

Community-maintained marketplace

Feedback

Create new workflow nodes for the Workscript engine or refactor existing nodes. Generate complete, production-ready node implementations following the single-edge return pattern. Use when creating new nodes, developing custom integrations, building data manipulation nodes, refactoring existing nodes, or implementing workflow capabilities.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name new-node
description Create new workflow nodes for the Workscript engine or refactor existing nodes. Generate complete, production-ready node implementations following the single-edge return pattern. Use when creating new nodes, developing custom integrations, building data manipulation nodes, refactoring existing nodes, or implementing workflow capabilities.

Workscript Node Development Skill

Overview

This skill helps you create and refactor workflow nodes for the Workscript Agentic Workflow Engine. All nodes follow a consistent pattern with the critical single-edge return rule: every node execution MUST return an EdgeMap with exactly ONE key.

Instructions

When creating or refactoring a node, follow these steps:

Step 1: Gather Requirements

Ask clarifying questions to understand:

  1. Node purpose - What should this node do?
  2. Node category - Core, data manipulation, server, or custom integration?
  3. Inputs - What configuration parameters does it need?
  4. Outputs - What data should it return via edges?
  5. Edge types - What routing outcomes are possible? (success/error, found/not_found, true/false, etc.)
  6. State mutations - What state keys should it write?

Step 2: Determine File Location

Based on category, place the node file in:

  • Core nodes/packages/nodes/src/MyNode.ts
  • Data manipulation/packages/nodes/src/data/MyNode.ts
  • Custom integrations/packages/nodes/src/custom/[provider]/MyNode.ts

Step 3: Create the Node File

Use the appropriate template from templates/:

Step 4: Implement the Node Structure

Every node MUST have:

import { WorkflowNode } from '@workscript/engine';
import type { ExecutionContext, EdgeMap } from '@workscript/engine';

export class MyNode extends WorkflowNode {
  // 1. Complete metadata with ai_hints
  metadata = {
    id: 'myNode',           // Unique identifier (camelCase or kebab-case)
    name: 'My Node',        // Human-readable name
    version: '1.0.0',       // Semantic version
    description: 'What this node does',
    inputs: ['param1', 'param2'],
    outputs: ['result'],
    ai_hints: {
      purpose: 'Brief purpose statement',
      when_to_use: 'When to use this node',
      expected_edges: ['success', 'error'],
      example_usage: '{"my-node": {"param1": "value", "success?": "next"}}',
      example_config: '{"param1": "string", "param2?": "number"}',
      get_from_state: [],
      post_to_state: ['myNodeResult']
    }
  };

  // 2. Execute method with single-edge return
  async execute(context: ExecutionContext, config?: any): Promise<EdgeMap> {
    // Implementation following the pattern
  }
}

export default MyNode;

Step 5: Follow the Single-Edge Return Pattern

CRITICAL: The execute method must ALWAYS return exactly ONE edge key:

async execute(context: ExecutionContext, config?: any): Promise<EdgeMap> {
  const { param } = config || {};

  // VALIDATION - Return error edge immediately
  if (!param) {
    return {
      error: () => ({ error: 'Missing required parameter: param' })
    };
  }

  // BUSINESS LOGIC in try-catch
  try {
    const result = await this.operation(param);
    context.state.myNodeResult = result;

    // Return SINGLE success edge
    return {
      success: () => ({ result })
    };

  } catch (error) {
    // Return SINGLE error edge from catch
    return {
      error: () => ({
        error: error instanceof Error ? error.message : 'Operation failed',
        nodeId: context.nodeId
      })
    };
  }
}

Step 6: Export the Node

Add exports to /packages/nodes/src/index.ts:

// Add import
import MyNewNode from './MyNewNode';

// Add to ALL_NODES array
export const ALL_NODES = [
  // ... existing nodes
  MyNewNode,
];

// Add individual export
export { MyNewNode };

Step 7: Create Tests

Create a test file alongside the implementation:

import { describe, it, expect, beforeEach } from 'vitest';
import { MyNode } from './MyNode';
import type { ExecutionContext } from '@workscript/engine';

describe('MyNode', () => {
  let node: MyNode;
  let context: ExecutionContext;

  beforeEach(() => {
    node = new MyNode();
    context = {
      state: {},
      inputs: {},
      workflowId: 'test-workflow',
      nodeId: 'test-node',
      executionId: 'test-execution-123'
    };
  });

  // CRITICAL: Always test single-edge return
  it('should return only one edge key', async () => {
    const result = await node.execute(context, { param: 'value' });
    expect(Object.keys(result)).toHaveLength(1);
  });
});

Step 8: Build and Verify

bun run build:nodes
bun run test:nodes

Refactoring Existing Nodes

When refactoring:

  1. Read the existing node to understand current behavior
  2. Identify issues - Check for multiple edge returns, missing validation, unclear naming
  3. Apply fixes following the single-edge pattern
  4. Update tests to verify single-edge return
  5. Update exports if node ID changes

Common Edge Patterns

Pattern Edge Names Use Case
Success/Error success, error Basic operations
Boolean true, false, error Conditional logic
Lookup found, not_found, error Search operations
Exists exists, not_exists, error File/record checks
Multi-value high, medium, low, error Categorization
Empty/Results success, empty, error List operations

Best Practices

  1. Single Responsibility - One node, one purpose
  2. Early Validation - Return error edge immediately for invalid inputs
  3. Clear Naming - Use semantic edge names (not "ok" or "done")
  4. State Namespacing - Use prefixed keys like myNodeResult
  5. Meaningful Errors - Include nodeId, operation, and suggestion in errors
  6. No Instance State - Keep nodes stateless, use context.state
  7. Complete ai_hints - Help AI workflows generate correct usage

Reference

For comprehensive documentation, see:

Workflow JSON Usage

After creating a node, use it in workflows:

{
  "id": "my-workflow",
  "name": "My Workflow",
  "version": "1.0.0",
  "initialState": {},
  "workflow": [
    {
      "my-node-1": {
        "param1": "value",
        "param2": 42,
        "success?": "next-node",
        "error?": "error-handler"
      }
    }
  ]
}