Agent skill
new-node
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 this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/new-node-narcis13-workscript
SKILL.md
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:
- Node purpose - What should this node do?
- Node category - Core, data manipulation, server, or custom integration?
- Inputs - What configuration parameters does it need?
- Outputs - What data should it return via edges?
- Edge types - What routing outcomes are possible? (success/error, found/not_found, true/false, etc.)
- 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/:
- standard-node.ts - Basic success/error pattern
- boolean-node.ts - True/false branching
- lookup-node.ts - Found/not_found pattern
- multi-outcome-node.ts - Multiple routing outcomes
- external-api-node.ts - HTTP/API calls
- database-node.ts - Database operations
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:
- Read the existing node to understand current behavior
- Identify issues - Check for multiple edge returns, missing validation, unclear naming
- Apply fixes following the single-edge pattern
- Update tests to verify single-edge return
- 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
- Single Responsibility - One node, one purpose
- Early Validation - Return error edge immediately for invalid inputs
- Clear Naming - Use semantic edge names (not "ok" or "done")
- State Namespacing - Use prefixed keys like
myNodeResult - Meaningful Errors - Include nodeId, operation, and suggestion in errors
- No Instance State - Keep nodes stateless, use context.state
- Complete ai_hints - Help AI workflows generate correct usage
Reference
For comprehensive documentation, see:
- reference.md - Quick reference and patterns
- examples.md - Complete node examples
- NODE_DEVELOPMENT_BLUEPRINT.md - Full blueprint
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"
}
}
]
}
Didn't find tool you were looking for?