Skip to content

UseFlowCanvas/flowcanvas-engine

Repository files navigation

useflowcanvas

enter image description here

FlowCanvas SDK — Build and execute AI-powered visual workflows programmatically.

Design directed acyclic graphs (DAGs) of nodes, wire them together, and run them. Supports OpenAI-powered AI nodes, HTTP requests, conditional branching, data transforms, and more.


Quick Start

import  "dotenv/config";

import  { FlowCanvas }  from  "useflowcanvas";

  

const  canvas = new  FlowCanvas("My First Workflow", {

openaiApiKey: process.env.OPENAI_API_KEY,

});

  

const  input = canvas.addInput("Input");

const  ai = canvas.addAI("Summarize", {

systemPrompt:  "You are a concise assistant.",

userPrompt:  "Summarize: {{text}}",

responseField:  "summary",

});

const  output = canvas.addOutput("Output");

  

canvas.pipe(input, ai).pipe(ai, output);

  

const  result = await  canvas.run({ text:  "Long article text goes here..."  });

console.log(result.outputs.summary);

Environment Variables

Copy .env.example to .env and fill in your values:


OPENAI_API_KEY=sk-...

OPENAI_DEFAULT_MODEL=gpt-4o-mini # optional


Node Types

| Node | Class | Purpose |

|------|-------|---------|

| input | InputNode | Entry point — passes initial data into the workflow |

| output | OutputNode | Terminal node — collects final results |

| ai | AINode | Calls OpenAI chat completions |

| transform | TransformNode | Maps, templates, or evaluates expressions |

| condition | ConditionNode | Evaluates a boolean expression and routes branches |

| http | HTTPNode | Makes HTTP requests to external APIs |

| delay | DelayNode | Pauses execution for a given duration |

| merge | MergeNode | Merges outputs from multiple upstream nodes |


API Reference

new FlowCanvas(name, options?)

| Option | Type | Description |

|--------|------|-------------|

| openaiApiKey | string | OpenAI API key (falls back to OPENAI_API_KEY env var) |

| openaiBaseUrl | string | Custom OpenAI-compatible base URL |

| defaultModel | string | Default chat model (e.g. "gpt-4o") |

| maxConcurrency | number | Max parallel node executions (reserved) |

| timeout | number | Execution timeout in ms (reserved) |

| onNodeStart | (nodeId, nodeType) => void | Fires before a node runs |

| onNodeComplete | (result) => void | Fires after a node succeeds |

| onNodeError | (nodeId, error) => void | Fires when a node throws |

Adding Nodes

canvas.addInput(label?)

canvas.addOutput(label?, fields?)

canvas.addAI(label?, config?)

canvas.addTransform(label?, config?)

canvas.addCondition(label?, config?)

canvas.addHTTP(label?, config?)

canvas.addDelay(label?, config?)

canvas.addMerge(label?)

Connecting Nodes

// Fluent chaining

canvas.pipe(nodeA, nodeB).pipe(nodeB, nodeC);

  

// With a conditional edge

canvas.connect(condNode.id, branchNode.id, {

label:  "true",

condition: (data) => data._conditionResult ===  true,

});

Running a Workflow

const  result = await  canvas.run(inputs, globals?);

WorkflowResult:

{

workflowId: string;

status: "success"  |  "error"  |  "partial";

results: ExecutionResult[]; // per-node results

outputs: NodeData; // merged outputs from terminal nodes

durationMs: number;

startedAt: Date;

finishedAt: Date;

}

Node Configs

AI Node

canvas.addAI("My AI Step", {

model:  "gpt-4o", // overrides defaultModel

systemPrompt:  "You are helpful.",

userPrompt:  "Analyze {{text}}", // {{variable}} interpolation

temperature:  0.7,

maxTokens:  500,

responseField:  "analysis", // key in output data (default: "result")

});

Transform Node

// Template interpolation

canvas.addTransform("Greeting", {

template:  "Hello, {{name}}! You scored {{score}}.",

});

  

// Key mapping with JS expressions

canvas.addTransform("Remap", {

mapping: {

fullName:  "firstName + ' ' + lastName",

scorePercent:  "score / 100",

},

});

  

// Arbitrary expression

canvas.addTransform("Compute", {

expression:  "score * 2 + bonus",

});

Condition Node

const  cond = canvas.addCondition("Is Premium?", {

condition:  "plan === 'premium' && score >= 80",

});

  

// Connect both branches explicitly

canvas.connect(cond.id, premiumNode.id, {

label:  "true",

condition: (d) => d._conditionResult ===  true,

});

canvas.connect(cond.id, freeNode.id, {

label:  "false",

condition: (d) => d._conditionResult ===  false,

});

Output includes _conditionResult: boolean and _branch: string.

HTTP Node

canvas.addHTTP("Fetch User", {

url:  "https://api.example.com/users/{{userId}}",

method:  "GET",

headers: { Authorization:  "Bearer {{token}}" },

responseField:  "user",

});

Delay Node

canvas.addDelay("Wait 2s", { delayMs:  2000  });

Template Interpolation

Any node config that accepts a string supports {{variable}} syntax. Variables are resolved from the merged output of all upstream nodes plus any globals passed to run().

canvas.addAI("Personalize", {

userPrompt:  "Write a message for {{name}} who likes {{hobby}}.",

});

  

await  canvas.run({ name:  "Alice", hobby:  "photography"  });

Serialization

Workflows can be serialized to JSON and restored:

// Save

const  json = canvas.toJSON();

await  fs.writeFile("workflow.json", JSON.stringify(json));

  

// Restore

const  data = JSON.parse(await  fs.readFile("workflow.json", "utf8"));

const  restored = FlowCanvas.fromJSON(data, { openaiApiKey: process.env.OPENAI_API_KEY  });

const  result = await  restored.run({ text:  "..."  });

Extending with Custom Nodes

import  { BaseNode }  from  "useflowcanvas";

  

class  UpperCaseNode  extends  BaseNode {

constructor(id, label = "UpperCase") {

super(id, "transform", label, {});

}

  

async  execute(context) {

const { text } = context.inputs;

return { ...context.inputs, text: text?.toUpperCase() ??  "" };

}

}

  

const  node = new  UpperCaseNode("upper_1");

canvas.addNode(node);

canvas.pipe(inputNode, node).pipe(node, outputNode);

Examples

| File | Description |

|------|-------------|

| examples/basic-workflow.js | Linear transform pipeline, no AI required |

| examples/ai-workflow.js | Multi-step summarize + translate pipeline |

| examples/conditional-workflow.js | Branching based on score threshold |

| examples/serialization.js | Save and restore workflows from JSON |


node examples/basic-workflow.js

node examples/ai-workflow.js # requires OPENAI_API_KEY

node examples/conditional-workflow.js

node examples/serialization.js


License

MIT

About

Build AI-powered visual workflows with nodes, DAG execution, OpenAI integration, branching logic, HTTP requests, and custom automation pipelines.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors