n8n-node-configuration

Operation-aware node configuration with progressive discovery and property dependency management. Start with get_node({detail: "standard"}) for 95% of configuration needs; escalate to full detail or search_properties mode only when standard doesn't provide required information Resource and operation determine which fields are required; use validation iteratively to discover conditional dependencies controlled by displayOptions rules Common patterns include resource/operation nodes (Slack, Google Sheets), HTTP-based nodes with method-dependent fields, database nodes with operation-specific requirements, and conditional logic nodes with operator-dependent value fields Configuration workflow: identify operation, get node info, configure required fields, validate, search properties if stuck, add optional fields, validate again, then deploy

INSTALLATION
npx skills add https://github.com/czlonkowski/n8n-skills --skill n8n-node-configuration
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

n8n Node Configuration

Expert guidance for operation-aware node configuration with property dependencies.

Configuration Philosophy

Progressive disclosure: Start minimal, add complexity as needed

Configuration best practices:

  • get_node with detail: "standard" is the most used discovery pattern
  • 56 seconds average between configuration edits
  • Covers 95% of use cases with 1-2K tokens response

Key insight: Most configurations need only standard detail, not full schema!

Core Concepts

1. Operation-Aware Configuration

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!

2. Property Dependencies

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

3. Progressive Discovery

Use the right detail level:

-

get_node({detail: "standard"}) - DEFAULT

  • Quick overview (~1-2K tokens)
  • Required fields + common options
  • Use first - covers 95% of needs

-

get_node({mode: "search_properties", propertyQuery: "..."}) (for finding specific fields)

  • Find properties by name
  • Use when looking for auth, body, headers, etc.

-

get_node({detail: "full"}) (complete schema)

  • All properties (~3-8K tokens)
  • Use only when standard detail is insufficient

Configuration Workflow

Standard Process

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

Example: Configuring HTTP Request

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! ✅

get_node Detail Levels

Standard Detail (DEFAULT - Use This!)

✅ Starting configuration

get_node({

  nodeType: "nodes-base.slack"

});

// detail="standard" is the default

Returns (~1-2K tokens):

  • Required fields
  • Common options
  • Operation list
  • Metadata

Use: 95% of configuration needs

Full Detail (Use Sparingly)

✅ When standard isn't enough

get_node({

  nodeType: "nodes-base.slack",

  detail: "full"

});

Returns (~3-8K tokens):

  • Complete schema
  • All properties
  • All nested options

Warning: Large response, use only when standard insufficient

Search Properties Mode

✅ Looking for specific field

get_node({

  nodeType: "nodes-base.httpRequest",

  mode: "search_properties",

  propertyQuery: "auth"

});

Use: Find authentication, headers, body fields, etc.

Decision Tree

┌─────────────────────────────────┐

│ 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"})│

└─────────────────────────────────┘

Property Dependencies Deep Dive

displayOptions Mechanism

Fields have visibility rules:

{

  "name": "body",

  "displayOptions": {

    "show": {

      "sendBody": [true],

      "method": ["POST", "PUT", "PATCH"]

    }

  }

}

Translation: "body" field shows when:

  • sendBody = true AND
  • method = POST, PUT, or PATCH

Common Dependency Patterns

#### Pattern 1: Boolean Toggle

Example: HTTP Request sendBody

// sendBody controls body visibility

{

  "sendBody": true   // → body field appears

}

#### Pattern 2: Operation Switch

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!)

}

#### Pattern 3: Type Selection

Example: IF node conditions

{

  "type": "string",

  "operation": "contains"

  // → Shows: value1, value2

}

{

  "type": "boolean",

  "operation": "equals"

  // → Shows: value1, value2, different operators

}

Finding Property Dependencies

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

Common Node Patterns

Pattern 1: Resource/Operation Nodes

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:

  • Choose resource
  • Choose operation
  • Use get_node to see operation-specific requirements
  • Configure required fields

Pattern 2: HTTP-Based Nodes

Examples: HTTP Request, Webhook

Structure:

{

  "method": "<HTTP_METHOD>",

  "url": "<endpoint>",

  "authentication": "<type>",

  // ... method-specific fields

}

Dependencies:

  • POST/PUT/PATCH → sendBody available
  • sendBody=true → body required
  • authentication != "none" → credentials required

Pattern 3: Database Nodes

Examples: Postgres, MySQL, MongoDB

Structure:

{

  "operation": "<query|insert|update|delete>",

  // ... operation-specific fields

}

Dependencies:

  • operation="executeQuery" → query required
  • operation="insert" → table + values required
  • operation="update" → table + values + where required

Pattern 4: Conditional Logic Nodes

Examples: IF, Switch, Merge

Structure:

{

  "conditions": {

    "<type>": [

      {

        "operation": "<operator>",

        "value1": "...",

        "value2": "..."  // Only for binary operators

      }

    ]

  }

}

Dependencies:

  • Binary operators (equals, contains, etc.) → value1 + value2
  • Unary operators (isEmpty, isNotEmpty) → value1 only + singleValue: true

Operation-Specific Configuration

Slack Node Examples

#### Post Message

{

  "resource": "message",

  "operation": "post",

  "channel": "#general",      // Required

  "text": "Hello!",           // Required

  "attachments": [],          // Optional

  "blocks": []                // Optional

}

#### Update Message

{

  "resource": "message",

  "operation": "update",

  "messageId": "1234567890",  // Required (different from post!)

  "text": "Updated!",         // Required

  "channel": "#general"       // Optional (can be inferred)

}

#### Create Channel

{

  "resource": "channel",

  "operation": "create",

  "name": "new-channel",      // Required

  "isPrivate": false          // Optional

  // Note: text NOT required for this operation

}

HTTP Request Node Examples

#### GET Request

{

  "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"

      }

    ]

  }

}

#### POST with JSON

{

  "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": "john@example.com"

    }

  }

}

IF Node Examples

#### String Comparison (Binary)

{

  "conditions": {

    "string": [

      {

        "value1": "={{$json.status}}",

        "operation": "equals",

        "value2": "active"              // Binary: needs value2

      }

    ]

  }

}

#### Empty Check (Unary)

{

  "conditions": {

    "string": [

      {

        "value1": "={{$json.email}}",

        "operation": "isEmpty",

        // No value2 - unary operator

        "singleValue": true             // Auto-added by sanitization

      }

    ]

  }

}

Handling Conditional Requirements

Example: HTTP Request Body

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

Example: IF Node singleValue

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

Node-Specific Configuration Notes

SplitInBatches v3

{

  "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 input

See the n8n Workflow Patterns skill for detailed loop and nested loop patterns.

Google Sheets Node

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.

Configuration Anti-Patterns

❌ Don't: Over-configure Upfront

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

❌ Don't: Skip Validation

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({...});

}

❌ Don't: Ignore Operation Context

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)

Surgical Field Edits with patchNodeField

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:

  • Editing code inside Code nodes without re-transmitting the full code block
  • Updating URLs or text in large HTML email templates
  • Fixing typos in JSON bodies or long text fields
// 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.

Best Practices

Do

-

Start with get_node (standard detail)

  • ~1-2K tokens response
  • Covers 95% of configuration needs
  • Default detail level

-

Validate iteratively

  • Configure → Validate → Fix → Repeat
  • Average 2-3 iterations is normal
  • Read validation errors carefully

-

Use search_properties mode when stuck

  • If field seems missing, search for it
  • Understand what controls field visibility
  • get_node({mode: "search_properties", propertyQuery: "..."})

-

Respect operation context

  • Different operations = different requirements
  • Always check get_node when changing operation
  • Don't assume configs are transferable

-

Trust auto-sanitization

  • Operator structure fixed automatically
  • Don't manually add/remove singleValue
  • IF/Switch metadata added on save

❌ Don't

-

Jump to detail="full" immediately

  • Try standard detail first
  • Only escalate if needed
  • Full schema is 3-8K tokens

-

Configure blindly

  • Always validate before deploying
  • Understand why fields are required
  • Use search_properties for conditional fields

-

Copy configs without understanding

  • Different operations need different fields
  • Validate after copying
  • Adjust for new context

-

Manually fix auto-sanitization issues

  • Let auto-sanitization handle operator structure
  • Focus on business logic
  • Save and let system fix structure

Detailed References

For comprehensive guides on specific topics:

  • DEPENDENCIES.md - Deep dive into property dependencies and displayOptions

Summary

Configuration Strategy:

  • Start with get_node (standard detail is default)
  • Configure required fields for operation
  • Validate configuration
  • Search properties if stuck
  • Iterate until valid (avg 2-3 cycles)
  • Deploy with confidence

Key Principles:

  • Operation-aware: Different operations = different requirements
  • Progressive disclosure: Start minimal, add as needed
  • Dependency-aware: Understand field visibility rules
  • Validation-driven: Let validation guide configuration

Related Skills:

  • n8n MCP Tools Expert - How to use discovery tools correctly
  • n8n Validation Expert - Interpret validation errors
  • n8n Expression Syntax - Configure expression fields
  • n8n Workflow Patterns - Apply patterns with proper configuration
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card