NodeTool exposes workflow REST endpoints under /api/workflows from a single server (nodetool serve):
/api/workflows for CRUD and query operations, and POST /api/workflows/{id}/run to run a workflow.
This page collects the basics from the project README. See API Reference for
the canonical endpoint list and auth requirements. When AUTH_PROVIDER is static or supabase, include
Authorization: Bearer <token>; tokens are optional only in local/none modes.
Loading Workflows
const response = await fetch("http://localhost:7777/api/workflows/");
const workflows = await response.json();
Running a Workflow
HTTP API
curl -X POST "http://localhost:7777/api/workflows/<workflow_id>/run" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"params": {
"param_name": "param_value"
}
}'
const response = await fetch(
"http://localhost:7777/api/workflows/<workflow_id>/run",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN",
},
body: JSON.stringify({
params: params,
}),
}
);
const body = await response.json();
// body has the shape:
// {
// "job_id": "<uuid>",
// "workflow_id": "<uuid>",
// "status": "completed" | "cancelled" | "failed",
// "outputs": { /* one property per output node, keyed by node name */ },
// "error": null,
// "message_count": 42,
// "background": false
// }
// outputs values can be a string, image, audio, etc.
POST /api/workflows/{id}/run runs the workflow to completion and returns a
single JSON response — it does not stream. For real-time progress (job and node
updates, incremental output), run the workflow over the WebSocket endpoint
instead.
Listing Names and Tools
Two lightweight GET routes answer “what workflows exist?” without paying for
full graphs. Both read the caller’s own library, so both stay behind auth.
GET /api/workflows/names returns an id → name object for up to 1000 of the
caller’s workflows. Use it to label a workflow id you already hold — a job
record, a saved reference — without fetching the workflow.
curl "http://localhost:7777/api/workflows/names" \
-H "Authorization: Bearer YOUR_TOKEN"
{ "21fddc0c2c46458493287b151b790cc4": "Greeting" }
GET /api/workflows/tools returns only the workflows saved with
run_mode: "tool" — the ones an agent may call as a tool — reduced to what a
tool picker needs. limit defaults to 100 and is capped at 500.
curl "http://localhost:7777/api/workflows/tools?limit=50" \
-H "Authorization: Bearer YOUR_TOKEN"
{
"workflows": [
{
"name": "Summarize",
"tool_name": "summarize",
"description": "Summarize a block of text"
}
],
"next": null
}
A workflow with a tool_name but no run_mode: "tool" does not appear here.
Exporting a Workflow as DSL
GET /api/workflows/{id}/dsl-export returns the workflow’s graph as TypeScript
DSL source with content-type: text/plain; charset=utf-8 — the same source
nodetool workflows export-dsl writes. Use it to put a workflow under version
control, or to hand an agent an editable form of the graph.
curl "http://localhost:7777/api/workflows/<workflow_id>/dsl-export" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o workflow.ts
import { constant, workflow } from "@nodetool-ai/dsl";
// 1 — nodetool.constant.String
const string = constant.string({
value: "hi"
});
export const greetingWorkflow = workflow(string);
The route answers 404 unless the workflow is yours or marked
access: "public", and 400 when the workflow has no graph or the graph
cannot be expressed as DSL.
Public Workflows
A workflow saved with access: "public" is readable without a token. These two
routes and the example routes below are the only /api/workflows paths exempt
from auth — every other one serves the caller’s private library, graph
included, so it stays behind a token.
# Every public workflow (limit defaults to 100, caps at 500)
curl "http://localhost:7777/api/workflows/public"
# One public workflow, full graph included
curl "http://localhost:7777/api/workflows/public/<workflow_id>"
Both return the normal workflow shape (id, name, description, graph,
access, …). Asking for a workflow that exists but is not public gets the same
404 as one that does not exist:
{ "detail": "Workflow not found" }
Example Templates
The example workflows NodeTool ships are served from disk rather than the database, so they need no token and exist on a fresh install.
curl "http://localhost:7777/api/workflows/examples"
curl "http://localhost:7777/api/workflows/examples/search?query=chat"
search filters the same list on query against each example’s name,
description, and tags, case-insensitively; omitting query returns everything.
Both responses carry metadata only — graph comes back empty:
{
"workflows": [
{
"id": "A Boolean Constant.json",
"name": "A Boolean Constant",
"description": "The smallest possible graph, and a real one: …",
"tags": ["example"],
"package_name": "nodetool-base",
"thumbnail": "A Boolean Constant.jpg",
"thumbnail_url": "/api/workflows/examples/thumbnails/A%20Boolean%20Constant.jpg?v=a6dce6b4",
"graph": { "nodes": [], "edges": [] }
}
],
"next": null
}
Fetch the image at the thumbnail_url the list hands back:
curl "http://localhost:7777/api/workflows/examples/thumbnails/A%20Boolean%20Constant.jpg" \
-o thumb.jpg
Only .jpg and .png are served — any other extension is a 400 — and the
filename is reduced to its basename, so it cannot escape the examples assets
directory.
WebSocket API
For real-time streaming and job control over WebSocket, see the dedicated
WebSocket API page. The reference client in
examples/workflow_runner/js/workflow-runner.js
shows how to consume job_update, node_update, and node_progress messages.
API Demo
- Grab the example runner (
examples/workflow_runner). - Open
index.htmlin a browser locally. - Select the endpoint (local or
api.nodetool.aifor alpha users). - Enter an API token from the NodeTool settings dialog.
- Select a workflow and run it.