What are Nodes and Edges?
Nodes and edges are the fundamental building blocks of all Flowise flows. Together, they form a visual graph that represents your AI workflow.
- Nodes: Individual components that perform specific functions (LLMs, vector stores, tools, etc.)
- Edges: Connections between nodes that define how data flows through your system
Flowise uses ReactFlow under the hood to provide the visual canvas interface for building with nodes and edges.
Nodes
What is a Node?
A node is a self-contained component that:
- Accepts inputs (data, configurations, credentials)
- Performs a specific operation
- Produces outputs for other nodes
Node Categories
Flowise includes 20+ node categories:
agentflow/ Multi-agent orchestration
agents/ Agent executors and tools
analytic/ Usage tracking and monitoring
cache/ Response caching
chains/ LangChain chains
chatmodels/ Chat-based LLMs
documentloaders/ File and data ingestion
embeddings/ Text embedding models
engine/ Query engines
graphs/ Graph databases
llms/ Language models
memory/ Conversation memory
moderation/ Content filtering
multiagents/ Multi-agent systems (V1)
outputparsers/ Response formatting
prompts/ Prompt templates
recordmanager/ Duplicate detection
responsesynthesizer/ Response generation
retrievers/ Document retrieval
sequentialagents/ Sequential workflows
Node Structure
Every node has the following structure:
{
id: string // Unique identifier (e.g., "chatOpenAI_0")
type: string // Node type for React Flow
position: { // Canvas position
x: number,
y: number
},
data: { // Node-specific data
id: string,
name: string, // Node type name (e.g., "chatOpenAI")
label: string, // Display name
version: number, // Node version
type: string, // Category
category: string, // Subcategory
description: string,
baseClasses: string[],
// Input configuration
inputAnchors: Anchor[],
inputParams: Parameter[],
// Output configuration
outputAnchors: Anchor[],
// State
selected: boolean,
tags: string[]
}
}
Input anchors define connections from other nodes:
{
id: string,
name: string,
label: string,
type: string, // Expected data type
optional: boolean,
list: boolean, // Accepts multiple connections
description: string
}
Example: Retrieval Chain Input Anchors
inputAnchors: [
{
name: "model",
label: "Language Model",
type: "BaseChatModel",
optional: false
},
{
name: "vectorStore",
label: "Vector Store",
type: "VectorStore",
optional: false
},
{
name: "memory",
label: "Chat Memory",
type: "BaseMemory",
optional: true
}
]
Input parameters are configurable values:
{
name: string,
label: string,
type: string, // "string" | "number" | "boolean" | "options" | etc.
default: any,
optional: boolean,
additionalParams: boolean, // Hidden in "Additional Parameters" section
description: string,
options: Array<{ // For dropdown fields
label: string,
name: string,
description: string
}>,
rows: number, // For text areas
placeholder: string
}
Example: OpenAI Node Parameters
inputParams: [
{
name: "modelName",
label: "Model Name",
type: "options",
options: [
{ label: "gpt-4", name: "gpt-4" },
{ label: "gpt-3.5-turbo", name: "gpt-3.5-turbo" }
],
default: "gpt-3.5-turbo"
},
{
name: "temperature",
label: "Temperature",
type: "number",
default: 0.7,
optional: true,
additionalParams: true
},
{
name: "maxTokens",
label: "Max Tokens",
type: "number",
optional: true,
additionalParams: true
}
]
Output Anchors
Output anchors define what a node produces:
{
id: string,
name: string,
label: string,
type: string, // Output data type
description: string
}
Example: ChatOpenAI Output
outputAnchors: [
{
name: "output",
label: "ChatOpenAI",
type: "ChatOpenAI | BaseChatModel | BaseLanguageModel",
description: "OpenAI chat model instance"
}
]
Node Versioning
Nodes have version numbers to track updates:
// Version check logic from source
const componentNode = canvas.componentNodes.find(
(nd) => nd.name === data.name
)
if (!data.version) {
// Warning: "Node outdated. Update to latest version X.X"
} else if (data.version && componentNode.version > data.version) {
// Warning: "Node version X outdated. Update to version Y"
}
Outdated nodes display a warning icon. Always update to the latest version for bug fixes and new features.
Node UI Components
The CanvasNode.jsx component renders:
- Header: Node icon, label, and action buttons
- Inputs Section: Input anchors and visible parameters
- Additional Parameters Button: For advanced configuration
- Output Section: Output anchors
// Node tooltip actions
<NodeTooltip>
<IconButton title="Duplicate" onClick={() => duplicateNode(data.id)} />
<IconButton title="Delete" onClick={() => deleteNode(data.id)} />
<IconButton title="Info" onClick={() => showNodeInfo()} />
</NodeTooltip>
Edges
What is an Edge?
An edge connects the output of one node to the input of another, enabling data flow.
Edge Structure
{
id: string, // Auto-generated unique ID
source: string, // Source node ID
target: string, // Target node ID
sourceHandle: string, // Specific output anchor ID
targetHandle: string, // Specific input anchor ID
type: string, // Edge type (usually "buttonedge")
data: { // Optional edge data
label: string
}
}
Example Edge:
{
"id": "chatOpenAI_0-conversationalRetrievalQAChain_0",
"source": "chatOpenAI_0",
"target": "conversationalRetrievalQAChain_0",
"sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI",
"targetHandle": "conversationalRetrievalQAChain_0-input-model-BaseChatModel",
"type": "buttonedge"
}
Edge Types
Flowise uses custom edge types:
The default edge with a delete button:
// From ButtonEdge.jsx
const ButtonEdge = ({ id, sourceX, sourceY, targetX, targetY }) => {
const [edgePath, edgeCenterX, edgeCenterY] = getBezierPath({
sourceX, sourceY, targetX, targetY
})
return (
<>
<path className="react-flow__edge-path" d={edgePath} />
<foreignObject
x={edgeCenterX - 20}
y={edgeCenterY - 20}
width={40}
height={40}
>
<button onClick={() => deleteEdge(id)}>
<IconX />
</button>
</foreignObject>
</>
)
}
Creating Edges
Edges are created by:
- Drag from output anchor to input anchor
- Type validation: Flowise checks if types are compatible
- Connection rules: Some inputs accept only one connection, others accept multiple
// Connection validation
if (inputAnchor.list === false && existingConnections.length > 0) {
// Remove existing connection before creating new one
deleteEdge(existingConnections[0].id)
}
Edge Labels
Edges can display labels for clarity:
<EdgeText
x={sourceX + 10}
y={sourceY + 10}
label={data.label}
labelStyle={{ fill: 'black' }}
labelBgStyle={{ fill: 'transparent' }}
/>
Type System
Flowise uses a type system to validate node connections:
Base Types
BaseLLM: Base language model
BaseChatModel: Chat-based language model
BaseLanguageModel: Any language model
VectorStore: Vector database
Embeddings: Embedding model
BaseRetriever: Document retriever
BaseMemory: Conversation memory
Tool: Agent tool
Document: Document object
Type Compatibility
Connections are valid if:
// Pseudo-code for type checking
if (
outputType === inputType ||
inputType.includes(outputType) ||
outputType.includes(inputType)
) {
// Connection allowed
}
Example:
// ✅ Valid: ChatOpenAI → BaseChatModel input
output: "ChatOpenAI | BaseChatModel"
input: "BaseChatModel"
// ❌ Invalid: ChatOpenAI → VectorStore input
output: "ChatOpenAI"
input: "VectorStore"
Flow Execution
Execution Order
Flowise determines execution order by analyzing the graph:
- Start nodes: Nodes with no incoming edges
- Dependency resolution: Execute nodes only after their inputs are ready
- Parallel execution: Independent nodes run concurrently
- Final nodes: Nodes with no outgoing edges
Execution order:
- Parallel: A, B, F, H (no dependencies)
- C (depends on A)
- D (depends on B and C)
- E (depends on D)
- G (depends on E, F, H) - final node
Data Flow
Data passes through edges as JavaScript objects:
// Simplified flow
const documentLoaderOutput = await documentLoader.load()
const splitterOutput = await textSplitter.split(documentLoaderOutput)
const vectorStore = await createVectorStore(embeddingsOutput, splitterOutput)
const retriever = vectorStore.asRetriever()
const response = await qaChain.invoke({
model: chatModelOutput,
retriever: retriever,
memory: memoryOutput,
question: userInput
})
Working with Nodes and Edges
Adding Nodes
// From the UI
1. Click "Add Nodes" button
2. Search or browse node categories
3. Click node to add to canvas
4. Configure node parameters
Connecting Nodes
// Drag connection
1. Click and hold on output anchor (right side)
2. Drag to target input anchor (left side)
3. Release to create edge
4. Click X button on edge to delete
Duplicating Nodes
// Preserves configuration, creates new ID
duplicateNode(nodeId) {
const node = nodes.find(n => n.id === nodeId)
const newNode = {
...node,
id: `${node.data.name}_${counter}`,
position: {
x: node.position.x + 50,
y: node.position.y + 50
}
}
addNode(newNode)
}
Deleting Nodes
// Also deletes connected edges
deleteNode(nodeId) {
// Remove node
nodes = nodes.filter(n => n.id !== nodeId)
// Remove connected edges
edges = edges.filter(e =>
e.source !== nodeId && e.target !== nodeId
)
}
Advanced Concepts
Conditional Nodes
Some nodes support conditional logic:
// IF-THEN node example
if (condition === "sentiment_positive") {
routeTo(positiveResponseNode)
} else {
routeTo(escalationNode)
}
Loop Nodes
Create iterative workflows:
// Retry logic
for (let attempt = 0; attempt < maxRetries; attempt++) {
result = await processNode.execute()
if (result.success) break
}
Custom Nodes
Developers can create custom nodes:
// Custom node template
class CustomNode implements INode {
label = 'My Custom Node'
name = 'customNode'
version = 1
type = 'CustomNode'
icon = 'custom.svg'
category = 'Custom'
inputs = [/* ... */]
outputs = [/* ... */]
async init(nodeData, input) {
// Node logic
return output
}
}
Best Practices
Node Organization
- Group related nodes together on the canvas
- Use consistent naming conventions
- Add descriptive labels to complex nodes
- Keep flows readable by avoiding edge crossings
- Minimize sequential dependencies
- Use caching nodes for repeated operations
- Choose appropriate models for each node
- Monitor node execution times
Maintainability
- Update nodes to latest versions regularly
- Document complex node configurations
- Use variables for repeated values
- Test flows after node updates
Troubleshooting
Connection Not Working
- Check type compatibility between output and input
- Verify node versions are current
- Ensure credentials are configured (for API nodes)
- Check for missing required parameters
Node Execution Errors
- Review node-specific error messages
- Verify input data format
- Check rate limits for API nodes
- Validate credentials and API keys
Edge Deleted Automatically
- Node type mismatch after update
- Input anchor changed in node version
- Validation rule prevents connection
Check browser console (F12) for detailed error messages when debugging node and edge issues.