Install
mkdir -p .claude/skills/write-flow && curl -L -o skill.zip "https://mcp.directory/api/skills/download/3755" && unzip -o skill.zip -d .claude/skills/write-flow && rm skill.zipInstalls to .claude/skills/write-flow
About this skill
Windmill Flow Building Guide
CLI Commands
Create a folder ending with __flow and add a flow.yaml file with the flow definition.
For rawscript modules, use !inline path/to/script.ts for the content key. Inline script files should NOT include .inline_script. in their names (e.g. use a.ts, not a.inline_script.ts).
After writing, tell the user they can run:
wmill flow generate-locks <path_to_flow_folder> --yes- Generate lock files for the specific flow you modified (e.g.wmill flow generate-locks f/my_folder/my_flow__flow --yes)wmill sync push- Deploy to Windmill
Do NOT run these commands yourself. Instead, inform the user that they should run them.
OpenFlow Schema
The OpenFlow schema (openflow.openapi.yaml) is the source of truth for flow structure. Refer to OPENFLOW_SCHEMA for the complete type definitions.
Reserved Module IDs
failure- Reserved for failure handler modulepreprocessor- Reserved for preprocessor moduleInput- Reserved for flow input reference
Module ID Rules
- Must be unique across the entire flow
- Use underscores, not spaces (e.g.,
fetch_datanotfetch data) - Use descriptive names that reflect the step's purpose
Common Mistakes to Avoid
- Missing
input_transforms- Rawscript parameters won't receive values without them - Referencing future steps -
results.step_idonly works for steps that execute before the current one - Duplicate module IDs - Each module ID must be unique in the flow
Data Flow Between Steps
flow_input.property- Access flow input parametersresults.step_id- Access output from a previous stepresults.step_id.property- Access specific property from previous step outputflow_input.iter.value- Current item when inside a for-loopflow_input.iter.index- Current index when inside a for-loop
Input Transforms
Every rawscript module needs input_transforms to map function parameters to values:
Static transform (fixed value): {"param_name": {"type": "static", "value": "fixed_string"}}
JavaScript transform (dynamic expression): {"param_name": {"type": "javascript", "expr": "results.previous_step.data"}}
Resource References
- For flow inputs: Use type
"object"with format"resource-{type}"(e.g.,"resource-postgresql") - For step inputs: Use static value
"$res:path/to/resource"
Failure Handler
Executes when any step fails. Has access to error details:
error.message- Error messageerror.step_id- ID of failed steperror.name- Error nameerror.stack- Stack trace
S3 Object Operations
Windmill provides built-in support for S3-compatible storage operations.
To accept an S3 object as flow input:
{
"type": "object",
"properties": {
"file": {
"type": "object",
"format": "resource-s3_object",
"description": "File to process"
}
}
}
Using Resources in Flows
On Windmill, credentials and configuration are stored in resources. Resource types define the format of the resource.
As Flow Input
In the flow schema, set the property type to "object" with format "resource-{type}":
{
"type": "object",
"properties": {
"database": {
"type": "object",
"format": "resource-postgresql",
"description": "Database connection"
}
}
}
As Step Input (Static Reference)
Reference a specific resource using $res: prefix:
{
"database": {
"type": "static",
"value": "$res:f/folder/my_database"
}
}
OpenFlow Schema
{"OpenFlow":{"type":"object","description":"Top-level flow definition containing metadata, configuration, and the flow structure","properties":{"summary":{"type":"string","description":"Short description of what this flow does"},"description":{"type":"string","description":"Detailed documentation for this flow"},"value":{"$ref":"#/components/schemas/FlowValue"},"schema":{"type":"object","description":"JSON Schema for flow inputs. Use this to define input parameters, their types, defaults, and validation. For resource inputs, set type to 'object' and format to 'resource-<type>' (e.g., 'resource-stripe')"},"on_behalf_of_email":{"type":"string","description":"The flow will be run with the permissions of the user with this email."}},"required":["summary","value"]},"FlowValue":{"type":"object","description":"The flow structure containing modules and optional preprocessor/failure handlers","properties":{"modules":{"type":"array","description":"Array of steps that execute in sequence. Each step can be a script, subflow, loop, or branch","items":{"$ref":"#/components/schemas/FlowModule"}},"failure_module":{"description":"Special module that executes when the flow fails. Receives error object with message, name, stack, and step_id. Must have id 'failure'. Only supports script/rawscript types","$ref":"#/components/schemas/FlowModule"},"preprocessor_module":{"description":"Special module that runs before the first step on external triggers. Must have id 'preprocessor'. Only supports script/rawscript types. Cannot reference other step results","$ref":"#/components/schemas/FlowModule"},"same_worker":{"type":"boolean","description":"If true, all steps run on the same worker for better performance"},"concurrent_limit":{"type":"number","description":"Maximum number of concurrent executions of this flow"},"concurrency_key":{"type":"string","description":"Expression to group concurrent executions (e.g., by user ID)"},"concurrency_time_window_s":{"type":"number","description":"Time window in seconds for concurrent_limit"},"debounce_delay_s":{"type":"integer","description":"Delay in seconds to debounce flow executions"},"debounce_key":{"type":"string","description":"Expression to group debounced executions"},"debounce_args_to_accumulate":{"type":"array","description":"Arguments to accumulate across debounced executions","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"Maximum total time in seconds that a job can be debounced"},"max_total_debounces_amount":{"type":"integer","description":"Maximum number of times a job can be debounced"},"skip_expr":{"type":"string","description":"JavaScript expression to conditionally skip the entire flow"},"cache_ttl":{"type":"number","description":"Cache duration in seconds for flow results"},"cache_ignore_s3_path":{"type":"boolean"},"flow_env":{"type":"object","description":"Environment variables available to all steps. Values can be strings, JSON values, or special references: '$var:path' (workspace variable) or '$res:path' (resource).","additionalProperties":{}},"priority":{"type":"number","description":"Execution priority (higher numbers run first)"},"early_return":{"type":"string","description":"JavaScript expression to return early from the flow"},"chat_input_enabled":{"type":"boolean","description":"Whether this flow accepts chat-style input"},"notes":{"type":"array","description":"Sticky notes attached to the flow","items":{"$ref":"#/components/schemas/FlowNote"}},"groups":{"type":"array","description":"Semantic groups of modules for organizational purposes","items":{"$ref":"#/components/schemas/FlowGroup"}}},"required":["modules"]},"Retry":{"type":"object","description":"Retry configuration for failed module executions","properties":{"constant":{"type":"object","description":"Retry with constant delay between attempts","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"seconds":{"type":"integer","description":"Seconds to wait between retries"}}},"exponential":{"type":"object","description":"Retry with exponential backoff (delay doubles each time)","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"multiplier":{"type":"integer","description":"Multiplier for exponential backoff"},"seconds":{"type":"integer","minimum":1,"description":"Initial delay in seconds"},"random_factor":{"type":"integer","minimum":0,"maximum":100,"description":"Random jitter percentage (0-100) to avoid thundering herd"}}},"retry_if":{"$ref":"#/components/schemas/RetryIf"}}},"FlowNote":{"type":"object","description":"A sticky note attached to a flow for documentation and annotation","properties":{"id":{"type":"string","description":"Unique identifier for the note"},"text":{"type":"string","description":"Content of the note"},"position":{"type":"object","description":"Position of the note in the flow editor","properties":{"x":{"type":"number","description":"X coordinate"},"y":{"type":"number","description":"Y coordinate"}},"required":["x","y"]},"size":{"type":"object","description":"Size of the note in the flow editor","properties":{"width":{"type":"number","description":"Width in pixels"},"height":{"type":"number","description":"Height in pixels"}},"required":["width","height"]},"color":{"type":"string","description":"Color of the note (e.g., "yellow", "#ffff00")"},"type":{"type":"string","enum":["free","group"],"description":"Type of note - 'free' for standalone notes, 'group' for notes that group other nodes"},"locked":{"type":"boolean","default":false,"description":"Whether the note is locked and cannot be edited or moved"},"contained_node_ids":{"type":"array","items":{"type":"string"},"description":"For group notes, the IDs of nodes contained within this group"}},"required":["id","text","color","type"]},"FlowGroup":{"type":"object","description":"A semantic group of flow modules for organizational purposes. Does not affect execution \u2014 modules remain in their original position in the flow. Groups provide naming and collapsibility in the editor. Members are computed dynamically from all nodes on paths between start_id and end_id.","properties":{"summary":{"type":"string","description":"Display name for this group"},"note":{"type":"string","description":"Markdown note shown below the group header"},"autocollapse":{"type":"boolean","default":false,"description":"If true, this group is collapsed by default in the flow
Content truncated.
More by windmill-labs
View all skills by windmill-labs →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversEmpower your Unity projects with Unity-MCP: AI-driven control, seamless integration, and advanced workflows within the U
AI-driven CAD modeling with FreeCAD: control design workflows, generate logos, and edit objects using remote Python scri
Seamlessly integrate with Odoo ERP for advanced business record management, automation, and secure data workflows via XM
Integrate with Miro's online whiteboard for seamless collaboration. Manage boards, create items, and use 80+ tools for v
Integrate with Monday.com for streamlined project management, team collaboration tools, and project tracking software fo
RSS Feed Parser is a powerful rss feed generator and rss link generator with RSSHub integration, perfect for creating cu
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.