Initial commit
This commit is contained in:
800
skills/n8n-node-configuration/DEPENDENCIES.md
Normal file
800
skills/n8n-node-configuration/DEPENDENCIES.md
Normal 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
|
||||
913
skills/n8n-node-configuration/OPERATION_PATTERNS.md
Normal file
913
skills/n8n-node-configuration/OPERATION_PATTERNS.md
Normal 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
|
||||
364
skills/n8n-node-configuration/README.md
Normal file
364
skills/n8n-node-configuration/README.md
Normal 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.
|
||||
774
skills/n8n-node-configuration/SKILL.md
Normal file
774
skills/n8n-node-configuration/SKILL.md
Normal 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
|
||||
Reference in New Issue
Block a user