A powerful and flexible workflow engine built with Node.js, Express, and LangGraph that dynamically executes arithmetic operations based on JSON configuration.
- Dynamic Workflow Creation: Define workflows using simple JSON configuration
- Multiple Operations: Support for Add, Subtract, Multiply, and Divide
- Node Referencing: Reference previous node results using
$nodeIdsyntax - Multiple Operands: Each operation can handle 2 or more values
- Flexible Variable Names: Use any property names in your data objects
- RESTful API: Easy-to-use HTTP endpoints
- Error Handling: Comprehensive error handling and validation
- Execution Logging: Track each step of the workflow execution
- Node.js (v16 or higher)
- npm or yarn
- Clone or create the project directory:
mkdir dynamic-math-workflow
cd dynamic-math-workflow- Initialize the project and install dependencies:
npm init -y
npm install express @langchain/langgraph dotenv cors helmet morgan
npm install -D nodemon- Create the project structure:
mkdir -p src/workflow src/routes src/middleware- Create the following files with the provided code:
dynamic-math-workflow/
├── src/
│ ├── server.js # Main Express server
│ ├── workflow/
│ │ ├── workflowEngine.js # LangGraph workflow logic
│ │ └── operations.js # Math operations
│ ├── routes/
│ │ └── workflowRoutes.js # API routes
│ └── middleware/
│ └── errorHandler.js # Error handling
├── package.json
├── .env
└── README.md
- Create
.envfile:
PORT=3000
NODE_ENV=development- Update
package.jsonscripts:
{
"type": "module",
"scripts": {
"dev": "nodemon src/server.js",
"start": "node src/server.js"
}
}Development mode (with auto-reload):
npm run devProduction mode:
npm startThe server will start on http://localhost:3000
GET /api/workflow/health
Check if the server is running.
curl http://localhost:3000/api/workflow/healthResponse:
{
"success": true,
"message": "Workflow engine is running",
"timestamp": "2024-01-15T10:30:00.000Z"
}GET /api/workflow/examples
Get pre-defined example workflows.
curl http://localhost:3000/api/workflow/examplesPOST /api/workflow/execute
Execute a custom workflow.
Request Body:
{
"name": "Workflow Name",
"description": "Optional description",
"nodes": [
{
"id": "unique_node_id",
"type": "add|subtract|multiply|divide",
"data": {
"variableName1": value,
"variableName2": "$referenceNodeId"
}
}
],
"edges": [
{
"source": "START",
"target": "node_id"
}
]
}Response:
{
"success": true,
"finalResult": 27,
"results": {
"node1": 15,
"node2": 30,
"node3": 27
},
"executionLog": [
"node1: 10 + 5 = 15",
"node2: 15 × 2 = 30",
"node3: 30 - 3 = 27",
"Final Result: 27"
]
}curl -X POST http://localhost:3000/api/workflow/execute \
-H "Content-Type: application/json" \
-d '{
"name": "Simple Addition",
"description": "10 + 5 = 15",
"nodes": [
{
"id": "add_node",
"type": "add",
"data": { "a": 10, "b": 5 }
}
],
"edges": [
{ "source": "START", "target": "add_node" },
{ "source": "add_node", "target": "END" }
]
}'curl -X POST http://localhost:3000/api/workflow/execute \
-H "Content-Type: application/json" \
-d '{
"name": "Chained Operations",
"description": "(10 + 5) * 2 - 3 = 27",
"nodes": [
{
"id": "add_node",
"type": "add",
"data": { "a": 10, "b": 5 }
},
{
"id": "multiply_node",
"type": "multiply",
"data": { "value": "$add_node", "multiplier": 2 }
},
{
"id": "subtract_node",
"type": "subtract",
"data": { "minuend": "$multiply_node", "subtrahend": 3 }
}
],
"edges": [
{ "source": "START", "target": "add_node" },
{ "source": "add_node", "target": "multiply_node" },
{ "source": "multiply_node", "target": "subtract_node" },
{ "source": "subtract_node", "target": "END" }
]
}'curl -X POST http://localhost:3000/api/workflow/execute \
-H "Content-Type: application/json" \
-d '{
"name": "Multiple Multiplication",
"description": "2 * 3 * 4 * 5 = 120",
"nodes": [
{
"id": "multiply_all",
"type": "multiply",
"data": { "val1": 2, "val2": 3, "val3": 4, "val4": 5 }
}
],
"edges": [
{ "source": "START", "target": "multiply_all" },
{ "source": "multiply_all", "target": "END" }
]
}'curl -X POST http://localhost:3000/api/workflow/execute \
-H "Content-Type: application/json" \
-d '{
"name": "Complex Calculation",
"description": "((100 - 20) / 4) + 10 = 30",
"nodes": [
{
"id": "sub_node",
"type": "subtract",
"data": { "x": 100, "y": 20 }
},
{
"id": "div_node",
"type": "divide",
"data": { "numerator": "$sub_node", "denominator": 4 }
},
{
"id": "add_node",
"type": "add",
"data": { "a": "$div_node", "b": 10 }
}
],
"edges": [
{ "source": "START", "target": "sub_node" },
{ "source": "sub_node", "target": "div_node" },
{ "source": "div_node", "target": "add_node" },
{ "source": "add_node", "target": "END" }
]
}'{
"id": "unique_identifier", // Unique node ID
"type": "add|subtract|multiply|divide", // Operation type
"data": {
"param1": 10, // Direct value
"param2": "$previous_node" // Reference to another node
}
}{
"source": "START|node_id", // Source node
"target": "node_id|END" // Target node
}| Operation | Type | Example | Result |
|---|---|---|---|
| Addition | add |
10 + 5 + 3 |
18 |
| Subtraction | subtract |
20 - 5 - 2 |
13 |
| Multiplication | multiply |
2 * 3 * 4 |
24 |
| Division | divide |
100 / 5 / 2 |
10 |
Use the $ prefix to reference results from previous nodes:
{
"data": {
"value": "$add_node", // Gets result from add_node
"multiplier": 2
}
}You can use any property names in your data objects:
{
"data": {
"firstNumber": 10,
"secondNumber": 5
}
}or
{
"data": {
"x": 10,
"y": 5
}
}Operations support 2 or more values:
{
"data": {
"val1": 2,
"val2": 3,
"val3": 4,
"val4": 5
}
}Reference previous node results to create complex workflows:
{
"nodes": [
{ "id": "step1", "type": "add", "data": { "a": 10, "b": 5 } },
{
"id": "step2",
"type": "multiply",
"data": { "value": "$step1", "by": 2 }
}
]
}The API provides comprehensive error handling:
{
"success": false,
"error": "Invalid workflow configuration: nodes array is required"
}{
"success": false,
"error": "Division by zero"
}{
"success": false,
"error": "Referenced node \"unknown_node\" not found or not executed yet"
}# Test health endpoint
curl http://localhost:3000/api/workflow/health
# Execute a workflow
curl -X POST http://localhost:3000/api/workflow/execute \
-H "Content-Type: application/json" \
-d @workflow.json- Import the collection
- Set the base URL to
http://localhost:3000 - Use the POST
/api/workflow/executeendpoint - Add your JSON workflow in the body
fetch("http://localhost:3000/api/workflow/execute", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Test Workflow",
nodes: [{ id: "add", type: "add", data: { a: 10, b: 5 } }],
edges: [
{ source: "START", target: "add" },
{ source: "add", target: "END" },
],
}),
})
.then((res) => res.json())
.then((data) => console.log(data));All successful workflow executions return:
{
"success": true,
"finalResult": 27,
"results": {
"node1": 15,
"node2": 30,
"node3": 27
},
"executionLog": [
"node1: 10 + 5 = 15",
"node2: 15 × 2 = 30",
"node3: 30 - 3 = 27",
"Final Result: 27"
]
}The application includes:
- Helmet.js for security headers
- CORS enabled
- Input validation
- Error message sanitization
# Install Heroku CLI
# Login to Heroku
heroku login
# Create app
heroku create your-app-name
# Push code
git push heroku main
# Open app
heroku open- Push code to GitHub
- Connect Railway to your repository
- Deploy automatically
- Connect your GitHub repository
- Set build command:
npm install - Set start command:
npm start
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.
Created with ❤️ using Node.js, Express, and LangGraph
For issues, questions, or suggestions, please open an issue on GitHub.
Happy Computing! 🎉