Internode is a visual, node-based workflow editor designed to build agentic workflows for OpenWebUI. Inspired by ComfyUI, it uses a modular "sidecar" architecture allowing you to mix high-performance Node.js orchestration with powerful Python AI execution.
The project runs on Docker Compose and consists of three communicating services:
Frontend (python-flow-front) - Port 3000
Backend (node-flow-back) - Port 4200
/workflows), and manages the plugin registry. It proxies execution requests to the Python worker.AI Worker (python-flow-ai) - Internal Network
.py files for custom node definitions (ComfyUI-style) and executes them when triggered by the Backend.Ensure your project directory looks like this. If you are missing folders, create them:
/my-flow-app
āāā docker-compose.yml
āāā workflows/ <-- Saved flows appear here
āāā frontend/ <-- Svelte source code
āāā backend/ <-- Node.js source code
ā āāā plugins/ <-- Custom JS nodes
āāā python_backend/ <-- Python source code
āāā core/ <-- loader.py
āāā plugins/ <-- Custom Python (.py) nodes
āāā main.py
āāā requirements.txt
Open your terminal in the project root and run:
docker compose up --build
Uvicorn running on http://0.0.0.0:8000 (Frontend & Python Backend)Backend running on port 4000 (Node Backend)Open your browser to: š http://localhost:3000
| Key Combo | Action |
|---|---|
Ctrl + S |
Save current workflow |
Ctrl + O |
Open load dialog |
Ctrl + D |
Duplicate selected node |
Backspace / Del |
Delete selected node/edge |
Space |
Fit View to all nodes |
./workflows folder on your computer../workflows.Internode supports both JavaScript (Node.js) and Python nodes.
Drop any .py file into python_backend/plugins/. It follows the ComfyUI Node Standard.
Example: python_backend/plugins/my_math.py
class MyMathNode:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"a": ("INT", {"default": 10}),
"b": ("INT", {"default": 20})
}
}
RETURN_TYPES = ("INT",)
FUNCTION = "add"
CATEGORY = "Custom/Math"
def add(self, a, b):
return (a + b,)
NODE_CLASS_MAPPINGS = { "MyMathNode": MyMathNode }
Restart the container (docker compose restart python_backend) to load new nodes.
Create a folder in backend/plugins/ (e.g., backend/plugins/my_nodes/index.js).
Example: backend/plugins/my_nodes/index.js
export const nodes = [
{
id: "JS.Log",
label: "Console Log",
category: "Utils",
inputs: [{ name: "message", type: "string" }],
outputs: [],
execute: (inputs) => {
console.log(inputs.message);
return {};
}
}
];
Restart the container (docker compose restart backend) to load new nodes.
If you see this in the logs, a service is listening on 127.0.0.1.
command in docker-compose.yml uses 0.0.0.0.uvicorn ... --host 0.0.0.0, which handles this automatically.fetch in Node 22 (where it is built-in) or importing a missing package.import fetch from 'node-fetch' lines. If a package is missing, delete node_modules volume: docker compose down -v and rebuild..svelte file requires a rebuild.docker compose up --build frontend--watch mode. Changes to server.js apply instantly.main.py or plugins usually require a restart: docker compose restart python_backend.docker-compose.yml has - ./workflows:/app/workflows under the backend service.