skills/n8n-node-configuration/SKILL.md
Operation-aware node configuration guidance. Use when configuring nodes, understanding property dependencies, determining required fields, choosing between get_node detail levels, or learning common configuration patterns by node type. Always use this skill when setting up node parameters — it explains which fields are required for each operation, how displayOptions control field visibility, and when to use patchNodeField for surgical edits vs full node updates.
npx skillsauth add czlonkowski/n8n-skills n8n-node-configurationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert guidance for operation-aware node configuration with property dependencies.
Progressive disclosure: Start minimal, add complexity as needed
Configuration best practices:
get_node with detail: "standard" is the most used discovery patternKey insight: Most configurations need only standard detail, not full schema!
Not all fields are always required - it depends on operation!
Example: Slack node
// For operation='post'
{
"resource": "message",
"operation": "post",
"channel": "#general", // Required for post
"text": "Hello!" // Required for post
}
// For operation='update'
{
"resource": "message",
"operation": "update",
"messageId": "123", // Required for update (different!)
"text": "Updated!" // Required for update
// channel NOT required for update
}
Key: Resource + operation determine which fields are required!
Fields appear/disappear based on other field values
Example: HTTP Request node
// When method='GET'
{
"method": "GET",
"url": "https://api.example.com"
// sendBody not shown (GET doesn't have body)
}
// When method='POST'
{
"method": "POST",
"url": "https://api.example.com",
"sendBody": true, // Now visible!
"body": { // Required when sendBody=true
"contentType": "json",
"content": {...}
}
}
Mechanism: displayOptions control field visibility
Use the right detail level:
get_node({detail: "standard"}) - DEFAULT
get_node({mode: "search_properties", propertyQuery: "..."}) (for finding specific fields)
get_node({detail: "full"}) (complete schema)
1. Identify node type and operation
↓
2. Use get_node (standard detail is default)
↓
3. Configure required fields
↓
4. Validate configuration
↓
5. If field unclear → get_node({mode: "search_properties"})
↓
6. Add optional fields as needed
↓
7. Validate again
↓
8. Deploy
Step 1: Identify what you need
// Goal: POST JSON to API
Step 2: Get node info
const info = get_node({
nodeType: "nodes-base.httpRequest"
});
// Returns: method, url, sendBody, body, authentication required/optional
Step 3: Minimal config
{
"method": "POST",
"url": "https://api.example.com/create",
"authentication": "none"
}
Step 4: Validate
validate_node({
nodeType: "nodes-base.httpRequest",
config,
profile: "runtime"
});
// → Error: "sendBody required for POST"
Step 5: Add required field
{
"method": "POST",
"url": "https://api.example.com/create",
"authentication": "none",
"sendBody": true
}
Step 6: Validate again
validate_node({...});
// → Error: "body required when sendBody=true"
Step 7: Complete configuration
{
"method": "POST",
"url": "https://api.example.com/create",
"authentication": "none",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"name": "={{$json.name}}",
"email": "={{$json.email}}"
}
}
}
Step 8: Final validation
validate_node({...});
// → Valid! ✅
✅ Starting configuration
get_node({
nodeType: "nodes-base.slack"
});
// detail="standard" is the default
Returns (~1-2K tokens):
Use: 95% of configuration needs
✅ When standard isn't enough
get_node({
nodeType: "nodes-base.slack",
detail: "full"
});
Returns (~3-8K tokens):
Warning: Large response, use only when standard insufficient
✅ Looking for specific field
get_node({
nodeType: "nodes-base.httpRequest",
mode: "search_properties",
propertyQuery: "auth"
});
Use: Find authentication, headers, body fields, etc.
┌─────────────────────────────────┐
│ Starting new node config? │
├─────────────────────────────────┤
│ YES → get_node (standard) │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Standard has what you need? │
├─────────────────────────────────┤
│ YES → Configure with it │
│ NO → Continue │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Looking for specific field? │
├─────────────────────────────────┤
│ YES → search_properties mode │
│ NO → Continue │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Still need more details? │
├─────────────────────────────────┤
│ YES → get_node({detail: "full"})│
└─────────────────────────────────┘
Fields have visibility rules:
{
"name": "body",
"displayOptions": {
"show": {
"sendBody": [true],
"method": ["POST", "PUT", "PATCH"]
}
}
}
Translation: "body" field shows when:
Example: HTTP Request sendBody
// sendBody controls body visibility
{
"sendBody": true // → body field appears
}
Example: Slack resource/operation
// Different operations → different fields
{
"resource": "message",
"operation": "post"
// → Shows: channel, text, attachments, etc.
}
{
"resource": "message",
"operation": "update"
// → Shows: messageId, text (different fields!)
}
Example: IF node conditions
{
"type": "string",
"operation": "contains"
// → Shows: value1, value2
}
{
"type": "boolean",
"operation": "equals"
// → Shows: value1, value2, different operators
}
Use get_node with search_properties mode:
get_node({
nodeType: "nodes-base.httpRequest",
mode: "search_properties",
propertyQuery: "body"
});
// Returns property paths matching "body" with descriptions
Or use full detail for complete schema:
get_node({
nodeType: "nodes-base.httpRequest",
detail: "full"
});
// Returns complete schema with displayOptions rules
Use this when: Validation fails and you don't understand why field is missing/required
Examples: Slack, Google Sheets, Airtable
Structure:
{
"resource": "<entity>", // What type of thing
"operation": "<action>", // What to do with it
// ... operation-specific fields
}
How to configure:
Examples: HTTP Request, Webhook
Structure:
{
"method": "<HTTP_METHOD>",
"url": "<endpoint>",
"authentication": "<type>",
// ... method-specific fields
}
Dependencies:
Critical: credentials block, node id, typeVersion
"id": "REPLACE_ME") — n8n's UI renders a permanently disabled credential selector for unknown IDs. Omit the credentials block when the real ID is unknown; the user then gets a normal clickable dropdown.id must be a UUID v4, not a readable slug — the frontend binds forms and the credential component to it.typeVersion values — verify the current version with get_node (httpRequest is 4.4+).Examples: Postgres, MySQL, MongoDB
Structure:
{
"operation": "<query|insert|update|delete>",
// ... operation-specific fields
}
Dependencies:
Critical: Write operations may return 0 items
alwaysOutputData: true on write-operation nodes to keep downstream chains alive$('UpstreamNode').all() instead of $input if they need dataExamples: IF, Switch, Merge
Structure:
{
"conditions": {
"<type>": [
{
"operation": "<operator>",
"value1": "...",
"value2": "..." // Only for binary operators
}
]
}
}
Dependencies:
{
"resource": "message",
"operation": "post",
"channel": "#general", // Required
"text": "Hello!", // Required
"attachments": [], // Optional
"blocks": [] // Optional
}
{
"resource": "message",
"operation": "update",
"messageId": "1234567890", // Required (different from post!)
"text": "Updated!", // Required
"channel": "#general" // Optional (can be inferred)
}
{
"resource": "channel",
"operation": "create",
"name": "new-channel", // Required
"isPrivate": false // Optional
// Note: text NOT required for this operation
}
{
"method": "GET",
"url": "https://api.example.com/users",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"sendQuery": true, // Optional
"queryParameters": { // Shows when sendQuery=true
"parameters": [
{
"name": "limit",
"value": "100"
}
]
}
}
{
"method": "POST",
"url": "https://api.example.com/users",
"authentication": "none",
"sendBody": true, // Required for POST
"body": { // Required when sendBody=true
"contentType": "json",
"content": {
"name": "John Doe",
"email": "[email protected]"
}
}
}
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active" // Binary: needs value2
}
]
}
}
{
"conditions": {
"string": [
{
"value1": "={{$json.email}}",
"operation": "isEmpty",
// No value2 - unary operator
"singleValue": true // Auto-added by sanitization
}
]
}
}
Scenario: body field required, but only sometimes
Rule:
body is required when:
- sendBody = true AND
- method IN (POST, PUT, PATCH, DELETE)
How to discover:
// Option 1: Read validation error
validate_node({...});
// Error: "body required when sendBody=true"
// Option 2: Search for the property
get_node({
nodeType: "nodes-base.httpRequest",
mode: "search_properties",
propertyQuery: "body"
});
// Shows: body property with displayOptions rules
// Option 3: Try minimal config and iterate
// Start without body, validation will tell you if needed
Scenario: singleValue property appears for unary operators
Rule:
singleValue should be true when:
- operation IN (isEmpty, isNotEmpty, true, false)
Good news: Auto-sanitization fixes this!
Manual check:
get_node({
nodeType: "nodes-base.if",
detail: "full"
});
// Shows complete schema with operator-specific rules
{
"batchSize": 100, // Number of items per batch
"options": {}
}
Output wiring:
main[0] (done) → Connect to downstream processing (add Limit 1 first)main[1] (each batch) → Connect to loop body, then loop back to SplitInBatches inputSee the n8n Workflow Patterns skill for detailed loop and nested loop patterns.
Per-item execution: Each input item triggers a separate API call. If you have 100 items and use a Google Sheets "Append Row" node, it makes 100 API calls. To write in bulk, aggregate items in a Code node first, then use a single HTTP Request with the Sheets API.
Formula columns: Never use append on sheets with formula columns — it overwrites formulas. Instead, use HTTP Request with Google Sheets API values.update (PUT) method and a googleApi credential.
Bad:
// Adding every possible field
{
"method": "GET",
"url": "...",
"sendQuery": false,
"sendHeaders": false,
"sendBody": false,
"timeout": 10000,
"ignoreResponseCode": false,
// ... 20 more optional fields
}
Good:
// Start minimal
{
"method": "GET",
"url": "...",
"authentication": "none"
}
// Add fields only when needed
Bad:
// Configure and deploy without validating
const config = {...};
n8n_update_partial_workflow({...}); // YOLO
Good:
// Validate before deploying
const config = {...};
const result = validate_node({...});
if (result.valid) {
n8n_update_partial_workflow({...});
}
Bad:
// Same config for all Slack operations
{
"resource": "message",
"operation": "post",
"channel": "#general",
"text": "..."
}
// Then switching operation without updating config
{
"resource": "message",
"operation": "update", // Changed
"channel": "#general", // Wrong field for update!
"text": "..."
}
Good:
// Check requirements when changing operation
get_node({
nodeType: "nodes-base.slack"
});
// See what update operation needs (messageId, not channel)
When you need to edit a specific string inside a node field — rather than replacing the whole field — use patchNodeField in n8n_update_partial_workflow. This is especially useful for:
// Instead of replacing the entire jsCode field:
n8n_update_partial_workflow({
id: "wf-123",
operations: [{
type: "patchNodeField",
nodeName: "Code",
fieldPath: "parameters.jsCode",
patches: [{find: "const limit = 10;", replace: "const limit = 50;"}]
}]
})
patchNodeField is strict — it errors if the find string isn't found or matches multiple times (unless replaceAll: true). This prevents accidental silent failures during configuration updates. See the n8n MCP Tools Expert skill for full syntax and examples.
Start with get_node (standard detail)
Validate iteratively
Use search_properties mode when stuck
get_node({mode: "search_properties", propertyQuery: "..."})Respect operation context
Trust auto-sanitization
Jump to detail="full" immediately
Configure blindly
Copy configs without understanding
Manually fix auto-sanitization issues
For comprehensive guides on specific topics:
Configuration Strategy:
get_node (standard detail is default)Key Principles:
Related Skills:
tools
--- name: n8n-code-tool description: Write JavaScript or Python for the n8n Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode) — the AI-agent-callable tool, NOT the workflow Code node. Use when building a Code Tool attached to an AI Agent, writing code that an LLM will invoke, parsing the `query` input, returning a string result, defining an input schema for structured arguments (specifyInputSchema, jsonSchemaExample, DynamicStructuredTool), or troubleshooting errors like "Wrong output type re
tools
Proven workflow architectural patterns from real n8n workflows. Use when building new workflows, designing workflow structure, choosing workflow patterns, planning workflow architecture, or asking about webhook processing, HTTP API integration, database operations, AI agent workflows, batch processing, or scheduled tasks. Always consult this skill when the user asks to create, build, or design an n8n workflow, automate a process, or connect services — even if they don't explicitly mention 'patterns'. Covers webhook, API, database, AI, batch processing, and scheduled automation architectures.
tools
Expert guide for using n8n-mcp MCP tools effectively. Use when searching for nodes, validating configurations, accessing templates, managing workflows, managing credentials, auditing instance security, or using any n8n-mcp tool. Provides tool selection guidance, parameter formats, and common patterns. IMPORTANT — Always consult this skill before calling any n8n-mcp tool — it prevents common mistakes like wrong nodeType formats, incorrect parameter structures, and inefficient tool usage. If the user mentions n8n, workflows, nodes, or automation and you have n8n MCP tools available, use this skill first.
tools
Write Python code in n8n Code nodes. Use when writing Python in n8n, using _input/_json/_node syntax, working with standard library, or need to understand Python limitations in n8n Code nodes. Use this skill when the user specifically requests Python for an n8n Code node. Note — JavaScript is recommended for 95% of use cases — only use Python when the user explicitly prefers it or the task requires Python-specific standard library capabilities (regex, hashlib, statistics). EXCEPTION — for Python in the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode), use the n8n-code-tool skill instead (input is _query, return must be a string).