/resources
MUST use when managing resources.
Claude Code
$ npx -y skills add windmill-labs/windmill --skill resources --agent claude-code
Codex
$ npx skills add windmill-labs/windmill --skill resources -a codex -y
Cursor
$ npx skills add windmill-labs/windmill --skill resources -a cursor -y
Gemini CLI
$ npx skills add windmill-labs/windmill --skill resources -a gemini-cli -y
GitHub Copilot
$ npx skills add windmill-labs/windmill --skill resources -a github-copilot -y
OpenCode
$ npx skills add windmill-labs/windmill --skill resources -a opencode -y
Windsurf
$ npx skills add windmill-labs/windmill --skill resources -a windsurf -y
SKILL.md
resources.SKILL.mdname: resources
description: MUST use when managing resources.
Windmill Resources
Resources store credentials and configuration for external services.
File Format
Resource files use the pattern: `{path}.resource.json`
Example: `f/databases/postgres_prod.resource.json`
Resource Structure
{
"value": {
"host": "db.example.com",
"port": 5432,
"user": "admin",
"password": "$var:g/all/db_password",
"dbname": "production"
},
"description": "Production PostgreSQL database",
"resource_type": "postgresql"
}Required Fields
- `value` - Object containing the resource configuration
- `resource_type` - Name of the resource type (e.g., "postgresql", "slack")
Agents
An agent, as the Agents page lists it, is a resource of type `ai_agent`. Its value holds the agent's provider, system prompt, tools and memory settings, and a flow step uses a saved agent by linking its path. Before writing one, use the `agents` skill.
Variable References
Reference variables in resource values:
{
"value": {
"api_key": "$var:g/all/api_key",
"secret": "$var:u/admin/secret"
}
}**Reference formats:**
- `$var:g/all/name` - Global variable
- `$var:u/username/name` - User variable
- `$var:f/folder/name` - Folder variable
Secrets
Never put a secret (password, API key, token) inline in a resource value. Store it in a secret variable and reference that variable as `$var:<path>`.
- `$var:<path>` is a reference, not a value: it resolves to the variable's value at run time. Never invent a value for a variable.
- A resource that references a variable needs the variable to exist first, so create or deploy the variable before the resource.
- A secret's plaintext never goes in a file of the repo: a `.variable.yaml` holding it would be committed. Ask the user to create the secret on the workspace instead, e.g. `wmill variable add '<value>' <path>` (a secret by default), then reference it by path.
Resource References
Reference other resources:
{
"value": {
"database": "$res:f/databases/postgres"
}
}Passing a Resource or Variable as a Run Argument
A script or flow argument typed as a resource (schema `format: resource-<type>`) is passed as the **bare string** `$res:<path>` — the whole argument value. Same for a variable, with `$var:<path>`. This applies everywhere job arguments are supplied: `wmill script run/preview`, `wmill flow run/preview`, the `runScriptByPath` / `runFlowByPath` API, a schedule's `args`, a trigger's configured static args.
{
"db": "$res:f/databases/postgres_prod",
"api_token": "$var:g/all/api_token"
}The reference is resolved when the job runs, under the job's run-as identity — the caller for an ordinary run, but the configured principal for a schedule, a trigger, or a runnable set to run on behalf of someone else. The run fails if that identity cannot read the referenced resource or variable.
**Never wrap it in an object.** The resolver only rewrites a JSON value that *is* a string starting with `$res:` / `$var:`; keys are never inspected. These are all wrong and are passed through to the script unchanged:
{ "db": { "$res": "f/databases/postgres_prod" } }
{ "db": { "resource": "f/databases/postgres_prod" } }
{ "db": "f/databases/postgres_prod" }The string may sit anywhere a string can — a top-level argument, a nested object field (`{ "gh_auth": { "token": "$var:g/all/gh_token" } }`), or an array element (array elements are walked only while nested at most two levels deep, and only for arrays of at most 1000 items). The prefix must be on the string itself.
Common Resource Types
PostgreSQL
{
"resource_type": "postgresql",
"value": {
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "$var:g/all/pg_password",
"dbname": "windmill",
"sslmode": "prefer"
}
}MySQL
{
"resource_type": "mysql",
"value": {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "$var:g/all/mysql_password",
"database": "myapp"
}
}Slack
{
"resource_type": "slack",
"value": {
"token": "$var:g/all/slack_token"
}
}AWS S3
{
"resource_type": "s3",
"value": {
"bucket": "my-bucket",
"region": "us-east-1",
"accessKeyId": "$var:g/all/aws_access_key",
"secretAccessKey": "$var:g/all/aws_secret_key"
}
}HTTP/API
{
"resource_type": "http",
"value": {
"baseUrl": "https://api.example.com",
"headers": {
"Authorization": "Bearer $var:g/all/api_token"
}
}
}Kafka
{
"resource_type": "kafka",
"value": {
"brokers": "broker1:9092,broker2:9092",
"sasl_mechanism": "PLAIN",
"security_protocol": "SASL_SSL",
"username": "$var:g/all/kafka_user",
"password": "$var:g/all/kafka_password"
}
}NATS
{
"resource_type": "nats",
"value": {
"servers": ["nats://localhost:4222"],
"user": "$var:g/all/nats_user",
"password": "$var:g/all/nats_password"
}
}MQTT
{
"resource_type": "mqtt",
"value": {
"host": "mqtt.example.com",
"port": 8883,
"username": "$var:g/all/mqtt_user",
"password": "$var:g/all/mqtt_password",
"tls": true
}
}When No Resource Type Fits
The Windmill Hub publishes resource types for most services, and an instance gets them by syncing with the hub. When none fits the service:
- If the instance is reported as not having synced the hub's types, mention that a superadmin can sync them: the hub most likely has one for the service. That holds for a type a hub script takes too: it is missing here until the sync, so say so before asking for a resource of it. Create one of your own only if the user still wants it, since after a sync the workspace would hold both.
- Otherwise, or when the user prefers it to syncing, propose a custom resource type named `c_<name>`
Read more
name: resources description: MUST use when managing resources.
Windmill Resources
Resources store credentials and configuration for external services.
File Format
Resource files use the pattern: `{path}.resource.json`
Example: `f/databases/postgres_prod.resource.json`
Resource Structure
{
"value": {
"host": "db.example.com",
"port": 5432,
"user": "admin",
"password": "$var:g/all/db_password",
"dbname": "production"
},
"description": "Production PostgreSQL database",
"resource_type": "postgresql"
}Required Fields
- `value` - Object containing the resource configuration
- `resource_type` - Name of the resource type (e.g., "postgresql", "slack")
Agents
An agent, as the Agents page lists it, is a resource of type `ai_agent`. Its value holds the agent's provider, system prompt, tools and memory settings, and a flow step uses a saved agent by linking its path. Before writing one, use the `agents` skill.
Variable References
Reference variables in resource values:
{
"value": {
"api_key": "$var:g/all/api_key",
"secret": "$var:u/admin/secret"
}
}**Reference formats:**
- `$var:g/all/name` - Global variable
- `$var:u/username/name` - User variable
- `$var:f/folder/name` - Folder variable
Secrets
Never put a secret (password, API key, token) inline in a resource value. Store it in a secret variable and reference that variable as `$var:<path>`.
- `$var:<path>` is a reference, not a value: it resolves to the variable's value at run time. Never invent a value for a variable.
- A resource that references a variable needs the variable to exist first, so create or deploy the variable before the resource.
- A secret's plaintext never goes in a file of the repo: a `.variable.yaml` holding it would be committed. Ask the user to create the secret on the workspace instead, e.g. `wmill variable add '<value>' <path>` (a secret by default), then reference it by path.
Resource References
Reference other resources:
{
"value": {
"database": "$res:f/databases/postgres"
}
}Passing a Resource or Variable as a Run Argument
A script or flow argument typed as a resource (schema `format: resource-<type>`) is passed as the **bare string** `$res:<path>` — the whole argument value. Same for a variable, with `$var:<path>`. This applies everywhere job arguments are supplied: `wmill script run/preview`, `wmill flow run/preview`, the `runScriptByPath` / `runFlowByPath` API, a schedule's `args`, a trigger's configured static args.
{
"db": "$res:f/databases/postgres_prod",
"api_token": "$var:g/all/api_token"
}The reference is resolved when the job runs, under the job's run-as identity — the caller for an ordinary run, but the configured principal for a schedule, a trigger, or a runnable set to run on behalf of someone else. The run fails if that identity cannot read the referenced resource or variable.
**Never wrap it in an object.** The resolver only rewrites a JSON value that *is* a string starting with `$res:` / `$var:`; keys are never inspected. These are all wrong and are passed through to the script unchanged:
{ "db": { "$res": "f/databases/postgres_prod" } }
{ "db": { "resource": "f/databases/postgres_prod" } }
{ "db": "f/databases/postgres_prod" }The string may sit anywhere a string can — a top-level argument, a nested object field (`{ "gh_auth": { "token": "$var:g/all/gh_token" } }`), or an array element (array elements are walked only while nested at most two levels deep, and only for arrays of at most 1000 items). The prefix must be on the string itself.
Common Resource Types
PostgreSQL
{
"resource_type": "postgresql",
"value": {
"host": "localhost",
"port": 5432,
"user": "postgres",
"password": "$var:g/all/pg_password",
"dbname": "windmill",
"sslmode": "prefer"
}
}MySQL
{
"resource_type": "mysql",
"value": {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "$var:g/all/mysql_password",
"database": "myapp"
}
}Slack
{
"resource_type": "slack",
"value": {
"token": "$var:g/all/slack_token"
}
}AWS S3
{
"resource_type": "s3",
"value": {
"bucket": "my-bucket",
"region": "us-east-1",
"accessKeyId": "$var:g/all/aws_access_key",
"secretAccessKey": "$var:g/all/aws_secret_key"
}
}HTTP/API
{
"resource_type": "http",
"value": {
"baseUrl": "https://api.example.com",
"headers": {
"Authorization": "Bearer $var:g/all/api_token"
}
}
}Kafka
{
"resource_type": "kafka",
"value": {
"brokers": "broker1:9092,broker2:9092",
"sasl_mechanism": "PLAIN",
"security_protocol": "SASL_SSL",
"username": "$var:g/all/kafka_user",
"password": "$var:g/all/kafka_password"
}
}NATS
{
"resource_type": "nats",
"value": {
"servers": ["nats://localhost:4222"],
"user": "$var:g/all/nats_user",
"password": "$var:g/all/nats_password"
}
}MQTT
{
"resource_type": "mqtt",
"value": {
"host": "mqtt.example.com",
"port": 8883,
"username": "$var:g/all/mqtt_user",
"password": "$var:g/all/mqtt_password",
"tls": true
}
}When No Resource Type Fits
The Windmill Hub publishes resource types for most services, and an instance gets them by syncing with the hub. When none fits the service:
- If the instance is reported as not having synced the hub's types, mention that a superadmin can sync them: the hub most likely has one for the service. That holds for a type a hub script takes too: it is missing here until the sync, so say so before asking for a resource of it. Create one of your own only if the user still wants it, since after a sync the workspace would hold both.
- Otherwise, or when the user prefers it to syncing, propose a custom resource type named `c_<name>`
Windmill is fully open-sourced (AGPLv3) and Windmill Labs offers dedicated instances and commercial support and licenses.
Other skills on windmill.
More skills from other plugins.
browser-use
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
Questions about resources.
- Which coding agents can use resources?
- resources installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

