Use this runbook to develop a function locally and invoke it through Windmill. A function is code that accepts inputs and returns a result. Windmill exposes deployed scripts as authenticated HTTP endpoints. It also supports scheduled jobs and workflows that combine scripts.
The repository configures Windmill 1.863.0 at https://windmill.aumer.dev through the internal Gateway. The HelmRelease declares one application replica and one worker replica in the default group. A standard worker executes one job at a time. Functions share worker capacity instead of receiving individual Kubernetes pods. Long jobs can delay other jobs, including cluster monitoring.
Worker replicas and worker groups provide additional capacity and workload separation. Autoscaling and dedicated workers have edition requirements. Changes to workers, routing, and network access require a separate infrastructure change. This runbook does not deploy a new platform or change worker capacity.
Use a workstation that can reach the internal Windmill hostname. Install Node.js, npm, Python 3, and curl on that workstation. Use Bash for the shell examples below. Use a Windmill account with access to a development workspace and permission to create scripts.
The commands follow current official CLI documentation, consulted on 2026-11-08. They were not tested against the configured 1.863.0 server. Current language and preview features require confirmation on that server. Use the installed CLI help if its arguments differ from this runbook.
Install the CLI on your workstation:
npm install -g windmill-cli
wmill --version
wmill workspace addIn the interactive setup, use these values:
- Enter
labv2-devas the local profile name. - Enter your existing development workspace ID from the Windmill workspace selector.
- Enter
https://windmill.aumer.devas the server URL. - Complete authentication through the browser or the interactive token prompt.
The profile name identifies a local connection, not a newly created workspace. The workspace command selects the new profile automatically. If you have several profiles, select this connection before each session:
wmill workspace switch labv2-devKeep CLI credentials outside Git. Do not paste tokens into commands, documentation, or shared terminal output. Use the interactive prompt when token authentication is necessary.
In the Windmill browser interface, create a Python script in your development workspace.
Use a new user-owned path, such as u/YOUR_USERNAME/hello.
Replace YOUR_USERNAME with your Windmill username throughout this runbook.
Do not edit f/cluster/monitor or other repository-owned automation for this exercise.
Use this script:
def main(name: str = "world"):
return {"message": f"Hello, {name}!"}Preview the script with {"name":"Aumer"} as its input.
Make sure that the result equals {"message":"Hello, Aumer!"}.
Deploy the script through the browser interface.
Keep the selected workspace ID and script path for the following steps.
Create a separate directory outside the infrastructure repository:
mkdir windmill-dev
cd windmill-dev
wmill initIf initialization asks for a workspace, select the development connection.
Keep credentials outside the generated files.
Review the generated wmill.yaml before synchronization.
The sync documentation describes file selection and secret exclusions.
Download only your example script and its metadata:
wmill sync pull --includes 'u/YOUR_USERNAME/hello*' --skip-variables --skip-resources --skip-secretsOpen u/YOUR_USERNAME/hello.py in your editor.
Keep the generated metadata and dependency lock files alongside the script.
Run this local assertion from the windmill-dev directory:
python3 - <<'PY'
import runpy
main = runpy.run_path("u/YOUR_USERNAME/hello.py")["main"]
assert main() == {"message": "Hello, world!"}
assert main("Aumer") == {"message": "Hello, Aumer!"}
PYThis test runs Python on your workstation without calling Windmill. It does not test worker dependencies, permissions, resources, or network access. Scripts that use Windmill resources need a connected instance or local test substitutes.
Confirm the selected development profile before deploying:
wmill workspace switch labv2-devDo not push over an unrelated script. The following push replaces the remote version at the specified path. It does not push the entire workspace.
wmill script push u/YOUR_USERNAME/hello.py
wmill script run u/YOUR_USERNAME/hello -d '{"name":"Aumer"}'Make sure that the remote result equals {"message":"Hello, Aumer!"}.
Open the run in Windmill to inspect its status, arguments, result, and logs.
The script commands deploy files and execute remote scripts.
The script run command uses a remote worker even when invoked from your workstation.
If imports or parameter types change, regenerate metadata before the next deployment.
Use the metadata command listed by your installed CLI help.
Review generated changes before pushing them.
Avoid an unrestricted wmill sync push against a shared workspace.
Open the deployed script and select its synchronous webhook, labeled Result/Sync in the current documentation.
A synchronous request waits for the function result.
Copy the generated URL into WINDMILL_WEBHOOK_URL below.
The URL must not contain a token.
The usual URL format is:
https://windmill.aumer.dev/api/w/WORKSPACE_ID/jobs/run_wait_result/p/u/YOUR_USERNAME/hello
Create a token with permission to run only the required script. Use the script's webhook token controls when available on your server. Keep that token out of browser application code. Browser applications need a backend or another appropriate authentication design.
In a private Bash session, invoke the function:
WINDMILL_WEBHOOK_URL='PASTE_GENERATED_URL_WITHOUT_TOKEN'
read -r -s -p 'Windmill token: ' WINDMILL_TOKEN
printf '\n'
printf 'header = "Authorization: Bearer %s"\n' "$WINDMILL_TOKEN" |
curl --config - --silent --show-error --fail-with-body \
--max-time 60 \
--header 'Content-Type: application/json' \
--data '{"name":"Aumer"}' \
"$WINDMILL_WEBHOOK_URL"
unset WINDMILL_TOKENThis command passes the authorization header through standard input instead of a command argument.
Do not enable shell tracing or curl verbose output during authentication.
Make sure that the response contains {"message":"Hello, Aumer!"}.
Inspect the matching Windmill run to confirm successful execution.
For long jobs, use the asynchronous webhook shown by Windmill. An asynchronous request returns a job ID for later result retrieval. An HTTP 200 response alone does not prove script success. Synchronous webhooks can return script errors inside a successful HTTP response. See the webhook reference.
From your local development directory, inspect the available preview command:
wmill dev --helpIf your CLI and server support the preview, start it:
wmill devThe development preview connects local files to a browser page with live reload. Execution still uses the connected Windmill instance. Keep this preview private because its connection carries authentication. If preview is unavailable, use the local assertion and explicit push/run steps above.
Current Windmill documentation lists the following script types:
| Category | Languages or tools |
|---|---|
| General programming | Python, TypeScript/JavaScript, Go, Rust, Java, C#, PHP, Ruby, R |
| Shell and automation | Bash, PowerShell, Nushell, Ansible |
| Database queries | PostgreSQL, MySQL, SQL Server, BigQuery, Snowflake, Oracle, DuckDB |
| Other integrations | REST, GraphQL, dbt |
TypeScript runtime availability depends on the server and worker image. Use the language selector on your server to confirm available script types. Run a small smoke test before selecting a language for production. One workflow can combine scripts written in different languages.
Container execution needs additional runtime support and isolation review. Do not assume that the current worker can execute arbitrary Docker images. The repository disables nsjail and PID namespace isolation on this worker. Use this shared worker only for trusted code.
If the hostname fails, make sure that your workstation can reach the internal network and resolve windmill.aumer.dev.
Do not replace the internal route with a public endpoint for troubleshooting.
If authentication fails, make sure that the token belongs to the correct workspace and permits the script.
If the script is missing, compare its deployed path with the webhook URL and CLI profile.
If a job stays queued, inspect Workers for an available worker with the matching job tag. If dependencies fail, inspect the build or run logs for missing runtimes and blocked downloads. Worker network policies restrict outbound access. Request a reviewed policy change if the workload needs a new destination.
If a request times out, inspect the run before retrying it. A client timeout does not prove that execution stopped. Repeated calls can repeat external writes. Design write operations to tolerate repeated requests safely.
If a deployment breaks the function, restore its previous source and metadata from your development history. Push the restored script to the same path. Repeat the local assertion, remote invocation, and HTTP test. Restoring source does not reverse external changes made by a previous run.
If a token leaks, revoke it in Windmill before issuing a replacement. Do not delete scripts or cancel shared jobs as part of this exercise without separate authorization. Do not edit repository-owned scripts directly because bootstrap automation restores their desired state. This runbook does not authorize live infrastructure changes.