Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:17:17 +08:00
commit 6062d3994e
39 changed files with 21748 additions and 0 deletions

View File

@@ -0,0 +1,800 @@
# Property Dependencies Guide
Deep dive into n8n property dependencies and displayOptions mechanism.
---
## What Are Property Dependencies?
**Definition**: Rules that control when fields are visible or required based on other field values.
**Mechanism**: `displayOptions` in node schema
**Purpose**:
- Show relevant fields only
- Hide irrelevant fields
- Simplify configuration UX
- Prevent invalid configurations
---
## displayOptions Structure
### Basic Format
```javascript
{
"name": "fieldName",
"type": "string",
"displayOptions": {
"show": {
"otherField": ["value1", "value2"]
}
}
}
```
**Translation**: Show `fieldName` when `otherField` equals "value1" OR "value2"
### Show vs Hide
#### show (Most Common)
**Show field when condition matches**:
```javascript
{
"name": "body",
"displayOptions": {
"show": {
"sendBody": [true]
}
}
}
```
**Meaning**: Show `body` when `sendBody = true`
#### hide (Less Common)
**Hide field when condition matches**:
```javascript
{
"name": "advanced",
"displayOptions": {
"hide": {
"simpleMode": [true]
}
}
}
```
**Meaning**: Hide `advanced` when `simpleMode = true`
### Multiple Conditions (AND Logic)
```javascript
{
"name": "body",
"displayOptions": {
"show": {
"sendBody": [true],
"method": ["POST", "PUT", "PATCH"]
}
}
}
```
**Meaning**: Show `body` when:
- `sendBody = true` AND
- `method IN (POST, PUT, PATCH)`
**All conditions must match** (AND logic)
### Multiple Values (OR Logic)
```javascript
{
"name": "someField",
"displayOptions": {
"show": {
"method": ["POST", "PUT", "PATCH"]
}
}
}
```
**Meaning**: Show `someField` when:
- `method = POST` OR
- `method = PUT` OR
- `method = PATCH`
**Any value matches** (OR logic)
---
## Common Dependency Patterns
### Pattern 1: Boolean Toggle
**Use case**: Optional feature flag
**Example**: HTTP Request sendBody
```javascript
// Field: sendBody (boolean)
{
"name": "sendBody",
"type": "boolean",
"default": false
}
// Field: body (depends on sendBody)
{
"name": "body",
"displayOptions": {
"show": {
"sendBody": [true]
}
}
}
```
**Flow**:
1. User sees sendBody checkbox
2. When checked → body field appears
3. When unchecked → body field hides
### Pattern 2: Resource/Operation Cascade
**Use case**: Different operations show different fields
**Example**: Slack message operations
```javascript
// Operation: post
{
"name": "channel",
"displayOptions": {
"show": {
"resource": ["message"],
"operation": ["post"]
}
}
}
// Operation: update
{
"name": "messageId",
"displayOptions": {
"show": {
"resource": ["message"],
"operation": ["update"]
}
}
}
```
**Flow**:
1. User selects resource="message"
2. User selects operation="post" → sees channel
3. User changes to operation="update" → channel hides, messageId shows
### Pattern 3: Type-Specific Configuration
**Use case**: Different types need different fields
**Example**: IF node conditions
```javascript
// String operations
{
"name": "value2",
"displayOptions": {
"show": {
"conditions.string.0.operation": ["equals", "notEquals", "contains"]
}
}
}
// Unary operations (isEmpty) don't show value2
{
"displayOptions": {
"hide": {
"conditions.string.0.operation": ["isEmpty", "isNotEmpty"]
}
}
}
```
### Pattern 4: Method-Specific Fields
**Use case**: HTTP methods have different options
**Example**: HTTP Request
```javascript
// Query parameters (all methods can have)
{
"name": "queryParameters",
"displayOptions": {
"show": {
"sendQuery": [true]
}
}
}
// Body (only certain methods)
{
"name": "body",
"displayOptions": {
"show": {
"sendBody": [true],
"method": ["POST", "PUT", "PATCH", "DELETE"]
}
}
}
```
---
## Using get_property_dependencies
### Basic Usage
```javascript
const deps = get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
```
### Example Response
```javascript
{
"nodeType": "n8n-nodes-base.httpRequest",
"dependencies": {
"body": {
"shows_when": {
"sendBody": [true],
"method": ["POST", "PUT", "PATCH", "DELETE"]
},
"required_when_shown": true
},
"queryParameters": {
"shows_when": {
"sendQuery": [true]
},
"required_when_shown": false
},
"headerParameters": {
"shows_when": {
"sendHeaders": [true]
},
"required_when_shown": false
}
}
}
```
### When to Use
**✅ Use when**:
- Validation fails with "missing field" but you don't see that field
- A field appears/disappears unexpectedly
- You need to understand what controls field visibility
- Building dynamic configuration tools
**❌ Don't use when**:
- Simple configuration (use get_node_essentials)
- Just starting configuration
- Field requirements are obvious
---
## Complex Dependency Examples
### Example 1: HTTP Request Complete Flow
**Scenario**: Configuring POST with JSON body
**Step 1**: Set method
```javascript
{
"method": "POST"
// → sendBody becomes visible
}
```
**Step 2**: Enable body
```javascript
{
"method": "POST",
"sendBody": true
// → body field becomes visible AND required
}
```
**Step 3**: Configure body
```javascript
{
"method": "POST",
"sendBody": true,
"body": {
"contentType": "json"
// → content field becomes visible AND required
}
}
```
**Step 4**: Add content
```javascript
{
"method": "POST",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"name": "John",
"email": "john@example.com"
}
}
}
// ✅ Valid!
```
**Dependency chain**:
```
method=POST
→ sendBody visible
→ sendBody=true
→ body visible + required
→ body.contentType=json
→ body.content visible + required
```
### Example 2: IF Node Operator Dependencies
**Scenario**: String comparison with different operators
**Binary operator** (equals):
```javascript
{
"conditions": {
"string": [
{
"operation": "equals"
// → value1 required
// → value2 required
// → singleValue should NOT be set
}
]
}
}
```
**Unary operator** (isEmpty):
```javascript
{
"conditions": {
"string": [
{
"operation": "isEmpty"
// → value1 required
// → value2 should NOT be set
// → singleValue should be true (auto-added)
}
]
}
}
```
**Dependency table**:
| Operator | value1 | value2 | singleValue |
|---|---|---|---|
| equals | Required | Required | false |
| notEquals | Required | Required | false |
| contains | Required | Required | false |
| isEmpty | Required | Hidden | true |
| isNotEmpty | Required | Hidden | true |
### Example 3: Slack Operation Matrix
**Scenario**: Different Slack operations show different fields
```javascript
// post message
{
"resource": "message",
"operation": "post"
// Shows: channel (required), text (required), attachments, blocks
}
// update message
{
"resource": "message",
"operation": "update"
// Shows: messageId (required), text (required), channel (optional)
}
// delete message
{
"resource": "message",
"operation": "delete"
// Shows: messageId (required), channel (required)
// Hides: text, attachments, blocks
}
// get message
{
"resource": "message",
"operation": "get"
// Shows: messageId (required), channel (required)
// Hides: text, attachments, blocks
}
```
**Field visibility matrix**:
| Field | post | update | delete | get |
|---|---|---|---|---|
| channel | Required | Optional | Required | Required |
| text | Required | Required | Hidden | Hidden |
| messageId | Hidden | Required | Required | Required |
| attachments | Optional | Optional | Hidden | Hidden |
| blocks | Optional | Optional | Hidden | Hidden |
---
## Nested Dependencies
### What Are They?
**Definition**: Dependencies within object properties
**Example**: HTTP Request body.contentType controls body.content structure
```javascript
{
"body": {
"contentType": "json",
// → content expects JSON object
"content": {
"key": "value"
}
}
}
{
"body": {
"contentType": "form-data",
// → content expects form fields array
"content": [
{
"name": "field1",
"value": "value1"
}
]
}
}
```
### How to Handle
**Strategy**: Configure parent first, then children
```javascript
// Step 1: Parent
{
"body": {
"contentType": "json" // Set parent first
}
}
// Step 2: Children (structure determined by parent)
{
"body": {
"contentType": "json",
"content": { // JSON object format
"key": "value"
}
}
}
```
---
## Auto-Sanitization and Dependencies
### What Auto-Sanitization Fixes
**Operator structure issues** (IF/Switch nodes):
**Example**: singleValue property
```javascript
// You configure (missing singleValue)
{
"type": "boolean",
"operation": "isEmpty"
// Missing singleValue
}
// Auto-sanitization adds it
{
"type": "boolean",
"operation": "isEmpty",
"singleValue": true // ✅ Added automatically
}
```
### What It Doesn't Fix
**Missing required fields**:
```javascript
// You configure (missing channel)
{
"resource": "message",
"operation": "post",
"text": "Hello"
// Missing required field: channel
}
// Auto-sanitization does NOT add
// You must add it yourself
{
"resource": "message",
"operation": "post",
"channel": "#general", // ← You must add
"text": "Hello"
}
```
---
## Troubleshooting Dependencies
### Problem 1: "Field X is required but not visible"
**Error**:
```json
{
"type": "missing_required",
"property": "body",
"message": "body is required"
}
```
**But you don't see body field in configuration!**
**Solution**:
```javascript
// Check dependencies
const deps = get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
// Find that body shows when sendBody=true
// Add sendBody
{
"method": "POST",
"sendBody": true, // ← Now body appears!
"body": {...}
}
```
### Problem 2: "Field disappears when I change operation"
**Scenario**:
```javascript
// Working configuration
{
"resource": "message",
"operation": "post",
"channel": "#general",
"text": "Hello"
}
// Change operation
{
"resource": "message",
"operation": "update", // Changed
"channel": "#general", // Still here
"text": "Updated" // Still here
// Missing: messageId (required for update!)
}
```
**Validation error**: "messageId is required"
**Why**: Different operation = different required fields
**Solution**:
```javascript
// Check essentials for new operation
get_node_essentials({
nodeType: "nodes-base.slack"
});
// Configure for update operation
{
"resource": "message",
"operation": "update",
"messageId": "1234567890", // Required for update
"text": "Updated",
"channel": "#general" // Optional for update
}
```
### Problem 3: "Validation passes but field doesn't save"
**Scenario**: Field hidden by dependencies after validation
**Example**:
```javascript
// Configure
{
"method": "GET",
"sendBody": true, // ❌ GET doesn't support body
"body": {...} // This will be stripped
}
// After save
{
"method": "GET"
// body removed because method=GET hides it
}
```
**Solution**: Respect dependencies from the start
```javascript
// Correct approach
get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
// See that body only shows for POST/PUT/PATCH/DELETE
// Use correct method
{
"method": "POST",
"sendBody": true,
"body": {...}
}
```
---
## Advanced Patterns
### Pattern 1: Conditional Required with Fallback
**Example**: Channel can be string OR expression
```javascript
// Option 1: String
{
"channel": "#general"
}
// Option 2: Expression
{
"channel": "={{$json.channelName}}"
}
// Validation accepts both
```
### Pattern 2: Mutually Exclusive Fields
**Example**: Use either ID or name, not both
```javascript
// Use messageId
{
"messageId": "1234567890"
// name not needed
}
// OR use messageName
{
"messageName": "thread-name"
// messageId not needed
}
// Dependencies ensure only one is required
```
### Pattern 3: Progressive Complexity
**Example**: Simple mode vs advanced mode
```javascript
// Simple mode
{
"mode": "simple",
"text": "{{$json.message}}"
// Advanced fields hidden
}
// Advanced mode
{
"mode": "advanced",
"attachments": [...],
"blocks": [...],
"metadata": {...}
// Simple field hidden, advanced fields shown
}
```
---
## Best Practices
### ✅ Do
1. **Check dependencies when stuck**
```javascript
get_property_dependencies({nodeType: "..."});
```
2. **Configure parent properties first**
```javascript
// First: method, resource, operation
// Then: dependent fields
```
3. **Validate after changing operation**
```javascript
// Operation changed → requirements changed
validate_node_operation({...});
```
4. **Read validation errors for dependency hints**
```
Error: "body required when sendBody=true"
→ Hint: Set sendBody=true to enable body
```
### ❌ Don't
1. **Don't ignore dependency errors**
```javascript
// Error: "body not visible" → Check displayOptions
```
2. **Don't hardcode all possible fields**
```javascript
// Bad: Adding fields that will be hidden
```
3. **Don't assume operations are identical**
```javascript
// Each operation has unique requirements
```
---
## Summary
**Key Concepts**:
- `displayOptions` control field visibility
- `show` = field appears when conditions match
- `hide` = field disappears when conditions match
- Multiple conditions = AND logic
- Multiple values = OR logic
**Common Patterns**:
1. Boolean toggle (sendBody → body)
2. Resource/operation cascade (different operations → different fields)
3. Type-specific config (string vs boolean conditions)
4. Method-specific fields (GET vs POST)
**Troubleshooting**:
- Field required but not visible → Check dependencies
- Field disappears after change → Operation changed requirements
- Field doesn't save → Hidden by dependencies
**Tools**:
- `get_property_dependencies` - See dependency rules
- `get_node_essentials` - See operation requirements
- Validation errors - Hints about dependencies
**Related Files**:
- **[SKILL.md](SKILL.md)** - Main configuration guide
- **[OPERATION_PATTERNS.md](OPERATION_PATTERNS.md)** - Common patterns by node type

View File

@@ -0,0 +1,913 @@
# Operation Patterns Guide
Common node configuration patterns organized by node type and operation.
---
## Overview
**Purpose**: Quick reference for common node configurations
**Coverage**: Top 20 most-used nodes from 525 available
**Pattern format**:
- Minimal valid configuration
- Common options
- Real-world examples
- Gotchas and tips
---
## HTTP & API Nodes
### HTTP Request (nodes-base.httpRequest)
Most versatile node for HTTP operations
#### GET Request
**Minimal**:
```javascript
{
"method": "GET",
"url": "https://api.example.com/users",
"authentication": "none"
}
```
**With query parameters**:
```javascript
{
"method": "GET",
"url": "https://api.example.com/users",
"authentication": "none",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "limit",
"value": "100"
},
{
"name": "offset",
"value": "={{$json.offset}}"
}
]
}
}
```
**With authentication**:
```javascript
{
"method": "GET",
"url": "https://api.example.com/users",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth"
}
```
#### POST with JSON
**Minimal**:
```javascript
{
"method": "POST",
"url": "https://api.example.com/users",
"authentication": "none",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"name": "John Doe",
"email": "john@example.com"
}
}
}
```
**With expressions**:
```javascript
{
"method": "POST",
"url": "https://api.example.com/users",
"authentication": "none",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"name": "={{$json.name}}",
"email": "={{$json.email}}",
"metadata": {
"source": "n8n",
"timestamp": "={{$now.toISO()}}"
}
}
}
}
```
**Gotcha**: Remember `sendBody: true` for POST/PUT/PATCH!
#### PUT/PATCH Request
**Pattern**: Same as POST, but method changes
```javascript
{
"method": "PUT", // or "PATCH"
"url": "https://api.example.com/users/123",
"authentication": "none",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"name": "Updated Name"
}
}
}
```
#### DELETE Request
**Minimal** (no body):
```javascript
{
"method": "DELETE",
"url": "https://api.example.com/users/123",
"authentication": "none"
}
```
**With body** (some APIs allow):
```javascript
{
"method": "DELETE",
"url": "https://api.example.com/users",
"authentication": "none",
"sendBody": true,
"body": {
"contentType": "json",
"content": {
"ids": ["123", "456"]
}
}
}
```
---
### Webhook (nodes-base.webhook)
Most common trigger - 813 searches!
#### Basic Webhook
**Minimal**:
```javascript
{
"path": "my-webhook",
"httpMethod": "POST",
"responseMode": "onReceived"
}
```
**Gotcha**: Webhook data is under `$json.body`, not `$json`!
```javascript
// ❌ Wrong
{
"text": "={{$json.email}}"
}
// ✅ Correct
{
"text": "={{$json.body.email}}"
}
```
#### Webhook with Authentication
**Header auth**:
```javascript
{
"path": "secure-webhook",
"httpMethod": "POST",
"responseMode": "onReceived",
"authentication": "headerAuth",
"options": {
"responseCode": 200,
"responseData": "{\n \"success\": true\n}"
}
}
```
#### Webhook Returning Data
**Custom response**:
```javascript
{
"path": "my-webhook",
"httpMethod": "POST",
"responseMode": "lastNode", // Return data from last node
"options": {
"responseCode": 201,
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
}
```
---
## Communication Nodes
### Slack (nodes-base.slack)
Popular choice for AI agent workflows
#### Post Message
**Minimal**:
```javascript
{
"resource": "message",
"operation": "post",
"channel": "#general",
"text": "Hello from n8n!"
}
```
**With dynamic content**:
```javascript
{
"resource": "message",
"operation": "post",
"channel": "={{$json.channel}}",
"text": "New user: {{$json.name}} ({{$json.email}})"
}
```
**With attachments**:
```javascript
{
"resource": "message",
"operation": "post",
"channel": "#alerts",
"text": "Error Alert",
"attachments": [
{
"color": "#ff0000",
"fields": [
{
"title": "Error Type",
"value": "={{$json.errorType}}"
},
{
"title": "Timestamp",
"value": "={{$now.toLocaleString()}}"
}
]
}
]
}
```
**Gotcha**: Channel must start with `#` for public channels or be a channel ID!
#### Update Message
**Minimal**:
```javascript
{
"resource": "message",
"operation": "update",
"messageId": "1234567890.123456", // From previous message post
"text": "Updated message content"
}
```
**Note**: `messageId` required, `channel` optional (can be inferred)
#### Create Channel
**Minimal**:
```javascript
{
"resource": "channel",
"operation": "create",
"name": "new-project-channel", // Lowercase, no spaces
"isPrivate": false
}
```
**Gotcha**: Channel name must be lowercase, no spaces, 1-80 chars!
---
### Gmail (nodes-base.gmail)
Popular for email automation
#### Send Email
**Minimal**:
```javascript
{
"resource": "message",
"operation": "send",
"to": "user@example.com",
"subject": "Hello from n8n",
"message": "This is the email body"
}
```
**With dynamic content**:
```javascript
{
"resource": "message",
"operation": "send",
"to": "={{$json.email}}",
"subject": "Order Confirmation #{{$json.orderId}}",
"message": "Dear {{$json.name}},\n\nYour order has been confirmed.\n\nThank you!",
"options": {
"ccList": "admin@example.com",
"replyTo": "support@example.com"
}
}
```
#### Get Email
**Minimal**:
```javascript
{
"resource": "message",
"operation": "getAll",
"returnAll": false,
"limit": 10
}
```
**With filters**:
```javascript
{
"resource": "message",
"operation": "getAll",
"returnAll": false,
"limit": 50,
"filters": {
"q": "is:unread from:important@example.com",
"labelIds": ["INBOX"]
}
}
```
---
## Database Nodes
### Postgres (nodes-base.postgres)
Database operations - 456 templates
#### Execute Query
**Minimal** (SELECT):
```javascript
{
"operation": "executeQuery",
"query": "SELECT * FROM users WHERE active = true LIMIT 100"
}
```
**With parameters** (SQL injection prevention):
```javascript
{
"operation": "executeQuery",
"query": "SELECT * FROM users WHERE email = $1 AND active = $2",
"additionalFields": {
"mode": "list",
"queryParameters": "user@example.com,true"
}
}
```
**Gotcha**: ALWAYS use parameterized queries for user input!
```javascript
// ❌ BAD - SQL injection risk!
{
"query": "SELECT * FROM users WHERE email = '{{$json.email}}'"
}
// ✅ GOOD - Parameterized
{
"query": "SELECT * FROM users WHERE email = $1",
"additionalFields": {
"mode": "list",
"queryParameters": "={{$json.email}}"
}
}
```
#### Insert
**Minimal**:
```javascript
{
"operation": "insert",
"table": "users",
"columns": "name,email,created_at",
"additionalFields": {
"mode": "list",
"queryParameters": "John Doe,john@example.com,NOW()"
}
}
```
**With expressions**:
```javascript
{
"operation": "insert",
"table": "users",
"columns": "name,email,metadata",
"additionalFields": {
"mode": "list",
"queryParameters": "={{$json.name}},={{$json.email}},{{JSON.stringify($json)}}"
}
}
```
#### Update
**Minimal**:
```javascript
{
"operation": "update",
"table": "users",
"updateKey": "id",
"columns": "name,email",
"additionalFields": {
"mode": "list",
"queryParameters": "={{$json.id}},Updated Name,newemail@example.com"
}
}
```
---
## Data Transformation Nodes
### Set (nodes-base.set)
Most used transformation - 68% of workflows!
#### Set Fixed Values
**Minimal**:
```javascript
{
"mode": "manual",
"duplicateItem": false,
"assignments": {
"assignments": [
{
"name": "status",
"value": "active",
"type": "string"
},
{
"name": "count",
"value": 100,
"type": "number"
}
]
}
}
```
#### Set from Input Data
**Mapping data**:
```javascript
{
"mode": "manual",
"duplicateItem": false,
"assignments": {
"assignments": [
{
"name": "fullName",
"value": "={{$json.firstName}} {{$json.lastName}}",
"type": "string"
},
{
"name": "email",
"value": "={{$json.email.toLowerCase()}}",
"type": "string"
},
{
"name": "timestamp",
"value": "={{$now.toISO()}}",
"type": "string"
}
]
}
}
```
**Gotcha**: Use correct `type` for each field!
```javascript
// ❌ Wrong type
{
"name": "age",
"value": "25", // String
"type": "string" // Will be string "25"
}
// ✅ Correct type
{
"name": "age",
"value": 25, // Number
"type": "number" // Will be number 25
}
```
---
### Code (nodes-base.code)
JavaScript execution - 42% of workflows
#### Simple Transformation
**Minimal**:
```javascript
{
"mode": "runOnceForAllItems",
"jsCode": "return $input.all().map(item => ({\n json: {\n name: item.json.name.toUpperCase(),\n email: item.json.email\n }\n}));"
}
```
**Per-item processing**:
```javascript
{
"mode": "runOnceForEachItem",
"jsCode": "// Process each item\nconst data = $input.item.json;\n\nreturn {\n json: {\n fullName: `${data.firstName} ${data.lastName}`,\n email: data.email.toLowerCase(),\n timestamp: new Date().toISOString()\n }\n};"
}
```
**Gotcha**: In Code nodes, use `$input.item.json` or `$input.all()`, NOT `{{...}}`!
```javascript
// ❌ Wrong - expressions don't work in Code nodes
{
"jsCode": "const name = '={{$json.name}}';"
}
// ✅ Correct - direct access
{
"jsCode": "const name = $input.item.json.name;"
}
```
---
## Conditional Nodes
### IF (nodes-base.if)
Conditional logic - 38% of workflows
#### String Comparison
**Equals** (binary):
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active"
}
]
}
}
```
**Contains** (binary):
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.email}}",
"operation": "contains",
"value2": "@example.com"
}
]
}
}
```
**isEmpty** (unary):
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.email}}",
"operation": "isEmpty"
// No value2 - unary operator
// singleValue: true added by auto-sanitization
}
]
}
}
```
**Gotcha**: Unary operators (isEmpty, isNotEmpty) don't need value2!
#### Number Comparison
**Greater than**:
```javascript
{
"conditions": {
"number": [
{
"value1": "={{$json.age}}",
"operation": "larger",
"value2": 18
}
]
}
}
```
#### Boolean Comparison
**Is true**:
```javascript
{
"conditions": {
"boolean": [
{
"value1": "={{$json.isActive}}",
"operation": "true"
// Unary - no value2
}
]
}
}
```
#### Multiple Conditions (AND)
**All must match**:
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active"
}
],
"number": [
{
"value1": "={{$json.age}}",
"operation": "larger",
"value2": 18
}
]
},
"combineOperation": "all" // AND logic
}
```
#### Multiple Conditions (OR)
**Any can match**:
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active"
},
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "pending"
}
]
},
"combineOperation": "any" // OR logic
}
```
---
### Switch (nodes-base.switch)
Multi-way routing - 18% of workflows
#### Basic Switch
**Minimal**:
```javascript
{
"mode": "rules",
"rules": {
"rules": [
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active"
}
]
}
},
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "pending"
}
]
}
}
]
},
"fallbackOutput": "extra" // Catch-all for non-matching
}
```
**Gotcha**: Number of rules must match number of outputs!
---
## AI Nodes
### OpenAI (nodes-langchain.openAi)
AI operations - 234 templates
#### Chat Completion
**Minimal**:
```javascript
{
"resource": "chat",
"operation": "complete",
"messages": {
"values": [
{
"role": "user",
"content": "={{$json.prompt}}"
}
]
}
}
```
**With system prompt**:
```javascript
{
"resource": "chat",
"operation": "complete",
"messages": {
"values": [
{
"role": "system",
"content": "You are a helpful assistant specialized in customer support."
},
{
"role": "user",
"content": "={{$json.userMessage}}"
}
]
},
"options": {
"temperature": 0.7,
"maxTokens": 500
}
}
```
---
## Schedule Nodes
### Schedule Trigger (nodes-base.scheduleTrigger)
Time-based workflows - 28% have schedule triggers
#### Daily at Specific Time
**Minimal**:
```javascript
{
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
],
"hour": 9,
"minute": 0,
"timezone": "America/New_York"
}
}
```
**Gotcha**: Always set timezone explicitly!
```javascript
// ❌ Bad - uses server timezone
{
"rule": {
"interval": [...]
}
}
// ✅ Good - explicit timezone
{
"rule": {
"interval": [...],
"timezone": "America/New_York"
}
}
```
#### Every N Minutes
**Minimal**:
```javascript
{
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 15
}
]
}
}
```
#### Cron Expression
**Advanced scheduling**:
```javascript
{
"mode": "cron",
"cronExpression": "0 */2 * * *", // Every 2 hours
"timezone": "America/New_York"
}
```
---
## Summary
**Key Patterns by Category**:
| Category | Most Common | Key Gotcha |
|---|---|---|
| HTTP/API | GET, POST JSON | Remember sendBody: true |
| Webhooks | POST receiver | Data under $json.body |
| Communication | Slack post | Channel format (#name) |
| Database | SELECT with params | Use parameterized queries |
| Transform | Set assignments | Correct type per field |
| Conditional | IF string equals | Unary vs binary operators |
| AI | OpenAI chat | System + user messages |
| Schedule | Daily at time | Set timezone explicitly |
**Configuration Approach**:
1. Use patterns as starting point
2. Adapt to your use case
3. Validate configuration
4. Iterate based on errors
5. Deploy when valid
**Related Files**:
- **[SKILL.md](SKILL.md)** - Configuration workflow and philosophy
- **[DEPENDENCIES.md](DEPENDENCIES.md)** - Property dependency rules

View File

@@ -0,0 +1,364 @@
# n8n Node Configuration
Expert guidance for operation-aware node configuration with property dependencies.
## Overview
**Skill Name**: n8n Node Configuration
**Priority**: Medium
**Purpose**: Teach operation-aware configuration with progressive discovery and dependency awareness
## The Problem This Solves
Node configuration patterns:
- get_node_essentials is the primary discovery tool (18s avg from search → essentials)
- 91.7% success rate with essentials-based configuration
- 56 seconds average between configuration edits
**Key insight**: Most configurations only need essentials, not full schema!
## What This Skill Teaches
### Core Concepts
1. **Operation-Aware Configuration**
- Resource + operation determine required fields
- Different operations = different requirements
- Always check requirements when changing operation
2. **Property Dependencies**
- Fields appear/disappear based on other field values
- displayOptions control visibility
- Conditional required fields
- Understanding dependency chains
3. **Progressive Discovery**
- Start with get_node_essentials (91.7% success)
- Escalate to get_property_dependencies if needed
- Use get_node_info only when necessary
- Right tool for right job
4. **Configuration Workflow**
- Identify → Discover → Configure → Validate → Iterate
- Average 2-3 validation cycles
- Read errors for dependency hints
- 56 seconds between edits average
5. **Common Patterns**
- Resource/operation nodes (Slack, Sheets)
- HTTP-based nodes (HTTP Request, Webhook)
- Database nodes (Postgres, MySQL)
- Conditional logic nodes (IF, Switch)
## File Structure
```
n8n-node-configuration/
├── SKILL.md (692 lines)
│ Main configuration guide
│ - Configuration philosophy (progressive disclosure)
│ - Core concepts (operation-aware, dependencies)
│ - Configuration workflow (8-step process)
│ - get_node_essentials vs get_node_info
│ - Property dependencies deep dive
│ - Common node patterns (4 categories)
│ - Operation-specific examples
│ - Conditional requirements
│ - Anti-patterns and best practices
├── DEPENDENCIES.md (671 lines)
│ Property dependencies reference
│ - displayOptions mechanism
│ - show vs hide rules
│ - Multiple conditions (AND logic)
│ - Multiple values (OR logic)
│ - 4 common dependency patterns
│ - Using get_property_dependencies
│ - Complex dependency examples
│ - Nested dependencies
│ - Auto-sanitization interaction
│ - Troubleshooting guide
│ - Advanced patterns
├── OPERATION_PATTERNS.md (783 lines)
│ Common configurations by node type
│ - HTTP Request (GET/POST/PUT/DELETE)
│ - Webhook (basic/auth/response)
│ - Slack (post/update/create)
│ - Gmail (send/get)
│ - Postgres (query/insert/update)
│ - Set (values/mapping)
│ - Code (per-item/all-items)
│ - IF (string/number/boolean)
│ - Switch (rules/fallback)
│ - OpenAI (chat completion)
│ - Schedule (daily/interval/cron)
│ - Gotchas and tips for each
└── README.md (this file)
Skill metadata and statistics
```
**Total**: ~2,146 lines across 4 files + 4 evaluations
## Usage Statistics
Configuration metrics:
| Metric | Value | Insight |
|---|---|---|
| get_node_essentials | Primary tool | Most popular discovery pattern |
| Success rate (essentials) | 91.7% | Essentials sufficient for most |
| Avg time search→essentials | 18 seconds | Fast discovery workflow |
| Avg time between edits | 56 seconds | Iterative configuration |
## Tool Usage Pattern
**Most common discovery pattern**:
```
search_nodes → get_node_essentials (18s average)
```
**Configuration cycle**:
```
get_node_essentials → configure → validate → iterate (56s avg per edit)
```
## Key Insights
### 1. Progressive Disclosure Works
**91.7% success rate** with get_node_essentials proves most configurations don't need full schema.
**Strategy**:
1. Start with essentials
2. Escalate to dependencies if stuck
3. Use full schema only when necessary
### 2. Operations Determine Requirements
**Same node, different operation = different requirements**
Example: Slack message
- `operation="post"` → needs channel + text
- `operation="update"` → needs messageId + text (different!)
### 3. Dependencies Control Visibility
**Fields appear/disappear based on other values**
Example: HTTP Request
- `method="GET"` → body hidden
- `method="POST"` + `sendBody=true` → body required
### 4. Configuration is Iterative
**Average 56 seconds between edits** shows configuration is iterative, not one-shot.
**Normal workflow**:
1. Configure minimal
2. Validate → error
3. Add missing field
4. Validate → error
5. Adjust value
6. Validate → valid ✅
### 5. Common Gotchas Exist
**Top 5 gotchas** from patterns:
1. Webhook data under `$json.body` (not `$json`)
2. POST needs `sendBody: true`
3. Slack channel format (`#name`)
4. SQL parameterized queries (injection prevention)
5. Timezone must be explicit (schedule nodes)
## Usage Examples
### Example 1: Basic Configuration Flow
```javascript
// Step 1: Get essentials
const info = get_node_essentials({
nodeType: "nodes-base.slack"
});
// Step 2: Configure for operation
{
"resource": "message",
"operation": "post",
"channel": "#general",
"text": "Hello!"
}
// Step 3: Validate
validate_node_operation({...});
// ✅ Valid!
```
### Example 2: Handling Dependencies
```javascript
// Step 1: Configure HTTP POST
{
"method": "POST",
"url": "https://api.example.com/create"
}
// Step 2: Validate → Error: "sendBody required"
// Step 3: Check dependencies
get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
// Shows: body visible when sendBody=true
// Step 4: Fix
{
"method": "POST",
"url": "https://api.example.com/create",
"sendBody": true,
"body": {
"contentType": "json",
"content": {...}
}
}
// ✅ Valid!
```
### Example 3: Operation Change
```javascript
// Initial config (post operation)
{
"resource": "message",
"operation": "post",
"channel": "#general",
"text": "Hello"
}
// Change operation
{
"resource": "message",
"operation": "update", // Changed!
// Need to check new requirements
}
// Get essentials for update operation
get_node_essentials({nodeType: "nodes-base.slack"});
// Shows: messageId required, channel optional
// Correct config
{
"resource": "message",
"operation": "update",
"messageId": "1234567890.123456",
"text": "Updated"
}
```
## When This Skill Activates
**Trigger phrases**:
- "how to configure"
- "what fields are required"
- "property dependencies"
- "get_node_essentials vs get_node_info"
- "operation-specific"
- "field not visible"
**Common scenarios**:
- Configuring new nodes
- Understanding required fields
- Field appears/disappears unexpectedly
- Choosing between discovery tools
- Switching operations
- Learning common patterns
## Integration with Other Skills
### Works With:
- **n8n MCP Tools Expert** - How to call discovery tools correctly
- **n8n Validation Expert** - Interpret missing_required errors
- **n8n Expression Syntax** - Configure expression fields
- **n8n Workflow Patterns** - Apply patterns with proper node config
### Complementary:
- Use MCP Tools Expert to learn tool selection
- Use Validation Expert to fix configuration errors
- Use Expression Syntax for dynamic field values
- Use Workflow Patterns to understand node relationships
## Testing
**Evaluations**: 4 test scenarios
1. **eval-001-property-dependencies.json**
- Tests understanding of displayOptions
- Guides to get_property_dependencies
- Explains conditional requirements
2. **eval-002-operation-specific-config.json**
- Tests operation-aware configuration
- Identifies resource + operation pattern
- References OPERATION_PATTERNS.md
3. **eval-003-conditional-fields.json**
- Tests unary vs binary operators
- Explains singleValue dependency
- Mentions auto-sanitization
4. **eval-004-essentials-vs-info.json**
- Tests tool selection knowledge
- Explains progressive disclosure
- Provides success rate statistics
## Success Metrics
**Before this skill**:
- Using get_node_info for everything (slow, overwhelming)
- Not understanding property dependencies
- Confused when fields appear/disappear
- Not aware of operation-specific requirements
- Trial and error configuration
**After this skill**:
- Start with get_node_essentials (91.7% success)
- Understand displayOptions mechanism
- Predict field visibility based on dependencies
- Check requirements when changing operations
- Systematic configuration approach
- Know common patterns by node type
## Coverage
**Node types covered**: Top 20 most-used nodes
| Category | Nodes | Coverage |
|---|---|---|
| HTTP/API | HTTP Request, Webhook | Complete |
| Communication | Slack, Gmail | Common operations |
| Database | Postgres, MySQL | CRUD operations |
| Transform | Set, Code | All modes |
| Conditional | IF, Switch | All operator types |
| AI | OpenAI | Chat completion |
| Schedule | Schedule Trigger | All modes |
## Related Documentation
- **n8n-mcp MCP Server**: Provides discovery tools
- **n8n Node API**: get_node_essentials, get_property_dependencies, get_node_info
- **n8n Schema**: displayOptions mechanism, property definitions
## Version History
- **v1.0** (2025-10-20): Initial implementation
- SKILL.md with configuration workflow
- DEPENDENCIES.md with displayOptions deep dive
- OPERATION_PATTERNS.md with 20+ node patterns
- 4 evaluation scenarios
## Author
Conceived by Romuald Członkowski - [www.aiadvisors.pl/en](https://www.aiadvisors.pl/en)
Part of the n8n-skills meta-skill collection.

View File

@@ -0,0 +1,774 @@
---
name: n8n-node-configuration
description: Operation-aware node configuration guidance. Use when configuring nodes, understanding property dependencies, determining required fields, choosing between get_node_essentials and get_node_info, or learning common configuration patterns by node type.
---
# 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_essentials is the most used discovery pattern
- 56 seconds average between configuration edits
- 91.7% success rate with essentials-based configuration
**Key insight**: Most configurations need only essentials, not full schema!
---
## Core Concepts
### 1. Operation-Aware Configuration
**Not all fields are always required** - it depends on operation!
**Example**: Slack node
```javascript
// 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
```javascript
// 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 tool for the right job**:
1. **get_node_essentials** (91.7% success rate)
- Quick overview
- Required fields
- Common options
- **Use first** - covers 90% of needs
2. **get_property_dependencies** (for complex nodes)
- Shows what fields depend on others
- Reveals conditional requirements
- Use when essentials isn't enough
3. **get_node_info** (full schema)
- Complete documentation
- All possible fields
- Use when essentials + dependencies insufficient
---
## Configuration Workflow
### Standard Process
```
1. Identify node type and operation
2. Use get_node_essentials
3. Configure required fields
4. Validate configuration
5. If dependencies unclear → get_property_dependencies
6. Add optional fields as needed
7. Validate again
8. Deploy
```
### Example: Configuring HTTP Request
**Step 1**: Identify what you need
```javascript
// Goal: POST JSON to API
```
**Step 2**: Get essentials
```javascript
const info = get_node_essentials({
nodeType: "nodes-base.httpRequest"
});
// Returns: method, url, sendBody, body, authentication required/optional
```
**Step 3**: Minimal config
```javascript
{
"method": "POST",
"url": "https://api.example.com/create",
"authentication": "none"
}
```
**Step 4**: Validate
```javascript
validate_node_operation({
nodeType: "nodes-base.httpRequest",
config,
profile: "runtime"
});
// → Error: "sendBody required for POST"
```
**Step 5**: Add required field
```javascript
{
"method": "POST",
"url": "https://api.example.com/create",
"authentication": "none",
"sendBody": true
}
```
**Step 6**: Validate again
```javascript
validate_node_operation({...});
// → Error: "body required when sendBody=true"
```
**Step 7**: Complete configuration
```javascript
{
"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
```javascript
validate_node_operation({...});
// → Valid! ✅
```
---
## get_node_essentials vs get_node_info
### Use get_node_essentials When:
**✅ Starting configuration** (91.7% success rate)
```javascript
get_node_essentials({
nodeType: "nodes-base.slack"
});
```
**Returns**:
- Required fields
- Common options
- Basic examples
- Operation list
**Fast**: ~18 seconds average (from search → essentials)
### Use get_node_info When:
**✅ Essentials insufficient**
```javascript
get_node_info({
nodeType: "nodes-base.slack"
});
```
**Returns**:
- Full schema
- All properties
- Complete documentation
- Advanced options
**Slower**: More data to process
### Decision Tree
```
┌─────────────────────────────────┐
│ Starting new node config? │
├─────────────────────────────────┤
│ YES → get_node_essentials │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ Essentials has what you need? │
├─────────────────────────────────┤
│ YES → Configure with essentials │
│ NO → Continue │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ Need dependency info? │
├─────────────────────────────────┤
│ YES → get_property_dependencies │
│ NO → Continue │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ Still need more details? │
├─────────────────────────────────┤
│ YES → get_node_info │
└─────────────────────────────────┘
```
---
## Property Dependencies Deep Dive
### displayOptions Mechanism
**Fields have visibility rules**:
```javascript
{
"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
```javascript
// sendBody controls body visibility
{
"sendBody": true // → body field appears
}
```
#### Pattern 2: Operation Switch
**Example**: Slack resource/operation
```javascript
// 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
```javascript
{
"type": "string",
"operation": "contains"
// → Shows: value1, value2
}
{
"type": "boolean",
"operation": "equals"
// → Shows: value1, value2, different operators
}
```
### Using get_property_dependencies
**Example**:
```javascript
const deps = get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
// Returns dependency tree
{
"dependencies": {
"body": {
"shows_when": {
"sendBody": [true],
"method": ["POST", "PUT", "PATCH", "DELETE"]
}
},
"queryParameters": {
"shows_when": {
"sendQuery": [true]
}
}
}
}
```
**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**:
```javascript
{
"resource": "<entity>", // What type of thing
"operation": "<action>", // What to do with it
// ... operation-specific fields
}
```
**How to configure**:
1. Choose resource
2. Choose operation
3. Use get_node_essentials to see operation-specific requirements
4. Configure required fields
### Pattern 2: HTTP-Based Nodes
**Examples**: HTTP Request, Webhook
**Structure**:
```javascript
{
"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**:
```javascript
{
"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**:
```javascript
{
"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
```javascript
{
"resource": "message",
"operation": "post",
"channel": "#general", // Required
"text": "Hello!", // Required
"attachments": [], // Optional
"blocks": [] // Optional
}
```
#### Update Message
```javascript
{
"resource": "message",
"operation": "update",
"messageId": "1234567890", // Required (different from post!)
"text": "Updated!", // Required
"channel": "#general" // Optional (can be inferred)
}
```
#### Create Channel
```javascript
{
"resource": "channel",
"operation": "create",
"name": "new-channel", // Required
"isPrivate": false // Optional
// Note: text NOT required for this operation
}
```
### HTTP Request Node Examples
#### GET Request
```javascript
{
"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
```javascript
{
"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)
```javascript
{
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "equals",
"value2": "active" // Binary: needs value2
}
]
}
}
```
#### Empty Check (Unary)
```javascript
{
"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**:
```javascript
// Option 1: Read validation error
validate_node_operation({...});
// Error: "body required when sendBody=true"
// Option 2: Check dependencies
get_property_dependencies({
nodeType: "nodes-base.httpRequest"
});
// Shows: body → shows_when: sendBody=[true], method=[POST,PUT,PATCH,DELETE]
// 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**:
```javascript
get_property_dependencies({
nodeType: "nodes-base.if"
});
// Shows operator-specific dependencies
```
---
## Configuration Anti-Patterns
### ❌ Don't: Over-configure Upfront
**Bad**:
```javascript
// Adding every possible field
{
"method": "GET",
"url": "...",
"sendQuery": false,
"sendHeaders": false,
"sendBody": false,
"timeout": 10000,
"ignoreResponseCode": false,
// ... 20 more optional fields
}
```
**Good**:
```javascript
// Start minimal
{
"method": "GET",
"url": "...",
"authentication": "none"
}
// Add fields only when needed
```
### ❌ Don't: Skip Validation
**Bad**:
```javascript
// Configure and deploy without validating
const config = {...};
n8n_update_partial_workflow({...}); // YOLO
```
**Good**:
```javascript
// Validate before deploying
const config = {...};
const result = validate_node_operation({...});
if (result.valid) {
n8n_update_partial_workflow({...});
}
```
### ❌ Don't: Ignore Operation Context
**Bad**:
```javascript
// 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**:
```javascript
// Check requirements when changing operation
get_node_essentials({
nodeType: "nodes-base.slack"
});
// See what update operation needs (messageId, not channel)
```
---
## Best Practices
### ✅ Do
1. **Start with get_node_essentials**
- 91.7% success rate
- Faster than get_node_info
- Sufficient for most needs
2. **Validate iteratively**
- Configure → Validate → Fix → Repeat
- Average 2-3 iterations is normal
- Read validation errors carefully
3. **Use property dependencies when stuck**
- If field seems missing, check dependencies
- Understand what controls field visibility
- get_property_dependencies reveals rules
4. **Respect operation context**
- Different operations = different requirements
- Always check essentials when changing operation
- Don't assume configs are transferable
5. **Trust auto-sanitization**
- Operator structure fixed automatically
- Don't manually add/remove singleValue
- IF/Switch metadata added on save
### ❌ Don't
1. **Jump to get_node_info immediately**
- Try essentials first
- Only escalate if needed
- Full schema is overwhelming
2. **Configure blindly**
- Always validate before deploying
- Understand why fields are required
- Check dependencies for conditional fields
3. **Copy configs without understanding**
- Different operations need different fields
- Validate after copying
- Adjust for new context
4. **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](DEPENDENCIES.md)** - Deep dive into property dependencies and displayOptions
- **[OPERATION_PATTERNS.md](OPERATION_PATTERNS.md)** - Common configuration patterns by node type
---
## Summary
**Configuration Strategy**:
1. Start with get_node_essentials (91.7% success)
2. Configure required fields for operation
3. Validate configuration
4. Check dependencies if stuck
5. Iterate until valid (avg 2-3 cycles)
6. 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