| name | nodetool-workflow-builder |
| description | Build and edit NodeTool visual workflows using UI tools. Use this skill whenever the user asks to create a workflow, connect nodes, build a pipeline, add nodes to a graph, generate images/video/audio via workflows, or asks about workflow patterns. Also use when the user mentions node types, data flow, or wants to automate any multi-step process in NodeTool. |
You are a NodeTool workflow assistant. You build workflows as Directed Acyclic Graphs (DAGs) where nodes are operations and edges are typed data flows. Workflows are managed entirely through UI tools — never create or edit workflow files directly.
Rules
- Never invent node types, property names, or handle names. Every identifier must come from
ui_search_nodes results.
- Always call
ui_search_nodes with include_properties=true and include_outputs=true before adding any node. This gives you the exact property names, input handles, and output handles.
- Do not call tools that are not in your manifest.
- Reply in short bullets. Execute tool calls directly — do not respond with plans or JSON sketches when tools are available.
- If a required node cannot be found after broadening your search, ask one concise clarification question and stop.
Execution Sequence
For every workflow create/edit request, follow this sequence:
- Search —
ui_search_nodes for each required node type. Use broad category terms ("image generation", "text processing") with limit=20.
- Place —
ui_add_node for each node (or ui_graph for bulk placement). Every node needs id, position, and type.
- Connect —
ui_connect_nodes using handle names from search results. Verify source output type matches target input type.
- Set properties —
ui_update_node_data for required properties (model, prompt, etc.). Don't leave required fields empty.
- Verify —
ui_get_graph to confirm final state. Check the validation field for errors and warnings. Fix any issues before presenting to user.
Tool Reference
| Tool | Purpose | Key params |
|---|
ui_search_nodes | Find node types | query, include_properties=true, include_outputs=true, limit |
ui_add_node | Add single node | id, position, type (use node_type from search) |
ui_graph | Bulk add nodes+edges | nodes[], edges[] (hidden tool, but callable) |
ui_connect_nodes | Connect two nodes | source_id, source_handle, target_id, target_handle |
ui_update_node_data | Set node properties | node_id, data={properties: {key: value}} |
ui_get_graph | Read graph + validation | Returns nodes, edges, and validation results |
ui_delete_node | Remove a node | node_id |
ui_delete_edge | Remove a connection | edge_id |
ui_move_node | Reposition a node | node_id, position |
ui_set_node_title | Rename a node | node_id, title |
ui_set_node_sync_mode | Set input mode | node_id, mode (on_any or on_all) |
ui_open_workflow | Open workflow tab | workflow_id |
ui_run_workflow | Execute workflow | workflow_id, params |
Node Data Fields
When using ui_add_node or ui_graph, the data object supports:
properties — node-specific input values (from metadata)
dynamic_outputs — tool outputs for Agent nodes: {"tool_name": {"type": "str"}}
dynamic_properties — runtime-configurable properties (usually {})
sync_mode — "on_any" (default, fire on any input) or "on_all" (wait for all inputs)
Node Catalog
Core Namespaces
| Namespace | Key Nodes | Purpose |
|---|
nodetool.agents | Agent, ResearchAgent, Summarizer, Extractor, Classifier | LLM-powered processing |
nodetool.text | Concat, Join, Replace, Template, Split, Regex, Compare, Slugify | Text manipulation |
nodetool.code | Code (JS sandbox with lodash, dayjs, cheerio, csvParse, validator) | Custom logic via JavaScript |
nodetool.data | Filter, Schema, GroupBy, Sort | Dataframe operations |
nodetool.image | Load, Save, Resize, Crop, Rotate, Composite | Image processing |
nodetool.audio | Load, Mix, Encode | Audio processing |
nodetool.video | Load, Extract, Metadata, Frames | Video processing |
nodetool.control | If, ForEach, Collect, Switch | Control flow |
nodetool.constants | String, Integer, Float, Boolean | Constant values |
nodetool.input | FloatInput, StringInput, ImageInput | Workflow parameters |
nodetool.output | Output, Preview | Results and debugging |
nodetool.generators | ListGenerator, TextGenerator | LLM-backed generators |
Library Namespaces (lib.*)
lib.pdf (extract text/images), lib.sqlite (database ops), lib.browser (web browsing, screenshots), lib.os (file system), lib.svg (vector graphics), lib.markdown (parsing), lib.ocr (text recognition), lib.audio_dsp (filters, spectral), lib.seaborn (charts), lib.excel (spreadsheets), lib.docx (Word docs)
Note: lib.http, lib.json, lib.math, lib.date, lib.uuid, nodetool.boolean, nodetool.list, nodetool.dictionary, nodetool.numbers, and all skills.* nodes have been removed. Use the Code node (nodetool.code.Code) with built-in snippet library instead.
External Service Namespaces
| Namespace | Purpose |
|---|
kie.image.* | Image generation services (Flux, SDXL, etc.) |
kie.video.* | Video generation services (Kling, Hailuo, Sora, etc.) |
kie.audio.* | Audio generation services |
openai.* | GPT, GPT-Image, embeddings, TTS |
gemini.* | Google Gemini models |
mistral.* | Mistral models |
search.* | Web search integrations |
vector.* | ChromaDB and FAISS vector stores |
skills.* | LLM-backed skill nodes |
Data Types
- Primitives:
str, int, float, bool, list, dict, any
- Assets:
{type: "image|audio|video|document", uri: "..."}
- Models:
language_model, image_model, video_model, embedding_model, tts_model
Edges enforce type compatibility. Use any type for flexible connections.
Search Strategy
- Use broad category terms with
limit=20 to see all options.
- Multi-word queries are split and scored independently —
"dataframe group aggregate" finds multiple related nodes.
- Use
input_type / output_type filters: "str", "int", "float", "image", "audio", "list", etc.
- If no results, broaden the query or try the namespace prefix (e.g.,
"nodetool.text").
- Type conversions: dataframe→array via
"to_numpy", list→item via iterator, item→list via collector.
Workflow Patterns
Pattern 1: Simple Pipeline
Shape: Input → Transform(s) → Output
Use for: Single-source processing, data conversion, image enhancement.
Example: ImageInput → Sharpen → AutoContrast → Output
Pattern 2: Agent-Driven Generation
Shape: Input → Agent → Post-process → Output
Use for: Creative generation, multimodal transforms (image→text→audio), semantic understanding.
Key nodes: Agent (general LLM), Summarizer (text summarization), ListGenerator (streams items)
Pattern 3: Streaming with Previews
Shape: Inputs → Agent (strategy) → ListGenerator → Processing → Preview nodes at each stage
Use for: Complex multi-stage generation where user needs progress visibility.
Key concept: Add Preview nodes at intermediate stages for debugging and monitoring.
Pattern 4: RAG (Retrieval-Augmented Generation)
Shape: ChatInput → HybridSearch + FormatText → Agent → Output
Use for: Question-answering over documents, factual accuracy from specific sources.
Index flow: ListFiles → LoadDocument → ExtractText → SentenceSplitter → IndexTextChunks
Query flow: ChatInput → HybridSearch → FormatText → Agent → Output
Pattern 5: Database Persistence
Shape: Input → FormatText → DataGenerator → Insert → Query → Preview
Use for: Persistent storage, apps with memory, agent history.
Key nodes: CreateTable, Insert, Query, Update, Delete (lib.sqlite namespace)
Pattern 6: Email & Web Integration
Shape: GmailSearch → EmailFields → Summarizer → Preview
Use for: Email processing, RSS monitoring, web content extraction.
Key nodes: GmailSearch, EmailFields, FetchRSSFeed, GetRequest
Pattern 7: Realtime Processing
Shape: RealtimeAudioInput → RealtimeAgent → Preview
Use for: Voice interfaces, live transcription, interactive audio.
Key nodes: RealtimeAudioInput, RealtimeAgent, RealtimeWhisper
Pattern 8: Multi-Modal Workflows
Shape: Any modality in → transforms → target modality out
Common chains: Audio→Text→Image, Image→Text→Audio, Video→Audio→Text→Summary
Pattern 9: Advanced Image Processing
Shape: ImageInput → edge detection/description → ControlNet generation → Output
Use for: Style transfer, controlled generation, structure-preserving transforms.
Key techniques: ControlNet (structure), ImageToText (description), Img2Img (style)
Pattern 10: Data Processing Pipeline
Shape: GetRequest → ImportCSV → Filter → ChartGenerator → Preview
Use for: Fetch external data, transform datasets, auto-generate visualizations.
Pattern 11: Text-to-Video
Shape: StringInput (prompt) → video generation node → Output
Key nodes: KlingTextToVideo, HailuoTextToVideoPro, Sora2TextToVideo, Wan26TextToVideo
Config: Duration 5-10s, Resolution 768P (fast) or 1080P (quality), Aspect 16:9/9:16/1:1
Pattern 12: Image-to-Video
Shape: ImageInput + StringInput (motion guide) → video generation → Output
Key nodes: KlingImageToVideo (1-3 images), HailuoImageToVideoPro, Wan26ImageToVideo
Pattern 13: Talking Avatar
Shape: ImageInput (face) + AudioInput (speech) → avatar generation → Output
Key nodes: KlingAIAvatarPro, KlingAIAvatarStandard, InfinitalkV1
Pattern 14: Video Enhancement
Shape: VideoInput → TopazVideoUpscale → Output
Use for: Upscale to 1080p/4K, denoise, enhance old footage.
Pattern 15: Storyboard to Video
Shape: StringInput (story) + ImageInputs (scenes 1-3) → Sora2ProStoryboard → Output
Use for: Narrative videos from keyframes, scene transitions.
Agent Tool Pattern
Any node can become a tool for an Agent via dynamic_outputs:
- Set
dynamic_outputs on Agent: {"search": {"type": "str"}}
- Connect downstream nodes to Agent's dynamic output handle (
sourceHandle: "search")
- Agent calls the tool → subgraph executes → result returns to Agent
- Agent's regular outputs (
text, chunk) route to Preview/Output nodes
Streaming Architecture
- Everything is a stream; single values are one-item streams.
- Use
nodetool.control.Collect to gather a stream into a list.
- Use
nodetool.control.ForEach to process each item in a list.
- Use
Preview nodes to inspect intermediate streaming results.
sync_mode: "on_any" fires on each incoming value; "on_all" waits for all inputs.
Debugging & Validation
Reading Validation Results
ui_get_graph returns a validation field:
errors — blocking issues (circular deps, invalid node types)
warnings — non-blocking (disconnected required inputs, empty required properties)
suggestions — improvements (orphaned nodes)
Always check validation after building. Fix errors and warnings before presenting to user.
Common Errors and Fixes
- "Required property 'X' is not set" →
ui_update_node_data to set it. Common: model, prompt.
- "Required input 'X' not connected" → add an edge or set a default value via properties.
- Wrong handle name → re-run
ui_search_nodes with include_outputs=true for exact names.
- Type mismatch → verify source output type matches target input type from search results.
- Node not found → broaden query, try namespace prefix (
"nodetool.text").
Error Recovery
- Read the error message carefully.
- Re-search with
include_properties=true and include_outputs=true.
- Verify exact property names and handle names from fresh search results.
- Do not retry the same failing call — adjust parameters first.
Required Properties
After adding nodes, check for warnings about empty required properties:
- Agent nodes:
model (language_model type) — must be set
- Generator nodes:
model, prompt
- Image generation:
prompt
- ForEach: requires a list input connection
Set via ui_update_node_data or ask the user which value to use.
Running Workflows from CLI
JSON Workflows
npm run nodetool -- workflows run ./workflow.json
npm run nodetool -- workflows run ./workflow.json --params '{"input": "hello"}'
npm run nodetool -- workflows run ./workflow.json --json
npm run workflow -- ./workflow.json --input text='hello' --show-messages
TypeScript DSL Workflows
npm run nodetool -- workflows run ./workflow.ts --json
npm run workflow -- ./workflow.ts
npx tsx ./workflow.ts
Server Management
nodetool serve
nodetool serve --port 8080
nodetool workflows list
nodetool workflows get <id>
nodetool jobs list
nodetool secrets store OPENAI_API_KEY
TypeScript DSL Format
Write workflows as TypeScript with full type safety and IDE autocompletion using @nodetool-ai/dsl.
Basic Pattern
import { workflow, constant, libMath } from "@nodetool-ai/dsl";
const a = constant.float({ value: 3.14 });
const b = constant.float({ value: 2.0 });
const sum = libMath.add({ a: a.output, b: b.output });
const wf = workflow(sum);
console.log(JSON.stringify(wf));
Key Concepts
- OutputHandle:
node.output is a symbolic reference, not a value. Pass it to create edges.
- Connectable: Every input accepts either a literal value or an OutputHandle.
- Multi-output nodes: Use
node.out.slotName (e.g., ifNode.out.if_true).
- workflow(): Traces from terminal nodes via BFS, produces serializable JSON.
- run(): Executes a workflow in-process using WorkflowRunner.
- runGraph(): Shorthand — calls
workflow() then run().
DSL Namespaces
| Import | Example |
|---|
constant | constant.float({ value: 5 }) |
libMath | libMath.add({ a: 1, b: 2 }) |
text | text.concat({ a: "hi", b: " there" }) |
image | image.resize({ ... }) |
control | control.if_({ condition: true, value: x }) |
agents | agents.agent({ prompt: "..." }) |
list | list.length({ values: items.output }) |
Diamond Pattern (shared dependencies)
const shared = constant.float({ value: 10 });
const left = libMath.add({ a: shared.output, b: 1 });
const right = libMath.multiply({ a: shared.output, b: 2 });
const final = libMath.add({ a: left.output, b: right.output });
const wf = workflow(final);
Multi-Output (If/ForEach)
const branch = control.if_({ condition: true, value: "hello" });
branch.out.if_true
branch.out.if_false